After discussion on IRC it revealed that hook-based approach is
unpracticable because number of available modes grows exponentially
with every parameter available. Here is the patch to change to
flag-based approach

-- 
Regards
Vladimir 'phcoder' Serbinenko

Personal git repository: http://repo.or.cz/w/grub2/phcoder.git
diff --git a/commands/videotest.c b/commands/videotest.c
index 6fe4b9b..07f61bd 100644
--- a/commands/videotest.c
+++ b/commands/videotest.c
@@ -30,7 +30,8 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ 
((unused)),
                     int argc __attribute__ ((unused)),
                     char **args __attribute__ ((unused)))
 {
-  if (grub_video_set_mode ("1024x768;800x600;640x480", 0) != GRUB_ERR_NONE)
+  if (grub_video_set_mode ("1024x768;800x600;640x480",
+                          GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0) != GRUB_ERR_NONE)
     return grub_errno;
 
   grub_video_color_t color;
diff --git a/include/grub/video.h b/include/grub/video.h
index 4145db4..94b0467 100644
--- a/include/grub/video.h
+++ b/include/grub/video.h
@@ -171,7 +171,7 @@ struct grub_video_adapter
   grub_err_t (*fini) (void);
 
   grub_err_t (*setup) (unsigned int width,  unsigned int height,
-                       unsigned int mode_type);
+                       unsigned int mode_type, unsigned int mode_mask);
 
   grub_err_t (*get_info) (struct grub_video_mode_info *mode_info);
 
@@ -307,7 +307,7 @@ grub_err_t grub_video_set_active_render_target (struct 
grub_video_render_target
 grub_err_t grub_video_get_active_render_target (struct 
grub_video_render_target **target);
 
 grub_err_t grub_video_set_mode (const char *modestring,
-                               int NESTED_FUNC_ATTR (*hook) 
(grub_video_adapter_t p,
-                                                             struct 
grub_video_mode_info *mode_info));
+                               unsigned int modemask,
+                               unsigned int modevalue);
 
 #endif /* ! GRUB_VIDEO_HEADER */
diff --git a/loader/i386/linux.c b/loader/i386/linux.c
index 238e4cd..c5802d8 100644
--- a/loader/i386/linux.c
+++ b/loader/i386/linux.c
@@ -505,12 +505,12 @@ grub_linux_boot (void)
       if (! tmp)
        return grub_errno;
       grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
-      err = grub_video_set_mode (tmp, 0);
+      err = grub_video_set_mode (tmp, 0, 0);
       grub_free (tmp);
     }
 #ifndef GRUB_ASSUME_LINUX_HAS_FB_SUPPORT
   else
-    err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0);
+    err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
 #endif
 
   if (err)
diff --git a/loader/i386/pc/xnu.c b/loader/i386/pc/xnu.c
index 69a9405..adca8c6 100644
--- a/loader/i386/pc/xnu.c
+++ b/loader/i386/pc/xnu.c
@@ -28,15 +28,6 @@
 
 #define DEFAULT_VIDEO_MODE "1024x768x32,800x600x32,640x480x32"
 
-static int NESTED_FUNC_ATTR video_hook (grub_video_adapter_t p __attribute__ 
((unused)),
-                                       struct grub_video_mode_info *info)
-{
-  if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
-    return 0;
-
-  return 1;
-}
-
 /* Setup video for xnu. */
 grub_err_t
 grub_xnu_set_video (struct grub_xnu_boot_params *params)
@@ -49,8 +40,12 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
   grub_err_t err;
 
   modevar = grub_env_get ("gfxpayload");
+  /* Consider only graphical 32-bit deep modes.  */
   if (! modevar || *modevar == 0)
