]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
emu: Add SDL2 support
authorJulian Andres Klode <julian.klode@canonical.com>
Wed, 21 Jun 2023 13:14:17 +0000 (15:14 +0200)
committerDaniel Kiper <daniel.kiper@oracle.com>
Thu, 22 Jun 2023 22:50:38 +0000 (00:50 +0200)
So all we did with the surface in SDL1 was split into window,
surface, renderer and texture. Instead of drawing into the
surface and then flipping, you build your pixels, then update
a texture and then copy the texture to the renderer.

Here we use an empty RGB surface to hold our pixels, which enables
us to keep most of the code the same. The SDL1 code has been adjusted
to refer to "surface" instead of "window" when trying to access the
properties of the surface.

This approaches the configuration by adding a new --enable-grub-emu-sdl2
argument. If set to yes, or auto detected, it disables SDL1 support
automatically.

This duplicates the sdl module block in Makefile.core.def which may
be something to be aware of, but we also don't want to build separate
module.

Fixes: https://bugs.debian.org/1038035
Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
configure.ac
grub-core/Makefile.am
grub-core/Makefile.core.def
grub-core/video/emu/sdl.c
include/grub/sdl.h

index 250dfc1c4338e9c5463c7b0f566f4fb7d7623348..9d7854d35fe1aed0a413a56bd84871e115f78140 100644 (file)
@@ -1586,6 +1586,10 @@ else
 fi
 AC_SUBST([BOOT_TIME_STATS])
 
