]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
REimport of videomask patch
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sat, 14 Nov 2009 15:25:50 +0000 (16:25 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sat, 14 Nov 2009 15:25:50 +0000 (16:25 +0100)
commands/videotest.c
include/grub/video.h
loader/i386/linux.c
loader/i386/pc/xnu.c
term/gfxterm.c
video/i386/pc/vbe.c
video/video.c

index 6fe4b9bd1e560031bdb0e9c10e2b7e64642bf234..fe504ee7bce5bc12de19122d7a011f4271ea6355 100644 (file)
@@ -30,9 +30,7 @@ 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)
-    return grub_errno;
-
+  grub_err_t err;
   grub_video_color_t color;
   unsigned int x;
   unsigned int y;
@@ -49,6 +47,10 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
   const char *str;
   int texty;
 
+  err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
+  if (err)
+    return err;
+
   grub_video_get_viewport (&x, &y, &width, &height);
 
   grub_video_create_render_target (&text_layer, width, height,
@@ -152,12 +154,13 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
 
   grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
 
-  for (i = 0; i < 255; i++)
+  for (i = 0; i < 5; i++)
     {
       color = grub_video_map_rgb (i, 33, 77);
       grub_video_fill_rect (color, 0, 0, width, height);
       grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, 0, 0,
                                      0, 0, width, height);
+      grub_video_swap_buffers ();
     }
 
   grub_getkey ();
index 4145db46516172a84fbf25c3ac05153535a40a0f..53fe67c4e42393402345e7763e3efa9fee874289 100644 (file)
@@ -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,14 @@ 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);
+
+static inline int
+grub_video_check_mode_flag (unsigned int flags, unsigned int mask,
+                           unsigned int flag, int def)
+{
+  return (flag & mask) ? !! (flags & flag) : def;
+}
 
 #endif /* ! GRUB_VIDEO_HEADER */
index 4bdb09b240b15f63115e64165918117a50d2fad5..8659e8245758a5e22d6d859a67b6652504218c30 100644 (file)
@@ -523,11 +523,11 @@ grub_linux_boot (void)
       if (! tmp)
        return grub_errno;
       grub_sprintf (tmp, "%s;text", modevar);
-      err = grub_video_set_mode (tmp, 0);
+      err = grub_video_set_mode (tmp, 0, 0);
       grub_free (tmp);
     }
   else
-    err = grub_video_set_mode ("text", 0);
+    err = grub_video_set_mode ("text", 0, 0);
 
   if (err)
     {
index ebb176bb41951ecbe20d465493903ef9bb5e00c9..839d0ad44d82f5ac9c43021856185fbb13dfc96e 100644 (file)
 #define min(a,b) (((a) < (b)) ? (a) : (b))
 #define max(a,b) (((a) > (b)) ? (a) : (b))
 
-#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;
-}
+#define DEFAULT_VIDEO_MODE "auto"
 
 /* Setup video for xnu. */
 grub_err_t
@@ -48,8 +39,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)
@@ -58,7 +53,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);
     }
 
index f161499e6f9137d9ac42919113427383cb0f6759..57c51cffa884c3351ee35c16c63afd9acba071f0 100644 (file)
@@ -27,7 +27,7 @@
 #include <grub/bitmap.h>
 #include <grub/command.h>
 
-#define DEFAULT_VIDEO_MODE "1024x768,800x600,640x480"
+#define DEFAULT_VIDEO_MODE "auto"
 #define DEFAULT_BORDER_WIDTH   10
 
 #define DEFAULT_STANDARD_COLOR  0x07
@@ -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);
     }
 
index a285b26ba881e43bb9737bdf8ee92b6dd40ecb04..8759ba652ebde26c20bf0d8c20e31b1502ae3862 100644 (file)
@@ -362,7 +362,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 vbe_mode_info;
@@ -412,32 +412,40 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
         /* Not compatible memory model.  */
         continue;
 
-      if ((vbe_mode_info.x_resolution != width)
-          || (vbe_mode_info.y_resolution != height))
+      if (((vbe_mode_info.x_resolution != width)
+          || (vbe_mode_info.y_resolution != height)) && width != 0 && height != 0)
         /* Non matching resolution.  */
         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)
