sdl_fb.c 9.2 KB

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