win_drv.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /**
  2. * @file win_drv.c
  3. *
  4. */
  5. /*********************
  6. * INCLUDES
  7. *********************/
  8. #include "win_drv.h"
  9. #if USE_WINDOWS
  10. #include <windows.h>
  11. #include <windowsx.h>
  12. #include "lvgl.h"
  13. #if LV_COLOR_DEPTH < 16
  14. #error Windows driver only supports true RGB colors at this time
  15. #endif
  16. /**********************
  17. * DEFINES
  18. **********************/
  19. #define WINDOW_STYLE (WS_OVERLAPPEDWINDOW & ~(WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME))
  20. /**********************
  21. * TYPEDEFS
  22. **********************/
  23. /**********************
  24. * STATIC PROTOTYPES
  25. **********************/
  26. static void do_register(void);
  27. static void win_drv_flush(lv_disp_t *drv, lv_area_t *area, const lv_color_t * color_p);
  28. static void win_drv_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color_t color);
  29. static void win_drv_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p);
  30. static bool win_drv_read(lv_indev_t *drv, lv_indev_data_t * data);
  31. static void msg_handler(void *param);
  32. static COLORREF lv_color_to_colorref(const lv_color_t color);
  33. static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  34. /**********************
  35. * GLOBAL VARIABLES
  36. **********************/
  37. bool lv_win_exit_flag = false;
  38. lv_disp_t *lv_windows_disp;
  39. uint32_t WINDOW_HOR_RES = LV_HOR_RES_MAX;
  40. uint32_t WINDOW_VER_RES = LV_VER_RES_MAX;
  41. /**********************
  42. * STATIC VARIABLES
  43. **********************/
  44. static HWND hwnd;
  45. static uint32_t *fbp = NULL; /* Raw framebuffer memory */
  46. static bool mouse_pressed;
  47. static int mouse_x, mouse_y;
  48. /**********************
  49. * MACROS
  50. **********************/
  51. /**********************
  52. * GLOBAL FUNCTIONS
  53. **********************/
  54. const char g_szClassName[] = "LittlevGL";
  55. HWND windrv_init(void)
  56. {
  57. WNDCLASSEX wc;
  58. RECT winrect;
  59. HICON lvgl_icon;
  60. //Step 1: Registering the Window Class
  61. wc.cbSize = sizeof(WNDCLASSEX);
  62. wc.style = 0;
  63. wc.lpfnWndProc = WndProc;
  64. wc.cbClsExtra = 0;
  65. wc.cbWndExtra = 0;
  66. wc.hInstance = GetModuleHandle(NULL);
  67. lvgl_icon = (HICON) LoadImage( NULL, "lvgl_icon.bmp", IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
  68. if(lvgl_icon == NULL)
  69. lvgl_icon = LoadIcon(NULL, IDI_APPLICATION);
  70. wc.hIcon = lvgl_icon;
  71. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  72. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  73. wc.lpszMenuName = NULL;
  74. wc.lpszClassName = g_szClassName;
  75. wc.hIconSm = lvgl_icon;
  76. if(!RegisterClassEx(&wc))
  77. {
  78. return NULL;
  79. }
  80. winrect.left = 0;
  81. winrect.right = WINDOW_HOR_RES - 1;
  82. winrect.top = 0;
  83. winrect.bottom = WINDOW_VER_RES - 1;
  84. AdjustWindowRectEx(&winrect, WINDOW_STYLE, FALSE, WS_EX_CLIENTEDGE);
  85. OffsetRect(&winrect, -winrect.left, -winrect.top);
  86. // Step 2: Creating the Window
  87. hwnd = CreateWindowEx(
  88. WS_EX_CLIENTEDGE,
  89. g_szClassName,
  90. "LittlevGL@LuatOS",
  91. WINDOW_STYLE,
  92. CW_USEDEFAULT, CW_USEDEFAULT, winrect.right, winrect.bottom,
  93. NULL, NULL, GetModuleHandle(NULL), NULL);
  94. if(hwnd == NULL)
  95. {
  96. return NULL;
  97. }
  98. ShowWindow(hwnd, SW_SHOWDEFAULT);
  99. UpdateWindow(hwnd);
  100. lv_task_create(msg_handler, 0, LV_TASK_PRIO_HIGHEST, NULL);
  101. lv_win_exit_flag = false;
  102. do_register();
  103. }
  104. /**********************
  105. * STATIC FUNCTIONS
  106. **********************/
  107. static void do_register(void)
  108. {
  109. /*-----------------------------
  110. * Create a buffer for drawing
  111. *----------------------------*/
  112. /* LittlevGL requires a buffer where it draw the objects. The buffer's has to be greater than 1 display row
  113. *
  114. * There are three buffering configurations:
  115. * 1. Create ONE buffer some rows: LittlevGL will draw the display's content here and writes it to your display
  116. * 2. Create TWO buffer some rows: LittlevGL will draw the display's content to a buffer and writes it your display.
  117. * You should use DMA to write the buffer's content to the display.
  118. * It will enable LittlevGL to draw the next part of the screen to the other buffer while
  119. * the data is being sent form the first buffer. It makes rendering and flushing parallel.
  120. * 3. Create TWO screen buffer: Similar to 2) but the buffer have to be screen sized. When LittlevGL is ready it will give the
  121. * whole frame to display. This way you only need to change the frame buffer's address instead of
  122. * copying the pixels.
  123. * */
  124. /* Example for 1) */
  125. static lv_disp_buf_t disp_buf_1;
  126. static lv_color_t buf1_1[LV_HOR_RES_MAX * LV_VER_RES_MAX]; /*A buffer for 1080p*/
  127. lv_disp_buf_init(&disp_buf_1, buf1_1, NULL, WINDOW_HOR_RES * WINDOW_VER_RES); /*Initialize the display buffer*/
  128. /*-----------------------------------
  129. * Register the display in LittlevGL
  130. *----------------------------------*/
  131. lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
  132. lv_disp_drv_init(&disp_drv); /*Basic initialization*/
  133. /*Set up the functions to access to your display*/
  134. /*Set the resolution of the display*/
  135. disp_drv.hor_res = WINDOW_HOR_RES;
  136. disp_drv.ver_res = WINDOW_VER_RES;
  137. /*Used to copy the buffer's content to the display*/
  138. disp_drv.flush_cb = win_drv_flush;
  139. /*Set a display buffer*/
  140. disp_drv.buffer = &disp_buf_1;
  141. /*Finally register the driver*/
  142. lv_windows_disp = lv_disp_drv_register(&disp_drv);
  143. lv_indev_drv_t indev_drv;
  144. lv_indev_drv_init(&indev_drv);
  145. indev_drv.type = LV_INDEV_TYPE_POINTER;
  146. indev_drv.read_cb = win_drv_read;
  147. lv_indev_drv_register(&indev_drv);
  148. }
  149. static void msg_handler(void *param)
  150. {
  151. (void)param;
  152. MSG msg;
  153. BOOL bRet;
  154. if( (bRet = PeekMessage( &msg, NULL, 0, 0, TRUE )) != 0)
  155. {
  156. if (bRet == -1)
  157. {
  158. return;
  159. }
  160. else
  161. {
  162. TranslateMessage(&msg);
  163. DispatchMessage(&msg);
  164. }
  165. if(msg.message == WM_QUIT)
  166. lv_win_exit_flag = true;
  167. }
  168. }
  169. static bool win_drv_read(lv_indev_t *drv, lv_indev_data_t * data)
  170. {
  171. data->state = mouse_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
  172. data->point.x = mouse_x;
  173. data->point.y = mouse_y;
  174. return false;
  175. }
  176. static void on_paint(void)
  177. {
  178. HBITMAP bmp = CreateBitmap(WINDOW_HOR_RES, WINDOW_VER_RES, 1, 32, fbp);
  179. PAINTSTRUCT ps;
  180. HDC hdc = BeginPaint(hwnd, &ps);
  181. HDC hdcMem = CreateCompatibleDC(hdc);
  182. HBITMAP hbmOld = SelectObject(hdcMem, bmp);
  183. BitBlt(hdc, 0, 0, WINDOW_HOR_RES, WINDOW_VER_RES, hdcMem, 0, 0, SRCCOPY);
  184. SelectObject(hdcMem, hbmOld);
  185. DeleteDC(hdcMem);
  186. EndPaint(hwnd, &ps);
  187. DeleteObject(bmp);
  188. }
  189. /**
  190. * Flush a buffer to the marked area
  191. * @param x1 left coordinate
  192. * @param y1 top coordinate
  193. * @param x2 right coordinate
  194. * @param y2 bottom coordinate
  195. * @param color_p an array of colors
  196. */
  197. static void win_drv_flush(lv_disp_t *drv, lv_area_t *area, const lv_color_t * color_p)
  198. {
  199. if (lv_win_exit_flag)
  200. return;
  201. win_drv_map(area->x1, area->y1, area->x2, area->y2, color_p);
  202. lv_disp_flush_ready(drv);
  203. }
  204. /**
  205. * Put a color map to the marked area
  206. * @param x1 left coordinate
  207. * @param y1 top coordinate
  208. * @param x2 right coordinate
  209. * @param y2 bottom coordinate
  210. * @param color_p an array of colors
  211. */
  212. static void win_drv_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p)
  213. {
  214. for(int y = y1; y <= y2; y++)
  215. {
  216. for(int x = x1; x <= x2; x++)
  217. {
  218. fbp[y*WINDOW_HOR_RES+x] = lv_color_to32(*color_p);
  219. color_p++;
  220. }
  221. }
  222. InvalidateRect(hwnd, NULL, FALSE);
  223. UpdateWindow(hwnd);
  224. }
  225. static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  226. {
  227. HDC hdc;
  228. PAINTSTRUCT ps;
  229. switch(msg) {
  230. case WM_CREATE:
  231. fbp = malloc(4*WINDOW_HOR_RES*WINDOW_VER_RES);
  232. if(fbp == NULL)
  233. return 1;
  234. SetTimer(hwnd, 0, 10, (TIMERPROC)lv_task_handler);
  235. SetTimer(hwnd, 1, 25, NULL);
  236. return 0;
  237. case WM_MOUSEMOVE:
  238. case WM_LBUTTONDOWN:
  239. case WM_LBUTTONUP:
  240. mouse_x = GET_X_LPARAM(lParam);
  241. mouse_y = GET_Y_LPARAM(lParam);
  242. if(msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP) {
  243. mouse_pressed = (msg == WM_LBUTTONDOWN);
  244. }
  245. return 0;
  246. case WM_CLOSE:
  247. free(fbp);
  248. fbp = NULL;
  249. DestroyWindow(hwnd);
  250. return 0;
  251. case WM_PAINT:
  252. on_paint();
  253. return 0;
  254. case WM_TIMER:
  255. lv_tick_inc(25);
  256. return 0;
  257. case WM_DESTROY:
  258. PostQuitMessage(0);
  259. return 0;
  260. default:
  261. break;
  262. }
  263. return DefWindowProc(hwnd, msg, wParam, lParam);
  264. }
  265. static COLORREF lv_color_to_colorref(const lv_color_t color)
  266. {
  267. uint32_t raw_color = lv_color_to32(color);
  268. lv_color32_t tmp;
  269. tmp.full = raw_color;
  270. uint32_t colorref = RGB(tmp.ch.red, tmp.ch.green, tmp.ch.blue);
  271. return colorref;
  272. }
  273. #endif