-              && (vbe_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)
-              && (vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
-            /* Requested only RGB modes.  */
-            continue;
+         unsigned my_mode_type = 0;
+
+         if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
+           my_mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+
+         if (vbe_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.  */
       if ((depth != 0) && (vbe_mode_info.bits_per_pixel != depth))
         continue;
 
-      /* Select mode with most number of bits per pixel.  */
+      /* Select mode with most of "volume" (size of framebuffer in bits).  */
       if (best_vbe_mode != 0)
-        if (vbe_mode_info.bits_per_pixel < best_vbe_mode_info.bits_per_pixel)
+        if ((grub_uint64_t) vbe_mode_info.bits_per_pixel
+           * vbe_mode_info.x_resolution * vbe_mode_info.y_resolution
+           < (grub_uint64_t) best_vbe_mode_info.bits_per_pixel
+           * best_vbe_mode_info.x_resolution * best_vbe_mode_info.y_resolution)
           continue;
 
       /* Save so far best mode information for later use.  */
index c1d66bdd00a458ee69c2094cd4ba23cccdd72a74..eff257122272a2897b951461af8ad906172d8633 100644 (file)
@@ -399,21 +399,81 @@ grub_video_get_active_render_target (struct grub_video_render_target **target)
   return grub_video_adapter_active->get_active_render_target (target);
 }
 
+/* Parse <width>x<height>[x<depth>]*/
+static grub_err_t
+parse_modespec (const char *current_mode, int *width, int *height, int *depth)
+{
+  const char *value;
+  const char *param = current_mode;
+
+  *width = *height = *depth = -1;
+
+  if (grub_strcmp (param, "auto") == 0)
+    {
+      *width = *height = 0;
+      return GRUB_ERR_NONE;
+    }
+
+  /* Find width value.  */
+  value = param;
+  param = grub_strchr(param, 'x');
+  if (param == NULL)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                      "Invalid mode: %s\n",
+                      current_mode);
+
+  param++;
+  
+  *width = grub_strtoul (value, 0, 0);
+  if (grub_errno != GRUB_ERR_NONE)
+      return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                        "Invalid mode: %s\n",
+                        current_mode);
+  
+  /* Find height value.  */
+  value = param;
+  param = grub_strchr(param, 'x');
+  if (param == NULL)
+    {
+      *height = grub_strtoul (value, 0, 0);
+      if (grub_errno != GRUB_ERR_NONE)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                          "Invalid mode: %s\n",
+                          current_mode);
+    }
+  else
+    {
+      /* We have optional color depth value.  */
+      param++;
+      
+      *height = grub_strtoul (value, 0, 0);
+      if (grub_errno != GRUB_ERR_NONE)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                          "Invalid mode: %s\n",
+                          current_mode);
+      
+      /* Convert color depth value.  */
+      value = param;
+      *depth = grub_strtoul (value, 0, 0);
+      if (grub_errno != GRUB_ERR_NONE)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                          "Invalid mode: %s\n",
+                          current_mode);
+    }
+  return GRUB_ERR_NONE;
+}
+
 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;
   char *current_mode;
-  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);
@@ -429,26 +489,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);
@@ -482,15 +542,16 @@ 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;
+      grub_err_t err;
+      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 == ';')
@@ -509,19 +570,16 @@ grub_video_set_mode (const char *modestring,
 
       /* Initialize token holders.  */
       current_mode = tmp;
-      param = tmp;
-      value = NULL;
 
       /* XXX: we assume that we're in pure text mode if
         no video mode is initialized. Is it always true? */
-      if (grub_strcmp (param, "text") == 0)
+      if (grub_strcmp (current_mode, "text") == 0)
        {
          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.  */
@@ -534,121 +592,31 @@ grub_video_set_mode (const char *modestring,
            }
        }
 
-      /* Parse <width>x<height>[x<depth>]*/
-
-      /* Find width value.  */
-      value = param;
-      param = grub_strchr(param, 'x');
-      if (param == NULL)
+      err = parse_modespec (current_mode, &width, &height, &depth);
+      if (err)
        {
-         grub_err_t rc;
-
-         /* First setup error message.  */
-         rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
-                          "Invalid mode: %s\n",
-                          current_mode);
-
          /* Free memory before returning.  */
          grub_free (modevar);
 
-         return rc;
-       }
-
-      *param = 0;
-      param++;
-
-      width = grub_strtoul (value, 0, 0);
-      if (grub_errno != GRUB_ERR_NONE)
-       {
-         grub_err_t rc;
-
-         /* First setup error message.  */
-         rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
-                          "Invalid mode: %s\n",
-                          current_mode);
-
-         /* Free memory before returning.  */
-         grub_free (modevar);
-
-         return rc;
-       }
-
-      /* Find height value.  */
-      value = param;
-      param = grub_strchr(param, 'x');
-      if (param == NULL)
-       {
-         height = grub_strtoul (value, 0, 0);
-         if (grub_errno != GRUB_ERR_NONE)
-           {
-             grub_err_t rc;
-
-             /* First setup error message.  */
-             rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
-                              "Invalid mode: %s\n",
-                              current_mode);
-
-             /* Free memory before returning.  */
-             grub_free (modevar);
-
-             return rc;
-           }
-       }
-      else
-       {
-         /* We have optional color depth value.  */
-         *param = 0;
-         param++;
-
-         height = grub_strtoul (value, 0, 0);
-         if (grub_errno != GRUB_ERR_NONE)
-           {
-             grub_err_t rc;
-
-             /* First setup error message.  */
-             rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
-                              "Invalid mode: %s\n",
-                              current_mode);
-
-             /* Free memory before returning.  */
-             grub_free (modevar);
-
-             return rc;
-           }
-
-         /* Convert color depth value.  */
-         value = param;
-         depth = grub_strtoul (value, 0, 0);
-         if (grub_errno != GRUB_ERR_NONE)
-           {
-             grub_err_t rc;
-
-             /* First setup error message.  */
-             rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
-                              "Invalid mode: %s\n",
-                              current_mode);
-
-             /* Free memory before returning.  */
-             grub_free (modevar);
-
-             return rc;
-           }
+         return err;
        }
 
       /* 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;
@@ -670,7 +638,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 ();
@@ -686,7 +654,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;