diff --git a/commands/videotest.c b/commands/videotest.c index 6fe4b9b..6f23560 100644 --- a/commands/videotest.c +++ b/commands/videotest.c @@ -159,7 +159,7 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, 0, 0, 0, 0, width, height); } - + grub_video_swap_buffers (); grub_getkey (); grub_video_delete_render_target (text_layer); diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 66fdbd4..60b87b0 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -153,6 +153,12 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \ fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c \ fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c \ \ + video/video.c video/fb/video_fb.c video/fb/fbblit.c \ + video/fb/fbfill.c video/fb/fbutil.c commands/videotest.c \ + video/bitmap.c video/readers/tga.c video/readers/jpeg.c \ + video/readers/png.c font/font_cmd.c font/font.c term/gfxterm.c \ + io/bufio.c util/sdl.c \ + \ util/console.c util/hostfs.c util/grub-emu.c util/misc.c \ util/hostdisk.c util/getroot.c \ util/i386/pc/misc.c \ diff --git a/term/gfxterm.c b/term/gfxterm.c index ef93bb7..f48379a 100644 --- a/term/gfxterm.c +++ b/term/gfxterm.c @@ -462,6 +462,7 @@ dirty_region_redraw (void) redraw_screen_rect (x, y, width, height); dirty_region_reset (); + grub_video_swap_buffers (); } static void diff --git a/util/sdl.c b/util/sdl.c new file mode 100644 index 0000000..7de6a16 --- /dev/null +++ b/util/sdl.c @@ -0,0 +1,249 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#define grub_video_render_target grub_video_fbrender_target + +#include +#include +#include +#include +#include +#include +#include +#include + +static SDL_Surface *window = 0; +static struct grub_video_render_target sdl_render_target; + +static grub_err_t +grub_video_sdl_set_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data); + +static grub_err_t +grub_video_sdl_init (void) +{ + window = 0; + grub_memset (&sdl_render_target, 0, sizeof(sdl_render_target)); + + if (SDL_Init (SDL_INIT_VIDEO) < 0) + return grub_error (GRUB_ERR_BAD_DEVICE, "Couldn't init SDL: %s", + SDL_GetError ()); + /* Reset frame buffer and render target variables. */ + grub_memset (&sdl_render_target, 0, sizeof(sdl_render_target)); + return grub_video_fb_init (); +} + +static grub_err_t +grub_video_sdl_fini (void) +{ + SDL_Quit (); + window = 0; + grub_memset (&sdl_render_target, 0, sizeof(sdl_render_target)); + + return grub_video_fb_fini (); +} + +static inline unsigned int +get_mask_size (grub_uint32_t mask) +{ + unsigned i; + for (i = 0; mask > 1U << i; i++); + return i; +} + +static grub_err_t +grub_video_sdl_setup (unsigned int width, unsigned int height, + unsigned int mode_type) +{ + int depth; + int flags = 0; + /* Decode depth from mode_type. If it is zero, then autodetect. */ + depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; + + if (mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED) + flags |= SDL_DOUBLEBUF; + + window = SDL_SetVideoMode (width, height, depth, flags | SDL_HWSURFACE); + if (! window) + window = SDL_SetVideoMode (width, height, depth, flags | SDL_SWSURFACE); + if (! window) + return grub_error (GRUB_ERR_BAD_DEVICE, "Couldn't open window: %s", + SDL_GetError ()); + + grub_memset (&sdl_render_target, 0, sizeof (sdl_render_target)); + + sdl_render_target.mode_info.width = window->w; + sdl_render_target.mode_info.height = window->h; + sdl_render_target.mode_info.mode_type = 0; + if (window->flags & SDL_DOUBLEBUF) + sdl_render_target.mode_info.mode_type + |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + if (window->format->palette) + sdl_render_target.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + else + sdl_render_target.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_RGB; + + sdl_render_target.mode_info.bpp = window->format->BitsPerPixel; + sdl_render_target.mode_info.bytes_per_pixel = window->format->BytesPerPixel; + sdl_render_target.mode_info.pitch = window->pitch; + + /* In index color mode, number of colors. In RGB mode this is 256. */ + if (window->format->palette) + sdl_render_target.mode_info.number_of_colors + = 1 << window->format->BitsPerPixel; + else + sdl_render_target.mode_info.number_of_colors = 256; + + if (! window->format->palette) + { + sdl_render_target.mode_info.red_mask_size + = get_mask_size (window->format->Rmask >> window->format->Rshift); + sdl_render_target.mode_info.red_field_pos = window->format->Rshift; + sdl_render_target.mode_info.green_mask_size + = get_mask_size (window->format->Gmask >> window->format->Gshift); + sdl_render_target.mode_info.green_field_pos = window->format->Gshift; + sdl_render_target.mode_info.blue_mask_size + = get_mask_size (window->format->Bmask >> window->format->Bshift); + sdl_render_target.mode_info.blue_field_pos = window->format->Bshift; + sdl_render_target.mode_info.reserved_mask_size + = get_mask_size (window->format->Amask >> window->format->Ashift); + sdl_render_target.mode_info.reserved_field_pos = window->format->Ashift; + sdl_render_target.mode_info.blit_format + = grub_video_get_blit_format (&sdl_render_target.mode_info); + } + + sdl_render_target.viewport.x = sdl_render_target.viewport.y = 0; + sdl_render_target.viewport.width = window->w; + sdl_render_target.viewport.height = window->h; + sdl_render_target.is_allocated = 0; + sdl_render_target.data = window->pixels; + + /* Copy default palette to initialize emulated palette. */ + grub_video_sdl_set_palette (0, (sizeof (grub_video_fbstd_colors) + / sizeof (grub_video_fbstd_colors[0])), + grub_video_fbstd_colors); + + /* Reset render target to SDL one. */ + return grub_video_fb_set_active_render_target (&sdl_render_target); +} + +static grub_err_t +grub_video_sdl_set_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data) +{ + unsigned i; + if (window->format->palette) + { + SDL_Color *tmp = grub_malloc (count * sizeof (tmp[0])); + for (i = 0; i < count; i++) + { + tmp[i].r = palette_data[i].r; + tmp[i].g = palette_data[i].g; + tmp[i].b = palette_data[i].b; + tmp[i].unused = palette_data[i].a; + } + SDL_SetColors (window, tmp, start, count); + grub_free (tmp); + } + + return grub_video_fb_set_palette (start, count, palette_data); +} + +grub_err_t +grub_video_sdl_set_viewport (unsigned int x, unsigned int y, + unsigned int width, unsigned int height) +{ + /* Make sure viewport is withing screen dimensions. If viewport was set + to be out of the region, mark its size as zero. */ + if (x > (unsigned) window->w) + { + x = 0; + width = 0; + } + + if (y > (unsigned) window->h) + { + y = 0; + height = 0; + } + + if (x + width > (unsigned) window->w) + width = window->w - x; + + if (y + height > (unsigned) window->h) + height = window->h - y; + return grub_video_fb_set_viewport (x, y, width, height); +} + +static grub_err_t +grub_video_sdl_swap_buffers (void) +{ + if (SDL_Flip (window) < 0) + return grub_error (GRUB_ERR_BAD_DEVICE, "couldn't swap buffers: %s", + SDL_GetError ()); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_sdl_set_active_render_target (struct grub_video_render_target *target) +{ + if (target == GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER) + return grub_video_fb_set_active_render_target (&sdl_render_target); + + return grub_video_fb_set_active_render_target (target); +} + +static struct grub_video_adapter grub_video_sdl_adapter = + { + .name = "SDL Video Driver", + + .init = grub_video_sdl_init, + .fini = grub_video_sdl_fini, + .setup = grub_video_sdl_setup, + .get_info = grub_video_fb_get_info, + .set_palette = grub_video_sdl_set_palette, + .get_palette = grub_video_fb_get_palette, + .set_viewport = grub_video_fb_set_viewport, + .get_viewport = grub_video_fb_get_viewport, + .map_color = grub_video_fb_map_color, + .map_rgb = grub_video_fb_map_rgb, + .map_rgba = grub_video_fb_map_rgba, + .unmap_color = grub_video_fb_unmap_color, + .fill_rect = grub_video_fb_fill_rect, + .blit_bitmap = grub_video_fb_blit_bitmap, + .blit_render_target = grub_video_fb_blit_render_target, + .scroll = grub_video_fb_scroll, + .swap_buffers = grub_video_sdl_swap_buffers, + .create_render_target = grub_video_fb_create_render_target, + .delete_render_target = grub_video_fb_delete_render_target, + .set_active_render_target = grub_video_sdl_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, + + .next = 0 + }; + +GRUB_MOD_INIT(sdl) +{ + grub_video_register (&grub_video_sdl_adapter); +} + +GRUB_MOD_FINI(sdl) +{ + grub_video_unregister (&grub_video_sdl_adapter); +} diff --git a/video/video.c b/video/video.c index 8271d79..2f70274 100644 --- a/video/video.c +++ b/video/video.c @@ -699,8 +699,6 @@ grub_video_set_mode (char *modestring, /* Initialize Video API module. */ GRUB_MOD_INIT(video_video) { - grub_video_adapter_active = 0; - grub_video_adapter_list = 0; } /* Finalize Video API module. */