diff --git a/Makefile.in b/Makefile.in index 25acce7..b9b9cda 100644 --- a/Makefile.in +++ b/Makefile.in @@ -95,12 +95,14 @@ endif AWK = @AWK@ LIBCURSES = @LIBCURSES@ LIBUSB = @LIBUSB@ +LIBSDL = @LIBSDL@ YACC = @YACC@ UNIFONT_BDF = @UNIFONT_BDF@ # Options. enable_grub_emu = @enable_grub_emu@ enable_grub_emu_usb = @enable_grub_emu_usb@ +enable_grub_emu_sdl = @enable_grub_emu_sdl@ enable_grub_fstest = @enable_grub_fstest@ enable_grub_pe2elf = @enable_grub_pe2elf@ enable_grub_mkfont = @enable_grub_mkfont@ diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 5b7b8c0..eb33781 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -150,6 +150,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/befs.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/console.c util/hostfs.c util/grub-emu.c util/misc.c \ util/hostdisk.c util/getroot.c \ \ @@ -163,7 +169,12 @@ grub_emu_LDFLAGS = $(LIBCURSES) ifeq ($(enable_grub_emu_usb), yes) grub_emu_SOURCES += disk/usbms.c util/usb.c bus/usb/usb.c \ commands/usbtest.c -grub_emu_LDFLAGS += $(LIBCURSES) $(LIBUSB) +grub_emu_LDFLAGS += $(LIBUSB) +endif + +ifeq ($(enable_grub_emu_sdl), yes) +grub_emu_SOURCES += util/sdl.c +grub_emu_LDFLAGS += $(LIBSDL) endif # Scripts. diff --git a/configure.ac b/configure.ac index 549b35c..a2140cd 100644 --- a/configure.ac +++ b/configure.ac @@ -460,6 +460,10 @@ AC_ARG_ENABLE([grub-emu], AC_ARG_ENABLE([grub-emu-usb], [AS_HELP_STRING([--enable-grub-emu-usb], [build and install the `grub-emu' debugging utility with USB support (default=guessed)])]) +AC_ARG_ENABLE([grub-emu-sdl], + [AS_HELP_STRING([--enable-grub-emu-sdl], + [build and install the `grub-emu' debugging utility with SDL support (default=guessed)])]) + if test x"$enable_grub_emu" = xno ; then grub_emu_excuse="explicitly disabled" fi @@ -487,6 +491,7 @@ enable_grub_emu=yes else enable_grub_emu=no grub_emu_usb_excuse="grub-emu isn't built" +grub_emu_sdl_excuse="grub-emu isn't built" fi if test x"$enable_grub_emu_usb" = xno ; then grub_emu_usb_excuse="explicitly disabled" @@ -511,8 +516,32 @@ else enable_grub_emu_usb=no fi +if test x"$enable_grub_emu_sdl" = xno ; then + grub_emu_sdl_excuse="explicitely disabled" +fi +[if [ x"$grub_emu_sdl_excuse" = x ]; then + # Check for libSDL libraries.] +AC_CHECK_LIB([SDL], [SDL_Init], [LIBSDL="-lSDL"], + [grub_emu_sdl_excuse=["libSDL libraries are required to build \`grub-emu' with SDL support"]]) + AC_SUBST([LIBSDL]) +[fi] +[if [ x"$grub_emu_sdl_excuse" = x ]; then + # Check for headers.] + AC_CHECK_HEADERS([SDL/SDL.h], [], + [grub_emu_sdl_excuse=["libSDL header file is required to build \`grub-emu' with SDL support"]]) +[fi] +if test x"enable_grub_emu_sdl" = xyes && test x"$grub_emu_sdl_excuse" != x ; then + AC_MSG_ERROR([SDL support for grub-emu was explicitely requested but can't be compiled]) +fi +if test x"$grub_emu_sdl_excuse" = x ; then +enable_grub_emu_sdl=yes +else +enable_grub_emu_sdl=no +fi + AC_SUBST([enable_grub_emu]) AC_SUBST([enable_grub_emu_usb]) +AC_SUBST([enable_grub_emu_sdl]) AC_ARG_ENABLE([grub-fstest], [AS_HELP_STRING([--enable-grub-fstest], @@ -591,6 +620,11 @@ echo USB support for grub-emu: Yes else echo USB support for grub-emu: No "($grub_emu_usb_excuse)" fi +if [ x"$grub_emu_sdl_excuse" = x ]; then +echo SDL support for grub-emu: Yes +else +echo SDL support for grub-emu: No "($grub_emu_sdl_excuse)" +fi if [ x"$enable_mm_debug" = xyes ]; then echo With memory debugging: Yes else diff --git a/util/sdl.c b/util/sdl.c new file mode 100644 index 0000000..319da1b --- /dev/null +++ b/util/sdl.c @@ -0,0 +1,253 @@ +/* + * 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, GRUB_VIDEO_FBSTD_NUMCOLORS, + 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_DISPLAY) + return grub_video_fb_set_active_render_target (&sdl_render_target); + + return grub_video_fb_set_active_render_target (target); +} + +static grub_err_t grub_video_sdl_enable_double_buffering (int enable) +{ + return GRUB_ERR_NONE; +} + +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, + .enable_double_buffering = grub_video_sdl_enable_double_buffering, + .next = 0 + }; + +GRUB_MOD_INIT(sdl) +{ + grub_video_register (&grub_video_sdl_adapter); +} + +GRUB_MOD_FINI(sdl) +{ + grub_video_unregister (&grub_video_sdl_adapter); +}