sdl.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #define grub_video_render_target grub_video_fbrender_target
  19. #include <grub/err.h>
  20. #include <grub/types.h>
  21. #include <grub/dl.h>
  22. #include <grub/misc.h>
  23. #include <grub/mm.h>
  24. #include <grub/video.h>
  25. #include <grub/video_fb.h>
  26. #include <grub/term.h>
  27. #include <SDL/SDL.h>
  28. static SDL_Surface *window = 0;
  29. static struct grub_video_render_target *sdl_render_target;
  30. static struct grub_video_mode_info mode_info;
  31. static grub_err_t
  32. grub_video_sdl_set_palette (unsigned int start, unsigned int count,
  33. struct grub_video_palette_data *palette_data);
  34. static int saved_char = -1;
  35. const char *ascii_mapping = "`~1!2@3#4$5%6^7&8*9(0)-_=+\\|[{]};:'\",<.>/?";
  36. static int
  37. get_ascii (int key, SDLMod mod)
  38. {
  39. const char *p;
  40. if ((mod != KMOD_LSHIFT) && (mod != KMOD_RSHIFT))
  41. return key;
  42. if ((key >= 'a') && (key <= 'z'))
  43. return key - 'a' + 'A';
  44. for (p = ascii_mapping; *p; p += 2)
  45. {
  46. if (*p == key)
  47. return *(p + 1);
  48. }
  49. return key;
  50. }
  51. static int
  52. grub_sdl_checkkey (void)
  53. {
  54. SDL_Event event;
  55. if (saved_char != -1)
  56. return saved_char;
  57. while (SDL_PollEvent (&event))
  58. {
  59. if (event.type == SDL_QUIT)
  60. grub_halt ();
  61. if (event.type == SDL_KEYDOWN)
  62. {
  63. int key;
  64. switch (event.key.keysym.sym)
  65. {
  66. case SDLK_LEFT:
  67. key = GRUB_TERM_LEFT;
  68. break;
  69. case SDLK_RIGHT:
  70. key = GRUB_TERM_RIGHT;
  71. break;
  72. case SDLK_UP:
  73. key = GRUB_TERM_UP;
  74. break;
  75. case SDLK_DOWN:
  76. key = GRUB_TERM_DOWN;
  77. break;
  78. case SDLK_HOME:
  79. key = GRUB_TERM_HOME;
  80. break;
  81. case SDLK_END:
  82. key = GRUB_TERM_END;
  83. break;
  84. case SDLK_PAGEUP:
  85. key = GRUB_TERM_PPAGE;
  86. break;
  87. case SDLK_PAGEDOWN:
  88. key = GRUB_TERM_NPAGE;
  89. break;
  90. case SDLK_DELETE:
  91. key = GRUB_TERM_DC;
  92. break;
  93. case SDLK_INSERT:
  94. key = GRUB_TERM_IC;
  95. break;
  96. case SDLK_F1:
  97. key = GRUB_TERM_F1;
  98. break;
  99. case SDLK_F2:
  100. key = GRUB_TERM_F2;
  101. break;
  102. case SDLK_F3:
  103. key = GRUB_TERM_F3;
  104. break;
  105. case SDLK_F4:
  106. key = GRUB_TERM_F4;
  107. break;
  108. case SDLK_F5:
  109. key = GRUB_TERM_F5;
  110. break;
  111. case SDLK_F6:
  112. key = GRUB_TERM_F6;
  113. break;
  114. case SDLK_F7:
  115. key = GRUB_TERM_F7;
  116. break;
  117. case SDLK_F8:
  118. key = GRUB_TERM_F8;
  119. break;
  120. case SDLK_F9:
  121. key = GRUB_TERM_F9;
  122. break;
  123. case SDLK_F10:
  124. key = GRUB_TERM_F10;
  125. break;
  126. default:
  127. key = (event.key.keysym.sym > 127) ? 0 :
  128. get_ascii (event.key.keysym.sym, event.key.keysym.mod);
  129. }
  130. saved_char = key;
  131. return key;
  132. }
  133. }
  134. return -1;
  135. }
  136. static int
  137. grub_sdl_getkey (void)
  138. {
  139. if (saved_char != -1)
  140. {
  141. int key;
  142. key = saved_char;
  143. saved_char = -1;
  144. return key;
  145. }
  146. while (1)
  147. {
  148. int c;
  149. c = grub_sdl_checkkey ();
  150. if (c != -1)
  151. {
  152. saved_char = -1;
  153. return c;
  154. }
  155. }
  156. }
  157. static struct grub_term_input grub_sdl_term_input =
  158. {
  159. .name = "sdl",
  160. .checkkey = grub_sdl_checkkey,
  161. .getkey = grub_sdl_getkey
  162. };
  163. static grub_err_t
  164. grub_video_sdl_init (void)
  165. {
  166. window = 0;
  167. if (SDL_Init (SDL_INIT_VIDEO) < 0)
  168. return grub_error (GRUB_ERR_BAD_DEVICE, "Couldn't init SDL: %s",
  169. SDL_GetError ());
  170. grub_memset (&mode_info, 0, sizeof (mode_info));
  171. return grub_video_fb_init ();
  172. }
  173. static grub_err_t
  174. grub_video_sdl_fini (void)
  175. {
  176. SDL_Quit ();
  177. window = 0;
  178. grub_memset (&mode_info, 0, sizeof (mode_info));
  179. return grub_video_fb_fini ();
  180. }
  181. static inline unsigned int
  182. get_mask_size (grub_uint32_t mask)
  183. {
  184. unsigned i;
  185. for (i = 0; mask > 1U << i; i++);
  186. return i;
  187. }
  188. static grub_err_t
  189. grub_video_sdl_setup (unsigned int width, unsigned int height,
  190. unsigned int mode_type,
  191. unsigned int mode_mask __attribute__ ((unused)))
  192. {
  193. int depth;
  194. int flags = 0;
  195. grub_err_t err;
  196. /* Decode depth from mode_type. If it is zero, then autodetect. */
  197. depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
  198. >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
  199. if ((depth == 0) || (depth == 32))
  200. depth = 24;
  201. if (width == 0 && height == 0)
  202. {
  203. width = 800;
  204. height = 600;
  205. }
  206. if ((mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED)
  207. || !(mode_mask & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED))
  208. flags |= SDL_DOUBLEBUF;
  209. window = SDL_SetVideoMode (width, height, depth, flags | SDL_HWSURFACE);
  210. if (! window)
  211. window = SDL_SetVideoMode (width, height, depth, flags | SDL_SWSURFACE);
  212. if (! window)
  213. return grub_error (GRUB_ERR_BAD_DEVICE, "Couldn't open window: %s",
  214. SDL_GetError ());
  215. grub_memset (&sdl_render_target, 0, sizeof (sdl_render_target));
  216. mode_info.width = window->w;
  217. mode_info.height = window->h;
  218. mode_info.mode_type = 0;
  219. if (window->flags & SDL_DOUBLEBUF)
  220. mode_info.mode_type
  221. |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
  222. if (window->format->palette)
  223. mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
  224. else
  225. mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_RGB;
  226. mode_info.bpp = window->format->BitsPerPixel;
  227. mode_info.bytes_per_pixel = window->format->BytesPerPixel;
  228. mode_info.pitch = window->pitch;
  229. /* In index color mode, number of colors. In RGB mode this is 256. */
  230. if (window->format->palette)
  231. mode_info.number_of_colors
  232. = 1 << window->format->BitsPerPixel;
  233. else
  234. mode_info.number_of_colors = 256;
  235. if (! window->format->palette)
  236. {
  237. mode_info.red_mask_size
  238. = get_mask_size (window->format->Rmask >> window->format->Rshift);
  239. mode_info.red_field_pos = window->format->Rshift;
  240. mode_info.green_mask_size
  241. = get_mask_size (window->format->Gmask >> window->format->Gshift);
  242. mode_info.green_field_pos = window->format->Gshift;
  243. mode_info.blue_mask_size
  244. = get_mask_size (window->format->Bmask >> window->format->Bshift);
  245. mode_info.blue_field_pos = window->format->Bshift;
  246. mode_info.reserved_mask_size
  247. = get_mask_size (window->format->Amask >> window->format->Ashift);
  248. mode_info.reserved_field_pos = window->format->Ashift;
  249. mode_info.blit_format
  250. = grub_video_get_blit_format (&mode_info);
  251. }
  252. err = grub_video_fb_create_render_target_from_pointer (&sdl_render_target,
  253. &mode_info,
  254. window->pixels);
  255. if (err)
  256. return err;
  257. /* Copy default palette to initialize emulated palette. */
  258. grub_video_sdl_set_palette (0, (sizeof (grub_video_fbstd_colors)
  259. / sizeof (grub_video_fbstd_colors[0])),
  260. grub_video_fbstd_colors);
  261. /* Reset render target to SDL one. */
  262. return grub_video_fb_set_active_render_target (sdl_render_target);
  263. }
  264. static grub_err_t
  265. grub_video_sdl_set_palette (unsigned int start, unsigned int count,
  266. struct grub_video_palette_data *palette_data)
  267. {
  268. unsigned i;
  269. if (window->format->palette)
  270. {
  271. SDL_Color *tmp = grub_malloc (count * sizeof (tmp[0]));
  272. for (i = 0; i < count; i++)
  273. {
  274. tmp[i].r = palette_data[i].r;
  275. tmp[i].g = palette_data[i].g;
  276. tmp[i].b = palette_data[i].b;
  277. tmp[i].unused = palette_data[i].a;
  278. }
  279. SDL_SetColors (window, tmp, start, count);
  280. grub_free (tmp);
  281. }
  282. return grub_video_fb_set_palette (start, count, palette_data);
  283. }
  284. static grub_err_t
  285. grub_video_sdl_swap_buffers (void)
  286. {
  287. if (SDL_Flip (window) < 0)
  288. return grub_error (GRUB_ERR_BAD_DEVICE, "couldn't swap buffers: %s",
  289. SDL_GetError ());
  290. return GRUB_ERR_NONE;
  291. }
  292. static grub_err_t
  293. grub_video_sdl_set_active_render_target (struct grub_video_render_target *target)
  294. {
  295. if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
  296. return grub_video_fb_set_active_render_target (sdl_render_target);
  297. return grub_video_fb_set_active_render_target (target);
  298. }
  299. static void
  300. grub_video_sdl_update_rect (int x, int y, int width, int height)
  301. {
  302. SDL_UpdateRect (window, x, y, width, height);
  303. }
  304. static struct grub_video_adapter grub_video_sdl_adapter =
  305. {
  306. .name = "SDL Video Driver",
  307. .init = grub_video_sdl_init,
  308. .fini = grub_video_sdl_fini,
  309. .setup = grub_video_sdl_setup,
  310. .get_info = grub_video_fb_get_info,
  311. .set_palette = grub_video_sdl_set_palette,
  312. .get_palette = grub_video_fb_get_palette,
  313. .set_viewport = grub_video_fb_set_viewport,
  314. .get_viewport = grub_video_fb_get_viewport,
  315. .map_color = grub_video_fb_map_color,
  316. .map_rgb = grub_video_fb_map_rgb,
  317. .map_rgba = grub_video_fb_map_rgba,
  318. .unmap_color = grub_video_fb_unmap_color,
  319. .fill_rect = grub_video_fb_fill_rect,
  320. .blit_bitmap = grub_video_fb_blit_bitmap,
  321. .blit_render_target = grub_video_fb_blit_render_target,
  322. .scroll = grub_video_fb_scroll,
  323. .swap_buffers = grub_video_sdl_swap_buffers,
  324. .create_render_target = grub_video_fb_create_render_target,
  325. .delete_render_target = grub_video_fb_delete_render_target,
  326. .set_active_render_target = grub_video_sdl_set_active_render_target,
  327. .get_active_render_target = grub_video_fb_get_active_render_target,
  328. .update_rect = grub_video_sdl_update_rect,
  329. .next = 0
  330. };
  331. GRUB_MOD_INIT(sdl)
  332. {
  333. grub_term_input_t term = &grub_sdl_term_input;
  334. grub_video_register (&grub_video_sdl_adapter);
  335. grub_term_register_input ("sdl", term);
  336. grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
  337. }
  338. GRUB_MOD_FINI(sdl)
  339. {
  340. grub_video_unregister (&grub_video_sdl_adapter);
  341. grub_term_unregister_input (&grub_sdl_term_input);
  342. }