sdl_fb.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. #include <rtthread.h>
  2. #ifdef _WIN32
  3. #include <sdl.h>
  4. #else
  5. #include <SDL/SDL.h>
  6. #endif
  7. #include <rtdevice.h>
  8. #include <rtgui/driver.h>
  9. #define SDL_SCREEN_WIDTH 800
  10. #define SDL_SCREEN_HEIGHT 480
  11. struct sdlfb_device
  12. {
  13. struct rt_device parent;
  14. SDL_Surface *screen;
  15. rt_uint16_t width;
  16. rt_uint16_t height;
  17. };
  18. struct sdlfb_device _device;
  19. /* common device interface */
  20. static rt_err_t sdlfb_init(rt_device_t dev)
  21. {
  22. return RT_EOK;
  23. }
  24. static rt_err_t sdlfb_open(rt_device_t dev, rt_uint16_t oflag)
  25. {
  26. return RT_EOK;
  27. }
  28. static rt_err_t sdlfb_close(rt_device_t dev)
  29. {
  30. SDL_Quit();
  31. return RT_EOK;
  32. }
  33. static rt_mutex_t sdllock;
  34. static rt_err_t sdlfb_control(rt_device_t dev, rt_uint8_t cmd, void *args)
  35. {
  36. struct sdlfb_device *device;
  37. rt_mutex_take(sdllock, RT_WAITING_FOREVER);
  38. device = (struct sdlfb_device *)dev;
  39. RT_ASSERT(device != RT_NULL);
  40. RT_ASSERT(device->screen != RT_NULL);
  41. switch (cmd)
  42. {
  43. case RTGRAPHIC_CTRL_GET_INFO:
  44. {
  45. struct rt_device_graphic_info *info;
  46. info = (struct rt_device_graphic_info *) args;
  47. info->bits_per_pixel = 16;
  48. info->pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565P;
  49. info->framebuffer = device->screen->pixels;
  50. info->width = device->screen->w;
  51. info->height = device->screen->h;
  52. }
  53. break;
  54. case RTGRAPHIC_CTRL_RECT_UPDATE:
  55. {
  56. struct rt_device_rect_info *rect;
  57. rect = (struct rt_device_rect_info *)args;
  58. /* SDL_UpdateRect(_device.screen, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h); */
  59. SDL_UpdateRect(_device.screen, 0, 0, device->width, device->height);
  60. }
  61. break;
  62. case RTGRAPHIC_CTRL_SET_MODE:
  63. {
  64. #if 0
  65. struct rt_device_rect_info *rect;
  66. rect = (struct rt_device_rect_info *)args;
  67. if ((_device.width == rect->width) && (_device.height == rect->height)) return -RT_ERROR;
  68. _device.width = rect->width;
  69. _device.height = rect->height;
  70. if (_device.screen != RT_NULL)
  71. {
  72. SDL_FreeSurface(_device.screen);
  73. /* re-create screen surface */
  74. _device.screen = SDL_SetVideoMode(_device.width, _device.height, 16, SDL_SWSURFACE | SDL_DOUBLEBUF);
  75. if (_device.screen == NULL)
  76. {
  77. fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
  78. exit(1);
  79. }
  80. SDL_WM_SetCaption("RT-Thread/GUI Simulator", NULL);
  81. }
  82. #endif
  83. }
  84. break;
  85. }
  86. rt_mutex_release(sdllock);
  87. return RT_EOK;
  88. }
  89. static void sdlfb_hw_init(void)
  90. {
  91. /* set video driver for VC++ debug */
  92. //_putenv("SDL_VIDEODRIVER=windib");
  93. //if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO) < 0)
  94. if (SDL_Init(SDL_INIT_VIDEO) < 0)
  95. {
  96. fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
  97. exit(1);
  98. }
  99. _device.parent.init = sdlfb_init;
  100. _device.parent.open = sdlfb_open;
  101. _device.parent.close = sdlfb_close;
  102. _device.parent.read = RT_NULL;
  103. _device.parent.write = RT_NULL;
  104. _device.parent.control = sdlfb_control;
  105. _device.width = SDL_SCREEN_WIDTH;
  106. _device.height = SDL_SCREEN_HEIGHT;
  107. _device.screen = SDL_SetVideoMode(_device.width, _device.height, 16, SDL_SWSURFACE | SDL_DOUBLEBUF);
  108. if (_device.screen == NULL)
  109. {
  110. fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
  111. exit(1);
  112. }
  113. SDL_WM_SetCaption("RT-Thread/GUI Simulator", NULL);
  114. rt_device_register(RT_DEVICE(&_device), "sdl", RT_DEVICE_FLAG_RDWR);
  115. sdllock = rt_mutex_create("fb", RT_IPC_FLAG_FIFO);
  116. }
  117. #ifdef _WIN32
  118. #include <windows.h>
  119. #include <mmsystem.h>
  120. #else
  121. #include <pthread.h>
  122. #include <signal.h>
  123. #endif
  124. #include <stdio.h>
  125. #include <rtgui/event.h>
  126. #include <rtgui/kbddef.h>
  127. #include <rtgui/rtgui_server.h>
  128. #include <rtgui/rtgui_system.h>
  129. #ifdef _WIN32
  130. static HANDLE sdl_ok_event = NULL;
  131. static DWORD WINAPI sdl_loop(LPVOID lpParam)
  132. #else
  133. static pthread_mutex_t sdl_ok_mutex;
  134. static pthread_cond_t sdl_ok_event;
  135. static void *sdl_loop(void *lpParam)
  136. #endif
  137. {
  138. int quit = 0;
  139. SDL_Event event;
  140. int button_state = 0;
  141. rt_device_t device;
  142. #ifndef _WIN32
  143. sigset_t sigmask, oldmask;
  144. /* set the getchar without buffer */
  145. sigfillset(&sigmask);
  146. pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
  147. pthread_mutex_lock(&sdl_ok_mutex);
  148. #endif
  149. sdlfb_hw_init();
  150. device = rt_device_find("sdl");
  151. RT_ASSERT(device);
  152. rtgui_graphic_set_device(device);
  153. #ifdef _WIN32
  154. SetEvent(sdl_ok_event);
  155. #else
  156. pthread_cond_signal(&sdl_ok_event);
  157. pthread_mutex_unlock(&sdl_ok_mutex);
  158. #endif
  159. /* handle SDL event */
  160. while (!quit)
  161. {
  162. SDL_WaitEvent(&event);
  163. switch (event.type)
  164. {
  165. case SDL_MOUSEMOTION:
  166. {
  167. struct rtgui_event_mouse emouse;
  168. emouse.parent.type = RTGUI_EVENT_MOUSE_MOTION;
  169. emouse.parent.sender = RT_NULL;
  170. emouse.wid = RT_NULL;
  171. emouse.x = ((SDL_MouseMotionEvent *)&event)->x;
  172. emouse.y = ((SDL_MouseMotionEvent *)&event)->y;
  173. /* init mouse button */
  174. emouse.button = button_state;
  175. /* send event to server */
  176. rtgui_server_post_event(&emouse.parent, sizeof(struct rtgui_event_mouse));
  177. }
  178. break;
  179. case SDL_MOUSEBUTTONDOWN:
  180. case SDL_MOUSEBUTTONUP:
  181. {
  182. struct rtgui_event_mouse emouse;
  183. SDL_MouseButtonEvent *mb;
  184. emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
  185. emouse.parent.sender = RT_NULL;
  186. emouse.wid = RT_NULL;
  187. mb = (SDL_MouseButtonEvent *)&event;
  188. emouse.x = mb->x;
  189. emouse.y = mb->y;
  190. /* init mouse button */
  191. emouse.button = 0;
  192. /* set emouse button */
  193. if (mb->button & (1 << (SDL_BUTTON_LEFT - 1)))
  194. {
  195. emouse.button |= RTGUI_MOUSE_BUTTON_LEFT;
  196. }
  197. else if (mb->button & (1 << (SDL_BUTTON_RIGHT - 1)))
  198. {
  199. emouse.button |= RTGUI_MOUSE_BUTTON_RIGHT;
  200. }
  201. else if (mb->button & (1 << (SDL_BUTTON_MIDDLE - 1)))
  202. {
  203. emouse.button |= RTGUI_MOUSE_BUTTON_MIDDLE;
  204. }
  205. if (mb->type == SDL_MOUSEBUTTONDOWN)
  206. {
  207. emouse.button |= RTGUI_MOUSE_BUTTON_DOWN;
  208. button_state = emouse.button;
  209. }
  210. else
  211. {
  212. emouse.button |= RTGUI_MOUSE_BUTTON_UP;
  213. button_state = 0;
  214. }
  215. /* send event to server */
  216. rtgui_server_post_event(&emouse.parent, sizeof(struct rtgui_event_mouse));
  217. }
  218. break;
  219. case SDL_KEYUP:
  220. {
  221. struct rtgui_event_kbd ekbd;
  222. ekbd.parent.type = RTGUI_EVENT_KBD;
  223. ekbd.parent.sender = RT_NULL;
  224. ekbd.type = RTGUI_KEYUP;
  225. ekbd.wid = RT_NULL;
  226. ekbd.mod = event.key.keysym.mod;
  227. ekbd.key = event.key.keysym.sym;
  228. /* FIXME: unicode */
  229. ekbd.unicode = 0;
  230. /* send event to server */
  231. rtgui_server_post_event(&ekbd.parent, sizeof(struct rtgui_event_kbd));
  232. }
  233. break;
  234. case SDL_KEYDOWN:
  235. {
  236. struct rtgui_event_kbd ekbd;
  237. ekbd.parent.type = RTGUI_EVENT_KBD;
  238. ekbd.parent.sender = RT_NULL;
  239. ekbd.type = RTGUI_KEYDOWN;
  240. ekbd.wid = RT_NULL;
  241. ekbd.mod = event.key.keysym.mod;
  242. ekbd.key = event.key.keysym.sym;
  243. /* FIXME: unicode */
  244. ekbd.unicode = 0;
  245. /* send event to server */
  246. rtgui_server_post_event(&ekbd.parent, sizeof(struct rtgui_event_kbd));
  247. }
  248. break;
  249. case SDL_QUIT:
  250. SDL_Quit();
  251. quit = 1;
  252. break;
  253. default:
  254. break;
  255. }
  256. if (quit)
  257. break;
  258. }
  259. //exit(0);
  260. return 0;
  261. }
  262. /* start sdl thread */
  263. void rt_hw_sdl_start(void)
  264. {
  265. #ifdef _WIN32
  266. HANDLE thread;
  267. DWORD thread_id;
  268. sdl_ok_event = CreateEvent(NULL,
  269. FALSE,
  270. FALSE,
  271. NULL);
  272. if (sdl_ok_event == NULL)
  273. {
  274. printf("error, create SDL event failed\n");
  275. exit(-1);
  276. }
  277. /* create thread that loop sdl event */
  278. thread = CreateThread(NULL,
  279. 0,
  280. (LPTHREAD_START_ROUTINE)sdl_loop,
  281. 0,
  282. CREATE_SUSPENDED,
  283. &thread_id);
  284. if (thread == NULL)
  285. {
  286. //Display Error Message
  287. return;
  288. }
  289. ResumeThread(thread);
  290. /* wait until SDL LCD device is registered and seted */
  291. WaitForSingleObject(sdl_ok_event, INFINITE);
  292. #else
  293. /* Linux */
  294. pthread_t pid;
  295. int res;
  296. pthread_mutex_init(&sdl_ok_mutex, NULL);
  297. pthread_cond_init(&sdl_ok_event, NULL);
  298. res = pthread_create(&pid, NULL, &sdl_loop, NULL);
  299. if (res)
  300. {
  301. printf("pthread create sdl thread faild, <%d>\n", res);
  302. exit(EXIT_FAILURE);
  303. }
  304. pthread_mutex_lock(&sdl_ok_mutex);
  305. pthread_cond_wait(&sdl_ok_event, &sdl_ok_mutex);
  306. pthread_mutex_destroy(&sdl_ok_mutex);
  307. pthread_cond_destroy(&sdl_ok_event);
  308. #endif
  309. }