Skip to contentSkip to conversation

GSoC #06 VBE optimization for BGR/BGRA color modes

PATCH In review Colin D Bennett 2 participants 2 messages Aug 31, 2008 – Sep 7, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 GSoC #06 VBE optimization for BGR/BGRA color modes

This patch adds optimized routines for video modes using BGR/BGRA color format. Most PC video cards use BGR (24-bit) or BGRA (32-bit) color modes, so this is an extremely important change and provides a massive performance benefit.

I also renamed the R8G8B8A8 and R8B8B8 modes to RGBA8888 and RGB888, etc., since it began to be highly unreadable when B8G8R8A8 was added into the mix. It seems that having the color components (letters) grouped together in the name makes it much easier for me to determine the mode name at a glance.

Regards,
Colin

2008-08-30 Colin D Bennett <[email protected]>

	VBE performance optimization.  Added optimized rendering functions for
	BGR/BGRA render targets.

	* include/grub/i386/pc/vbeblit.h
	(grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8): Renamed from this...
	(grub_video_i386_vbeblit_RGBA8888_RGBA8888): ...to this.
	(grub_video_i386_vbeblit_R8G8B8_R8G8B8A8): Renamed from this...
	(grub_video_i386_vbeblit_RGB888_RGBA8888): ...to this.
	(grub_video_i386_vbeblit_R8G8B8_R8G8B8X8): Renamed from this...
	(grub_video_i386_vbeblit_RGB888_RGBX8888): ...to this.
	(grub_video_i386_vbeblit_index_R8G8B8A8): Renamed from this...
	(grub_video_i386_vbeblit_index_RGBA8888): ...to this.
	(grub_video_i386_vbeblit_index_R8G8B8X8): Renamed from this...
	(grub_video_i386_vbeblit_index_RGBX8888): ...to this.
	(grub_video_i386_vbeblit_R8G8B8A8_R8G8B8): Renamed from this...
	(grub_video_i386_vbeblit_RGBA8888_RGB888): ...to this.
	(grub_video_i386_vbeblit_R8G8B8_R8G8B8): Renamed from this...
	(grub_video_i386_vbeblit_RGB888_RGB888): ...to this.
	(grub_video_i386_vbeblit_index_R8G8B8): Renamed from this...
	(grub_video_i386_vbeblit_index_RGB888): ...to this.
	(grub_video_i386_vbeblit_BGRX8888_RGBX8888): New prototype.
	(grub_video_i386_vbeblit_BGRA8888_RGB888): New prototype.
	(grub_video_i386_vbeblit_BGR888_RGB888): New prototype.
	(grub_video_i386_vbeblit_BGRA8888_RGBA8888): New prototype.
	(grub_video_i386_vbeblit_BGR888_RGBA8888): New prototype.
	(grub_video_i386_vbeblit_BGR888_RGBX8888): New prototype.
	(grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8): Renamed from this...
	(grub_video_i386_vbeblit_direct32_copy): ...to this.

	* video/i386/pc/vbeblit.c
	(grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8): Renamed from this...
	(grub_video_i386_vbeblit_RGBA8888_RGBA8888): ...to this.
	(grub_video_i386_vbeblit_R8G8B8_R8G8B8A8): Renamed from this...
	(grub_video_i386_vbeblit_RGB888_RGBA8888): ...to this.
	(grub_video_i386_vbeblit_R8G8B8_R8G8B8X8): Renamed from this...
	(grub_video_i386_vbeblit_RGB888_RGBX8888): ...to this.
	(grub_video_i386_vbeblit_index_R8G8B8A8): Renamed from this...
	(grub_video_i386_vbeblit_index_RGBA8888): ...to this.
	(grub_video_i386_vbeblit_index_R8G8B8X8): Renamed from this...
	(grub_video_i386_vbeblit_index_RGBX8888): ...to this.
	(grub_video_i386_vbeblit_R8G8B8A8_R8G8B8): Renamed from this...
	(grub_video_i386_vbeblit_RGBA8888_RGB888): ...to this.
	(grub_video_i386_vbeblit_R8G8B8_R8G8B8): Renamed from this...
	(grub_video_i386_vbeblit_RGB888_RGB888): ...to this.
	(grub_video_i386_vbeblit_index_R8G8B8): Renamed from this...
	(grub_video_i386_vbeblit_index_RGB888): ...to this.
	(grub_video_i386_vbeblit_BGRX8888_RGBX8888): New function.
	(grub_video_i386_vbeblit_BGRA8888_RGB888): New function.
	(grub_video_i386_vbeblit_BGR888_RGB888): New function.
	(grub_video_i386_vbeblit_BGRA8888_RGBA8888): New function.
	(grub_video_i386_vbeblit_BGR888_RGBA8888): New function.
	(grub_video_i386_vbeblit_BGR888_RGBX8888): New function.
	(grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8): Renamed from this...
	(grub_video_i386_vbeblit_direct32_copy): ...to this.

	* include/grub/i386/pc/vbefill.h
	(grub_video_i386_vbefill_R8G8B8A8): Renamed from this..
	(grub_video_i386_vbefill_direct32): ...to this.
	(grub_video_i386_vbefill_R8G8B8): Renamed from this...
	(grub_video_i386_vbefill_direct24): ...to this.

	* include/grub/video.h (grub_video_blit_format): Added BGR/BGRA modes
	and renamed R8G8B8A->RGBA_8888.
	* video/bitmap.c (grub_video_bitmap_create): Use new blit format
	names.
	* video/i386/pc/vbe.c (grub_video_vbe_fill_rect): Use optimized
	BGR/BGRA fill routines; use new RGB/RGBA blit format names.
	(common_blitter): Use optimized BGR/BGRA blit routines; use new
	RGB/RGBA blit format names.

	* video/i386/pc/vbefill.c 
	(grub_video_i386_vbefill_R8G8B8A8): Renamed from this...
	(grub_video_i386_vbefill_direct32): ...to this; don't re-calculate the
	video pointer position every row.
	(grub_video_i386_vbefill_R8G8B8): Renamed from this...
	(grub_video_i386_vbefill_direct24): ...to this; don't re-calculate the
	video pointer position every row.
	(grub_video_i386_vbefill_index): Don't re-calculate the video pointer
	position every row.

	* video/readers/jpeg.c (grub_jpeg_decode_sos): Use new blit format
	name.
	* video/readers/png.c (grub_png_decode_image_header): Likewise.
	* video/readers/tga.c (grub_video_reader_tga): Likewise.

	* video/video.c (grub_video_get_blit_format): Detect BGR/BGRA blit
	formats, and also detect a wider range of RGB/RGBA formats.