+AC_ARG_ENABLE([grub-emu-sdl2],
+             [AS_HELP_STRING([--enable-grub-emu-sdl2],
+                             [build and install the `grub-emu' debugging utility with SDL2 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)])])
@@ -1595,6 +1599,28 @@ AC_ARG_ENABLE([grub-emu-pci],
                              [build and install the `grub-emu' debugging utility with PCI support (potentially dangerous) (default=no)])])
 
 if test "$platform" = emu; then
+  if test x"$enable_grub_emu_sdl2" = xno ; then
+    grub_emu_sdl2_excuse="explicitly disabled"
+  fi
+  [if [ x"$grub_emu_sdl2_excuse" = x ]; then
+    # Check for libSDL libraries.]
+    PKG_CHECK_MODULES([SDL2], [sdl2], [
+            AC_DEFINE([HAVE_SDL2], [1], [Define to 1 if you have SDL2 library.])
+            AC_SUBST(HAVE_SDL2)],
+            [grub_emu_sdl2_excuse="libSDL2 libraries are required to build \`grub-emu' with SDL2 support"])
+  [fi]
+  if test x"enable_grub_emu_sdl2" = xyes && test x"$grub_emu_sdl2_excuse" != x ; then
+    AC_MSG_ERROR([SDL2 support for grub-emu was explicitly requested but can't be compiled ($grub_emu_sdl2_excuse)])
+  fi
+  if test x"$grub_emu_sdl2_excuse" = x ; then
+    enable_grub_emu_sdl2=yes
+  else
+    enable_grub_emu_sdl2=no
+  fi
+  if test x"$enable_grub_emu_sdl2" = xyes ; then
+    grub_emu_sdl_excuse="disabled by sdl2"
+  fi
+
 
   if test x"$enable_grub_emu_sdl" = xno ; then
     grub_emu_sdl_excuse="explicitly disabled"
@@ -1643,12 +1669,14 @@ AC_CHECK_LIB([SDL], [SDL_Init], [LIBSDL="-lSDL"],
     enable_grub_emu_pci=no
   fi
 
+  AC_SUBST([enable_grub_emu_sdl2])
   AC_SUBST([enable_grub_emu_sdl])
   AC_SUBST([enable_grub_emu_pci])
 
 else
 
   # Ignore --enable-emu-* if platform is not emu
+  enable_grub_emu_sdl2=no
   enable_grub_emu_sdl=no
   enable_grub_emu_pci=no
 fi
@@ -2075,6 +2103,7 @@ AM_CONDITIONAL([COND_HOST_XNU], [test x$host_kernel = xxnu])
 AM_CONDITIONAL([COND_HOST_ILLUMOS], [test x$host_kernel = xillumos])
 
 AM_CONDITIONAL([COND_MAN_PAGES], [test x$cross_compiling = xno -a x$HELP2MAN != x])
+AM_CONDITIONAL([COND_GRUB_EMU_SDL2], [test x$enable_grub_emu_sdl2 = xyes])
 AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes])
 AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes])
 AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes])
@@ -2153,6 +2182,11 @@ echo "*******************************************************"
 echo GRUB2 will be compiled with following components:
 echo Platform: "$target_cpu"-"$platform"
 if [ x"$platform" = xemu ]; then
+if [ x"$grub_emu_sdl2_excuse" = x ]; then
+echo SDL2 support for grub-emu: Yes
+else
+echo SDL2 support for grub-emu: No "($grub_emu_sdl2_excuse)"
+fi
 if [ x"$grub_emu_sdl_excuse" = x ]; then
 echo SDL support for grub-emu: Yes
 else
index d32f2b662e9fb8a1b1bd9c2c0a1db357efe070e9..f0cb2f2cc4b532b451c073cc04010d98889bc465 100644 (file)
@@ -317,6 +317,9 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/exec.h
 if COND_GRUB_EMU_SDL
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
 endif
+if COND_GRUB_EMU_SDL2
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
+endif
 if COND_GRUB_EMU_PCI
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libpciaccess.h
 endif
index e458aa665574de30996fbbacf0aecf529e2a553c..d2cf29584a1ab0620ecaf1bf979e2e539fdb522c 100644 (file)
@@ -418,7 +418,7 @@ program = {
 
   ldadd = 'kernel.exec$(EXEEXT)';
   ldadd = '$(MODULE_FILES)';
-  ldadd = 'lib/gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
+  ldadd = 'lib/gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(SDL2_LIBS) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
 
   enable = emu;
 };
@@ -430,7 +430,7 @@ program = {
   emu_nodist = symlist.c;
 
   ldadd = 'kernel.exec$(EXEEXT)';
-  ldadd = 'lib/gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
+  ldadd = 'lib/gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(SDL2_LIBS) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
 
   enable = emu;
 };
@@ -2325,6 +2325,14 @@ module = {
   condition = COND_GRUB_EMU_SDL;
 };
 
+module = {
+  name = sdl;
+  emu = video/emu/sdl.c;
+  enable = emu;
+  condition = COND_GRUB_EMU_SDL2;
+  cflags = '$(SDL2_CFLAGS)';
+};
+
 module = {
   name = datehook;
   common = hook/datehook.c;
index c1b66f01e0737dfb58f46d6824cfd4f4ed134ba8..cb8490e35093128791f13c3eb0a1ea18e1e2663c 100644 (file)
@@ -18,6 +18,9 @@
 
 #define grub_video_render_target grub_video_fbrender_target
 
+#include <config-util.h>
+#include <config.h>
+
 #include <grub/err.h>
 #include <grub/types.h>
 #include <grub/dl.h>
 #include <grub/mm.h>
 #include <grub/video.h>
 #include <grub/video_fb.h>
+#ifdef HAVE_SDL2
+#include <SDL2/SDL.h>
+#else
 #include <SDL/SDL.h>
+#endif
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
+#ifdef HAVE_SDL2
+static SDL_Window *window = NULL;
+static SDL_Texture *texture = NULL;
+static SDL_Renderer *renderer = NULL;
+#else
 static SDL_Surface *window = NULL;
+#endif
+static SDL_Surface *surface = NULL;
 static struct grub_video_render_target *sdl_render_target;
 static struct grub_video_mode_info mode_info;
 
@@ -72,7 +86,7 @@ get_mask_size (grub_uint32_t mask)
 
 static grub_err_t
 grub_video_sdl_setup (unsigned int width, unsigned int height,
-                      unsigned int mode_type, unsigned int mode_mask)
+                      unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused)))
 {
   int depth;
   int flags = 0;
@@ -91,6 +105,35 @@ grub_video_sdl_setup (unsigned int width, unsigned int height,
       height = 600;
     }
 
+#ifdef HAVE_SDL2
+  window = SDL_CreateWindow ("grub-emu",
+                            SDL_WINDOWPOS_UNDEFINED,
+                            SDL_WINDOWPOS_UNDEFINED,
+                            width, height, flags);
+  if(window == NULL)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "could not open window: %s",
+                      SDL_GetError ());
+  renderer = SDL_CreateRenderer (window, -1, 0);
+  if (renderer == NULL)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "could not open renderer: %s",
+                      SDL_GetError ());
+  texture = SDL_CreateTexture (renderer,
+                              SDL_PIXELFORMAT_ARGB8888,
+                              SDL_TEXTUREACCESS_STREAMING,
+                              width, height);
+  if (texture == NULL)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "could not create texture: %s",
+                      SDL_GetError ());
+
+  /*
+   * An empty surface that acts as the pixel buffer, the texture will receive the pixels
+   * from here.
+   */
+  surface = SDL_CreateRGBSurface (0, width, height, depth, 0, 0, 0, 0);
+  if (surface == NULL)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "could not open surface: %s",
+                      SDL_GetError ());
+#else
   if ((mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED)
       || !(mode_mask & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED))
     flags |= SDL_DOUBLEBUF;