-    err = grub_video_set_mode (DEFAULT_VIDEO_MODE, video_hook);
+    err = grub_video_set_mode (DEFAULT_VIDEO_MODE,
+                              GRUB_VIDEO_MODE_TYPE_PURE_TEXT
+                              | GRUB_VIDEO_MODE_TYPE_DEPTH_MASK,
+                              32 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS);
   else
     {
       tmp = grub_malloc (grub_strlen (modevar)
@@ -59,7 +54,10 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
        return grub_error (GRUB_ERR_OUT_OF_MEMORY,
                           "couldn't allocate temporary storag");
       grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
-      err = grub_video_set_mode (tmp, video_hook);
+      err = grub_video_set_mode (tmp,
+                                GRUB_VIDEO_MODE_TYPE_PURE_TEXT
+                                | GRUB_VIDEO_MODE_TYPE_DEPTH_MASK,
+                                32 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS);
       grub_free (tmp);
     }
 
diff --git a/term/gfxterm.c b/term/gfxterm.c
index f161499..e6c6746 100644
--- a/term/gfxterm.c
+++ b/term/gfxterm.c
@@ -244,12 +244,6 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y,
   return grub_errno;
 }
 
-static int NESTED_FUNC_ATTR video_hook (grub_video_adapter_t p __attribute__ 
((unused)),
-                                       struct grub_video_mode_info *info)
-{
-  return ! (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT);
-}
-
 static grub_err_t
 grub_gfxterm_init (void)
 {
@@ -269,13 +263,15 @@ grub_gfxterm_init (void)
   /* Parse gfxmode environment variable if set.  */
   modevar = grub_env_get ("gfxmode");
   if (! modevar || *modevar == 0)
-    err = grub_video_set_mode (DEFAULT_VIDEO_MODE, video_hook);
+    err = grub_video_set_mode (DEFAULT_VIDEO_MODE,
+                              GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
   else
     {
       tmp = grub_malloc (grub_strlen (modevar)
                         + sizeof (DEFAULT_VIDEO_MODE) + 1);
       grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
-      err = grub_video_set_mode (tmp, video_hook);
+      err = grub_video_set_mode (tmp,
+                                GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
       grub_free (tmp);
     }
 
diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c
index 0244b90..c4878f6 100644
--- a/video/i386/pc/vbe.c
+++ b/video/i386/pc/vbe.c
@@ -379,7 +379,7 @@ grub_video_vbe_fini (void)
 
 static grub_err_t
 grub_video_vbe_setup (unsigned int width, unsigned int height,
-                      unsigned int mode_type)
+                      unsigned int mode_type, unsigned int mode_mask)
 {
   grub_uint16_t *p;
   struct grub_vbe_mode_info_block mode_info;
@@ -435,17 +435,22 @@ grub_video_vbe_setup (unsigned int width, unsigned int 
height,
         continue;
 
       /* Check if user requested RGB or index color mode.  */
-      if ((mode_type & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0)
+      if ((mode_mask & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0)
         {
-          if (((mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
-              && (mode_info.memory_model != 
GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL))
-            /* Requested only index color modes.  */
-            continue;
-
-          if (((mode_type & GRUB_VIDEO_MODE_TYPE_RGB) != 0)
-              && (mode_info.memory_model != 
GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
-            /* Requested only RGB modes.  */
-            continue;
+         unsigned my_mode_type = 0;
+
+         if (mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
+           my_mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+
+         if (mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR)
+           my_mode_type |= GRUB_VIDEO_MODE_TYPE_RGB;
+
+         if ((my_mode_type & mode_mask
+              & (GRUB_VIDEO_MODE_TYPE_RGB | GRUB_VIDEO_MODE_TYPE_INDEX_COLOR))
+             != (mode_type & mode_mask
+                 & (GRUB_VIDEO_MODE_TYPE_RGB
+                    | GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)))
+           continue;
         }
 
       /* If there is a request for specific depth, ignore others.  */
diff --git a/video/video.c b/video/video.c
index 36ebfd1..1c5a35d 100644
--- a/video/video.c
+++ b/video/video.c
@@ -399,8 +399,8 @@ grub_video_get_active_render_target (struct 
grub_video_render_target **target)
 
 grub_err_t
 grub_video_set_mode (const char *modestring,
-                    int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p,
-                                                  struct grub_video_mode_info 
*mode_info))
+                    unsigned int modemask,
+                    unsigned int modevalue)
 {
   char *tmp;
   char *next_mode;
@@ -408,10 +408,8 @@ grub_video_set_mode (const char *modestring,
   char *param;
   char *value;
   char *modevar;
-  int width = -1;
-  int height = -1;
-  int depth = -1;
-  int flags = 0;
+
+  modevalue &= modemask;
 
   /* Take copy of env.var. as we don't want to modify that.  */
   modevar = grub_strdup (modestring);
@@ -427,26 +425,26 @@ grub_video_set_mode (const char *modestring,
       || grub_memcmp (next_mode, "keep,", sizeof ("keep,") - 1) == 0
       || grub_memcmp (next_mode, "keep;", sizeof ("keep;") - 1) == 0)
     {
-      struct grub_video_mode_info mode_info;
       int suitable = 1;
       grub_err_t err;
 
-      grub_memset (&mode_info, 0, sizeof (mode_info));
-
       if (grub_video_adapter_active)
        {
+         struct grub_video_mode_info mode_info;
+         grub_memset (&mode_info, 0, sizeof (mode_info));
          err = grub_video_get_info (&mode_info);
          if (err)
            {
              suitable = 0;
              grub_errno = GRUB_ERR_NONE;
            }
+         if ((mode_info.mode_type & modemask) != modevalue)
+           suitable = 0;
        }
-      else
-       mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT;
+      else if (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0)
+              && ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0))
+       suitable = 0;
 
-      if (suitable && hook)
-       suitable = hook (grub_video_adapter_active, &mode_info);
       if (suitable)
        {
          grub_free (modevar);
@@ -480,15 +478,15 @@ grub_video_set_mode (const char *modestring,
   /* Loop until all modes has been tested out.  */
   while (next_mode != NULL)
     {
+      int width = -1;
+      int height = -1;
+      int depth = -1;
+      unsigned int flags = modevalue;
+      unsigned int flagmask = modemask;
+
       /* Use last next_mode as current mode.  */
       tmp = next_mode;
 
-      /* Reset video mode settings.  */
-      width = -1;
-      height = -1;
-      depth = -1;
-      flags = 0;
-
       /* Save position of next mode and separate modes.  */
       for (; *next_mode; next_mode++)
        if (*next_mode == ',' || *next_mode == ';')
@@ -517,9 +515,8 @@ grub_video_set_mode (const char *modestring,
          struct grub_video_mode_info mode_info;
 
          grub_memset (&mode_info, 0, sizeof (mode_info));
-         mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT;
-
-         if (! hook || hook (0, &mode_info))
+         if (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) == 0)
+             || ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) != 0))
            {
              /* Valid mode found from adapter, and it has been activated.
                 Specify it as active adapter.  */
@@ -635,18 +632,20 @@ grub_video_set_mode (const char *modestring,
 
       /* Try out video mode.  */
 
-      /* If we have 8 or less bits, then assume that it is indexed color mode. 
 */
-      if ((depth <= 8) && (depth != -1))
-       flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
-
-      /* We have more than 8 bits, then assume that it is RGB color mode.  */
-      if (depth > 8)
-       flags |= GRUB_VIDEO_MODE_TYPE_RGB;
+      /* If user requested specific depth check if this depth is supported.  */
+      if (depth != -1 && (flagmask & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
+         &&
+         (((flags & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
+           != ((depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
+               & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK))))
+       continue;
 
-      /* If user requested specific depth, forward that information to driver. 
 */
       if (depth != -1)
-       flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
-         & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
+       {
+         flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
+           & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
+         flagmask |= GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
+       }
 
       /* Try to initialize requested mode.  Ignore any errors.  */
       grub_video_adapter_t p;
@@ -668,7 +667,7 @@ grub_video_set_mode (const char *modestring,
            }
 
          /* Try to initialize video mode.  */
-         err = p->setup (width, height, flags);
+         err = p->setup (width, height, flags, flagmask);
          if (err != GRUB_ERR_NONE)
            {
              p->fini ();
@@ -684,7 +683,15 @@ grub_video_set_mode (const char *modestring,
              continue;
            }
 
-         if (hook && ! hook (p, &mode_info))
+         flags = mode_info.mode_type & ~GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
+         flags |= (mode_info.bpp << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
+           & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
+
+         /* Check that mode is suitable for upper layer.  */
+         if ((flags & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
+             ? (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0)
+                && ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0))
+             : ((flags & modemask) != modevalue))
            {
              p->fini ();
              grub_errno = GRUB_ERR_NONE;
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to