=== modified file 'include/grub/i386/pc/vbeblit.h'

grub/i386/pc/vbeblit.h +87 -49
@@ -25,55 +25,93 @@
 struct grub_video_i386_vbeblit_info;
 
 void
-grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (struct grub_video_i386_vbeblit_info *dst,
-                                           struct grub_video_i386_vbeblit_info *src,
-                                           int x, int y, int width, int height,
-                                           int offset_x, int offset_y);
-
-void
-grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8 (struct grub_video_i386_vbeblit_info *dst,
-                                           struct grub_video_i386_vbeblit_info *src,
-                                           int x, int y, int width, int height,
-                                           int offset_x, int offset_y);
-
-void
-grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (struct grub_video_i386_vbeblit_info *dst,
-                                         struct grub_video_i386_vbeblit_info *src,
-                                         int x, int y, int width, int height,
-                                         int offset_x, int offset_y);
-
-void
-grub_video_i386_vbeblit_R8G8B8_R8G8B8X8 (struct grub_video_i386_vbeblit_info *dst,
-                                         struct grub_video_i386_vbeblit_info *src,
-                                         int x, int y, int width, int height,
-                                         int offset_x, int offset_y);
-
-void
-grub_video_i386_vbeblit_index_R8G8B8A8 (struct grub_video_i386_vbeblit_info *dst,
-                                        struct grub_video_i386_vbeblit_info *src,
-                                        int x, int y, int width, int height,
-                                        int offset_x, int offset_y);
-
-void
-grub_video_i386_vbeblit_index_R8G8B8X8 (struct grub_video_i386_vbeblit_info *dst,
-                                        struct grub_video_i386_vbeblit_info *src,
-                                        int x, int y, int width, int height,
-                                        int offset_x, int offset_y);
-
-void
-grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_i386_vbeblit_info *dst,
-                                         struct grub_video_i386_vbeblit_info *src,
-                                         int x, int y, int width, int height,
-                                         int offset_x, int offset_y);
-
-void
-grub_video_i386_vbeblit_R8G8B8_R8G8B8 (struct grub_video_i386_vbeblit_info *dst,
-                                       struct grub_video_i386_vbeblit_info *src,
-                                       int x, int y, int width, int height,
-                                       int offset_x, int offset_y);
-
-void
-grub_video_i386_vbeblit_index_R8G8B8 (struct grub_video_i386_vbeblit_info *dst,
+grub_video_i386_vbeblit_BGRX8888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst,
+                                           struct grub_video_i386_vbeblit_info *src,
+                                           int x, int y, int width, int height,
+                                           int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_BGRA8888_RGB888 (struct grub_video_i386_vbeblit_info *dst,
+                                         struct grub_video_i386_vbeblit_info *src,
+                                         int x, int y, int width, int height,
+                                         int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_BGR888_RGB888 (struct grub_video_i386_vbeblit_info *dst,
+                                       struct grub_video_i386_vbeblit_info *src,
+                                       int x, int y, int width, int height,
+                                       int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_BGRA8888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                           struct grub_video_i386_vbeblit_info *src,
+                                           int x, int y, int width, int height,
+                                           int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_BGR888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                         struct grub_video_i386_vbeblit_info *src,
+                                         int x, int y, int width, int height,
+                                         int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_BGR888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst,
+                                         struct grub_video_i386_vbeblit_info *src,
+                                         int x, int y, int width, int height,
+                                         int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_RGBA8888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                           struct grub_video_i386_vbeblit_info *src,
+                                           int x, int y, int width, int height,
+                                           int offset_x, int offset_y);
+
+/* Direct copy for compatible 32 bpp blit formats.
+ * (RGBA8888->RGBA8888, BGRA8888->BGRA8888, etc.) */
+void
+grub_video_i386_vbeblit_direct32_copy (struct grub_video_i386_vbeblit_info *dst,
+                                       struct grub_video_i386_vbeblit_info *src,
+                                       int x, int y, int width, int height,
+                                       int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_RGB888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                         struct grub_video_i386_vbeblit_info *src,
+                                         int x, int y, int width, int height,
+                                         int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_RGB888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst,
+                                         struct grub_video_i386_vbeblit_info *src,
+                                         int x, int y, int width, int height,
+                                         int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_index_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                        struct grub_video_i386_vbeblit_info *src,
+                                        int x, int y, int width, int height,
+                                        int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_index_RGBX8888 (struct grub_video_i386_vbeblit_info *dst,
+                                        struct grub_video_i386_vbeblit_info *src,
+                                        int x, int y, int width, int height,
+                                        int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_RGBA8888_RGB888 (struct grub_video_i386_vbeblit_info *dst,
+                                         struct grub_video_i386_vbeblit_info *src,
+                                         int x, int y, int width, int height,
+                                         int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_RGB888_RGB888 (struct grub_video_i386_vbeblit_info *dst,
+                                       struct grub_video_i386_vbeblit_info *src,
+                                       int x, int y, int width, int height,
+                                       int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_index_RGB888 (struct grub_video_i386_vbeblit_info *dst,
                                       struct grub_video_i386_vbeblit_info *src,
                                       int x, int y, int width, int height,
                                       int offset_x, int offset_y);

=== modified file 'include/grub/i386/pc/vbefill.h'

grub/i386/pc/vbefill.h +4 -4
@@ -25,14 +25,14 @@
 struct grub_video_i386_vbeblit_info;
 
 void
-grub_video_i386_vbefill_R8G8B8A8 (struct grub_video_i386_vbeblit_info *dst,
+grub_video_i386_vbefill_direct32 (struct grub_video_i386_vbeblit_info *dst,
                                   grub_video_color_t color,  int x, int y,
                                   int width, int height);
 
 void
-grub_video_i386_vbefill_R8G8B8 (struct grub_video_i386_vbeblit_info *dst,
-                                grub_video_color_t color, int x, int y,
-                                int width, int height);
+grub_video_i386_vbefill_direct24 (struct grub_video_i386_vbeblit_info *dst,
+                                  grub_video_color_t color, int x, int y,
+                                  int width, int height);
 
 void
 grub_video_i386_vbefill_index (struct grub_video_i386_vbeblit_info *dst,

=== modified file 'include/grub/video.h'

grub/video.h +6 -8
@@ -55,14 +55,12 @@
 /* Defined blitting formats.  */
 enum grub_video_blit_format
   {
-    /* Follow exactly field & mask information.  */
-    GRUB_VIDEO_BLIT_FORMAT_RGBA,
-    /* Make optimization assumption.  */
-    GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8,
-    /* Follow exactly field & mask information.  */
-    GRUB_VIDEO_BLIT_FORMAT_RGB,
-    /* Make optimization assumption.  */
-    GRUB_VIDEO_BLIT_FORMAT_R8G8B8,
+    GRUB_VIDEO_BLIT_FORMAT_RGBA,       /* General: Use fields & masks. */
+    GRUB_VIDEO_BLIT_FORMAT_RGBA_8888,  /* Optimized format. */
+    GRUB_VIDEO_BLIT_FORMAT_BGRA_8888,  /* Optimized format. */
+    GRUB_VIDEO_BLIT_FORMAT_RGB,        /* General: Use fields & masks. */
+    GRUB_VIDEO_BLIT_FORMAT_RGB_888,    /* Optimized format. */
+    GRUB_VIDEO_BLIT_FORMAT_BGR_888,    /* Optimized format. */
     /* When needed, decode color or just use value as is.  */
     GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR
   };

=== modified file 'video/bitmap.c'

bitmap.c +2 -2
@@ -78,7 +78,7 @@
 
   switch (blit_format)
     {
-      case GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8:
+      case GRUB_VIDEO_BLIT_FORMAT_RGBA_8888:
         mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_RGB 
                                | GRUB_VIDEO_MODE_TYPE_ALPHA;
         mode_info->bpp = 32;
@@ -94,7 +94,7 @@
         mode_info->reserved_field_pos = 24;
         break;
 
-      case GRUB_VIDEO_BLIT_FORMAT_R8G8B8:
+      case GRUB_VIDEO_BLIT_FORMAT_RGB_888:
         mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
         mode_info->bpp = 24;
         mode_info->bytes_per_pixel = 3;

=== modified file 'video/i386/pc/vbe.c'

i386/pc/vbe.c +140 -58

267 lines not on this page · raw message

=== modified file 'video/i386/pc/vbeblit.c'

i386/pc/vbeblit.c +348 -12

414 lines not on this page · raw message

=== modified file 'video/i386/pc/vbefill.c'

i386/pc/vbefill.c +41 -26

119 lines not on this page · raw message

=== modified file 'video/readers/jpeg.c'

readers/jpeg.c +1 -1
@@ -542,7 +542,7 @@
 
   if (grub_video_bitmap_create (data->bitmap, data->image_width,
 				data->image_height,
-				GRUB_VIDEO_BLIT_FORMAT_R8G8B8))
+				GRUB_VIDEO_BLIT_FORMAT_RGB_888))
     return grub_errno;
 
   data->bit_mask = 0x0;

=== modified file 'video/readers/png.c'

readers/png.c +2 -2
@@ -231,7 +231,7 @@
     {
       if (grub_video_bitmap_create (data->bitmap, data->image_width,
 				    data->image_height,
-				    GRUB_VIDEO_BLIT_FORMAT_R8G8B8))
+				    GRUB_VIDEO_BLIT_FORMAT_RGB_888))
 	return grub_errno;
       data->bpp = 3;
     }
@@ -239,7 +239,7 @@
     {
       if (grub_video_bitmap_create (data->bitmap, data->image_width,
 				    data->image_height,
-				    GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8))
+				    GRUB_VIDEO_BLIT_FORMAT_RGBA_8888))
 	return grub_errno;
       data->bpp = 4;
     }

=== modified file 'video/readers/tga.c'

readers/tga.c +2 -2
@@ -397,7 +397,7 @@
     {
       grub_video_bitmap_create (bitmap, header.image_width,
                                 header.image_height,
-                                GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8);
+                                GRUB_VIDEO_BLIT_FORMAT_RGBA_8888);
       if (grub_errno != GRUB_ERR_NONE)
         {
           grub_file_close (file);
@@ -420,7 +420,7 @@
     {
       grub_video_bitmap_create (bitmap, header.image_width,
                                 header.image_height,
-                                GRUB_VIDEO_BLIT_FORMAT_R8G8B8);
+                                GRUB_VIDEO_BLIT_FORMAT_RGB_888);
       if (grub_errno != GRUB_ERR_NONE)
         {
           grub_file_close (file);

=== modified file 'video/video.c'

video.c +21 -5
@@ -152,15 +152,22 @@
   if (mode_info->bpp == 32)
     {
       if ((mode_info->red_mask_size == 8)
+          && (mode_info->red_field_pos == 16)
+          && (mode_info->green_mask_size == 8)
+          && (mode_info->green_field_pos == 8)
+          && (mode_info->blue_mask_size == 8)
+          && (mode_info->blue_field_pos == 0))
+        {
+          return GRUB_VIDEO_BLIT_FORMAT_BGRA_8888;
+        }
+      if ((mode_info->red_mask_size == 8)
           && (mode_info->red_field_pos == 0)
           && (mode_info->green_mask_size == 8)
           && (mode_info->green_field_pos == 8)
           && (mode_info->blue_mask_size == 8)
-          && (mode_info->blue_field_pos == 16)
-          && (mode_info->reserved_mask_size == 8)
-          && (mode_info->reserved_field_pos == 24))
+          && (mode_info->blue_field_pos == 16))
         {
-          return GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8;
+          return GRUB_VIDEO_BLIT_FORMAT_RGBA_8888;
         }
     }
 
@@ -168,13 +175,22 @@
   if (mode_info->bpp == 24)
     {
       if ((mode_info->red_mask_size == 8)
+          && (mode_info->red_field_pos == 16)
+          && (mode_info->green_mask_size == 8)
+          && (mode_info->green_field_pos == 8)
+          && (mode_info->blue_mask_size == 8)
+          && (mode_info->blue_field_pos == 0))
+        {
+          return GRUB_VIDEO_BLIT_FORMAT_BGR_888;
+        }
+      if ((mode_info->red_mask_size == 8)
           && (mode_info->red_field_pos == 0)
           && (mode_info->green_mask_size == 8)
           && (mode_info->green_field_pos == 8)
           && (mode_info->blue_mask_size == 8)
           && (mode_info->blue_field_pos == 16))
         {
-          return GRUB_VIDEO_BLIT_FORMAT_R8G8B8;
+          return GRUB_VIDEO_BLIT_FORMAT_RGB_888;
         }
     }
 
#1 lore raw
Quoted 10 lines · Colin D Bennett

This patch adds optimized routines for video modes using BGR/BGRA color format. Most PC video cards use BGR (24-bit) or BGRA (32-bit) color modes, so this is an extremely important change and provides a massive performance benefit.

I also renamed the R8G8B8A8 and R8B8B8 modes to RGBA8888 and RGB888, etc., since it began to be highly unreadable when B8G8R8A8 was added into the mix. It seems that having the color components (letters) grouped together in the name makes it much easier for me to determine the mode name at a glance.

Thanks for the patch. I have committed similar version to SVN.

I made some changes there so apologies if it broke something in between. I was only able to test it on qemu and it was ok there, but that is far from complete test. So please test it on real hardware with different cards and if problems are found report them back.

Thanks,
Vesa Jääskeläinen