@@ -102,51 +145,55 @@ grub_video_sdl_setup (unsigned int width, unsigned int height,
     return grub_error (GRUB_ERR_BAD_DEVICE, "could not open window: %s",
                       SDL_GetError ());
 
+  surface = window;
+#endif
   grub_memset (&sdl_render_target, 0, sizeof (sdl_render_target));
 
-  mode_info.width = window->w;
-  mode_info.height = window->h;
   mode_info.mode_type = 0;
-  if (window->flags & SDL_DOUBLEBUF)
+  mode_info.width = surface->w;
+  mode_info.height = surface->h;
+#ifndef HAVE_SDL2
+  if (surface->flags & SDL_DOUBLEBUF)
     mode_info.mode_type
       |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
-  if (window->format->palette)
+#endif
+  if (surface->format->palette)
     mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
   else
     mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_RGB;
 
-  mode_info.bpp = window->format->BitsPerPixel;
-  mode_info.bytes_per_pixel = window->format->BytesPerPixel;
-  mode_info.pitch = window->pitch;
+  mode_info.bpp = surface->format->BitsPerPixel;
+  mode_info.bytes_per_pixel = surface->format->BytesPerPixel;
+  mode_info.pitch = surface->pitch;
 
   /* In index color mode, number of colors.  In RGB mode this is 256.  */
-  if (window->format->palette)
+  if (surface->format->palette)
     mode_info.number_of_colors
-      = 1 << window->format->BitsPerPixel;
+      = 1 << surface->format->BitsPerPixel;
   else
     mode_info.number_of_colors = 256;
 
-  if (! window->format->palette)
+  if (! surface->format->palette)
     {
       mode_info.red_mask_size
-       = get_mask_size (window->format->Rmask >> window->format->Rshift);
-      mode_info.red_field_pos = window->format->Rshift;
+       = get_mask_size (surface->format->Rmask >> surface->format->Rshift);
+      mode_info.red_field_pos = surface->format->Rshift;
       mode_info.green_mask_size
-       = get_mask_size (window->format->Gmask >> window->format->Gshift);
-      mode_info.green_field_pos = window->format->Gshift;
+       = get_mask_size (surface->format->Gmask >> surface->format->Gshift);
+      mode_info.green_field_pos = surface->format->Gshift;
       mode_info.blue_mask_size
-       = get_mask_size (window->format->Bmask >> window->format->Bshift);
-      mode_info.blue_field_pos = window->format->Bshift;
+       = get_mask_size (surface->format->Bmask >> surface->format->Bshift);
+      mode_info.blue_field_pos = surface->format->Bshift;
       mode_info.reserved_mask_size
-       = get_mask_size (window->format->Amask >> window->format->Ashift);
-      mode_info.reserved_field_pos = window->format->Ashift;
+       = get_mask_size (surface->format->Amask >> surface->format->Ashift);
+      mode_info.reserved_field_pos = surface->format->Ashift;
       mode_info.blit_format
        = grub_video_get_blit_format (&mode_info);
     }
 
   err = grub_video_fb_create_render_target_from_pointer (&sdl_render_target,
                                                         &mode_info,
-                                                        window->pixels);
+                                                        surface->pixels);
   if (err)
     return err;
 
@@ -163,7 +210,7 @@ grub_video_sdl_set_palette (unsigned int start, unsigned int count,
                             struct grub_video_palette_data *palette_data)
 {
   unsigned i;
-  if (window->format->palette)
+  if (surface->format->palette)
     {
       SDL_Color *tmp;
       if (start >= mode_info.number_of_colors)
@@ -178,9 +225,17 @@ grub_video_sdl_set_palette (unsigned int start, unsigned int count,
          tmp[i].r = palette_data[i].r;
          tmp[i].g = palette_data[i].g;
          tmp[i].b = palette_data[i].b;
+#ifdef HAVE_SDL2
+         tmp[i].a = palette_data[i].a;
+#else
          tmp[i].unused = palette_data[i].a;
+#endif
        }
+#ifdef HAVE_SDL2
+      SDL_SetPaletteColors (surface->format->palette, tmp, 0 /* firstcolor */, count);
+#else
       SDL_SetColors (window, tmp, start, count);
+#endif
       grub_free (tmp);
     }
 
@@ -190,9 +245,22 @@ grub_video_sdl_set_palette (unsigned int start, unsigned int count,
 static grub_err_t
 grub_video_sdl_swap_buffers (void)
 {
+#ifdef HAVE_SDL2
+  if (SDL_UpdateTexture (texture, NULL, surface->pixels, surface->w * sizeof (Uint32)) < 0)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "could not update texture: %s",
+                      SDL_GetError ());
+  if (SDL_RenderClear (renderer) < 0)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "could not clear renderer: %s",
+                      SDL_GetError ());
+  if (SDL_RenderCopy (renderer, texture, NULL, NULL) < 0)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "could not copy texture to renderer: %s",
+                      SDL_GetError ());
+  SDL_RenderPresent (renderer);
+#else
   if (SDL_Flip (window) < 0)
     return grub_error (GRUB_ERR_BAD_DEVICE, "could not swap buffers: %s",
                       SDL_GetError ());
+#endif
   return GRUB_ERR_NONE;
 }
 
index e4efdc9b14e0429b454412fa9a1356af8ae02016..8f10b88173f49223c859b635561d58767486dd23 100644 (file)
  *  You should have received a copy of the GNU General Public License
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
+#include <config-util.h>
 
 void EXPORT_FUNC (SDL_Quit) (void);
-void EXPORT_FUNC (SDL_SetColors) (void);
 void EXPORT_FUNC (SDL_Init) (void);
 void EXPORT_FUNC (SDL_GetError) (void);
+#ifdef HAVE_SDL2
+void EXPORT_FUNC (SDL_CreateWindow) (void);
+void EXPORT_FUNC (SDL_GetWindowSurface) (void);
+void EXPORT_FUNC (SDL_CreateRenderer) (void);
+void EXPORT_FUNC (SDL_CreateRGBSurface) (void);
+void EXPORT_FUNC (SDL_CreateTexture) (void);
+void EXPORT_FUNC (SDL_UpdateTexture) (void);
+void EXPORT_FUNC (SDL_SetPaletteColors) (void);
+void EXPORT_FUNC (SDL_RenderClear) (void);
+void EXPORT_FUNC (SDL_RenderCopy) (void);
+void EXPORT_FUNC (SDL_RenderPresent) (void);
+#else
 void EXPORT_FUNC (SDL_Flip) (void);
+void EXPORT_FUNC (SDL_SetColors) (void);
 void EXPORT_FUNC (SDL_SetVideoMode) (void);
+#endif