* [PATCH] Optimised 1bit blitters
@ 2009-08-21 15:33 Vladimir 'phcoder' Serbinenko
2009-08-23 10:48 ` Robert Millan
0 siblings, 1 reply; 7+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-08-21 15:33 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 280 bytes --]
Hello. Glyphs are 1-bit bitmaps and when they are blitted currently
generic and slow blitter is used. This patch adds optimised blitters
and this make text rendering faster
--
Regards
Vladimir 'phcoder' Serbinenko
Personal git repository: http://repo.or.cz/w/grub2/phcoder.git
[-- Attachment #2: 1bit.diff --]
[-- Type: text/plain, Size: 22900 bytes --]
diff --git a/ChangeLog b/ChangeLog
index b76fe38..7d86044 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2009-08-21 Vladimir Serbinenko <phcoder@gmail.com>
+
+ 1-bit optimised blitters.
+
+ * include/grub/fbblit.h (grub_video_fbblit_replace_32bit_1bit): New
+ prototype.
+ (grub_video_fbblit_replace_24bit_1bit): Likewise.
+ (grub_video_fbblit_replace_16bit_1bit): Likewise.
+ (grub_video_fbblit_replace_8bit_1bit): Likewise.
+ (grub_video_fbblit_blend_XXXA8888_1bit): Likewise.
+ (grub_video_fbblit_blend_XXX888_1bit): Likewise.
+ (grub_video_fbblit_blend_XXX565_1bit): Likewise.
+ * video/fb/fbblit.c (grub_video_fbblit_replace_32bit_1bit): New
+ function.
+ (grub_video_fbblit_replace_24bit_1bit): Likewise.
+ (grub_video_fbblit_replace_16bit_1bit): Likewise.
+ (grub_video_fbblit_replace_8bit_1bit): Likewise.
+ (grub_video_fbblit_blend_XXXA8888_1bit): Likewise.
+ (grub_video_fbblit_blend_XXX888_1bit): Likewise.
+ (grub_video_fbblit_blend_XXX565_1bit): Likewise.
+ * video/fb/video_fb.c (common_blitter): Use 1-bit optimised blitters
+ when possible.
+ * video/video.c (grub_video_get_blit_format): Return
+ GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED if bpp = 1.
+
2009-08-17 Michal Suchanek <hramrach@centrum.cz>
VBE cleanup.
diff --git a/include/grub/fbblit.h b/include/grub/fbblit.h
index 664f508..af97dfb 100644
--- a/include/grub/fbblit.h
+++ b/include/grub/fbblit.h
@@ -131,4 +131,52 @@ grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst,
int width, int height,
int offset_x, int offset_y);
+void
+grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
+
+void
+grub_video_fbblit_replace_24bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
+
+void
+grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
+
+void
+grub_video_fbblit_replace_8bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
+
+void
+grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
+
+void
+grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
+
+void
+grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
#endif /* ! GRUB_FBBLIT_HEADER */
diff --git a/video/fb/fbblit.c b/video/fb/fbblit.c
index 5b613bc..fe32bae 100644
--- a/video/fb/fbblit.c
+++ b/video/fb/fbblit.c
@@ -90,6 +90,302 @@ grub_video_fbblit_replace_directN (struct grub_video_fbblit_info *dst,
}
}
+/* Optimized replacing blitter for 1-bit to 32bit. */
+void
+grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint32_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ if (*srcptr & srcmask)
+ *(grub_uint32_t *) dstptr = fgcolor;
+ else
+ *(grub_uint32_t *) dstptr = bgcolor;
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr += 4;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
+
+
+/* Optimized replacing blitter for 1-bit to 24-bit. */
+void
+grub_video_fbblit_replace_24bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint32_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width - 1; i++)
+ {
+ if (*srcptr & srcmask)
+ *(grub_uint32_t *) dstptr = fgcolor;
+ else
+ *(grub_uint32_t *) dstptr = bgcolor;
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr += 3;
+ }
+
+ if (*srcptr & srcmask)
+ {
+ *dstptr++ = fgcolor & 0xff;
+ *dstptr++ = (fgcolor & 0xff00) >> 8;
+ *dstptr++ = (fgcolor & 0xff0000) >> 16;
+ }
+ else
+ {
+ *dstptr++ = bgcolor & 0xff;
+ *dstptr++ = (bgcolor & 0xff00) >> 8;
+ *dstptr++ = (bgcolor & 0xff0000) >> 16;
+ }
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
+
+/* Optimized replacing blitter for 1-bit to 16-bit. */
+void
+grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint16_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ if (*srcptr & srcmask)
+ *(grub_uint16_t *) dstptr = fgcolor;
+ else
+ *(grub_uint16_t *) dstptr = bgcolor;
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr += 2;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
+
+/* Optimized replacing blitter for 1-bit to 8-bit. */
+void
+grub_video_fbblit_replace_8bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint8_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ if (*srcptr & srcmask)
+ *(grub_uint8_t *) dstptr = fgcolor;
+ else
+ *(grub_uint8_t *) dstptr = bgcolor;
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr++;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
+
/* Optimized replacing blitter for RGBX8888 to BGRX8888. */
void
grub_video_fbblit_replace_BGRX8888_RGBX8888 (struct grub_video_fbblit_info *dst,
@@ -826,3 +1122,294 @@ grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst,
}
}
}
+
+/* Optimized replacing blitter for 1-bit to XXXA8888. */
+void
+grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint32_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ grub_uint32_t color;
+ grub_uint8_t a;
+
+ if (*srcptr & srcmask)
+ color = fgcolor;
+ else
+ color = bgcolor;
+ a = (color >> 24) & 0xff;
+
+ if (a == 255)
+ *(grub_uint32_t *) dstptr = color;
+ else if (a != 0)
+ {
+ grub_uint8_t s1 = (color >> 0) & 0xFF;
+ grub_uint8_t s2 = (color >> 8) & 0xFF;
+ grub_uint8_t s3 = (color >> 16) & 0xFF;
+
+ grub_uint8_t d1 = (*(grub_uint32_t *) dstptr >> 0) & 0xFF;
+ grub_uint8_t d2 = (*(grub_uint32_t *) dstptr >> 8) & 0xFF;
+ grub_uint8_t d3 = (*(grub_uint32_t *) dstptr >> 16) & 0xFF;
+
+ d1 = (d1 * (255 - a) + s1 * a) / 255;
+ d2 = (d2 * (255 - a) + s2 * a) / 255;
+ d3 = (d3 * (255 - a) + s3 * a) / 255;
+
+ *(grub_uint32_t *) dstptr = (a << 24) | (d3 << 16) | (d2 << 8)
+ | d1;
+ }
+
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr += 4;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
+
+/* Optimized replacing blitter for 1-bit to XXX888. */
+void
+grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint32_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ grub_uint32_t color;
+ grub_uint8_t a;
+ if (*srcptr & srcmask)
+ {
+ color = fgcolor;
+ a = src->mode_info->fg_alpha;
+ }
+ else
+ {
+ color = bgcolor;
+ a = src->mode_info->bg_alpha;
+ }
+
+ if (a == 255)
+ {
+ ((grub_uint8_t *) dstptr)[0] = color & 0xff;
+ ((grub_uint8_t *) dstptr)[1] = (color & 0xff00) >> 8;
+ ((grub_uint8_t *) dstptr)[2] = (color & 0xff0000) >> 16;
+ }
+ else if (a != 0)
+ {
+ grub_uint8_t s1 = (color >> 0) & 0xFF;
+ grub_uint8_t s2 = (color >> 8) & 0xFF;
+ grub_uint8_t s3 = (color >> 16) & 0xFF;
+
+ grub_uint8_t d1 = (*(grub_uint32_t *) dstptr >> 0) & 0xFF;
+ grub_uint8_t d2 = (*(grub_uint32_t *) dstptr >> 8) & 0xFF;
+ grub_uint8_t d3 = (*(grub_uint32_t *) dstptr >> 16) & 0xFF;
+
+ ((grub_uint8_t *) dstptr)[0] = (d1 * (255 - a) + s1 * a) / 255;
+ ((grub_uint8_t *) dstptr)[1] = (d2 * (255 - a) + s2 * a) / 255;
+ ((grub_uint8_t *) dstptr)[2] = (d3 * (255 - a) + s3 * a) / 255;
+ }
+
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr += 3;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
+
+/* Optimized replacing blitter for 1-bit to XXX888. */
+void
+grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint16_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ grub_uint32_t color;
+ grub_uint8_t a;
+ if (*srcptr & srcmask)
+ {
+ color = fgcolor;
+ a = src->mode_info->fg_alpha;
+ }
+ else
+ {
+ color = bgcolor;
+ a = src->mode_info->bg_alpha;
+ }
+
+ if (a == 255)
+ *(grub_uint16_t *) dstptr = color;
+ else if (a != 0)
+ {
+ grub_uint8_t s1 = (color >> 0) & 0x1F;
+ grub_uint8_t s2 = (color >> 5) & 0x3F;
+ grub_uint8_t s3 = (color >> 11) & 0x1F;
+
+ grub_uint8_t d1 = (*(grub_uint16_t *) dstptr >> 0) & 0x1F;
+ grub_uint8_t d2 = (*(grub_uint16_t *) dstptr >> 5) & 0x3F;
+ grub_uint8_t d3 = (*(grub_uint16_t *) dstptr >> 11) & 0x1F;
+
+ d1 = (d1 * (255 - a) + s1 * a) / 255;
+ d2 = (d2 * (255 - a) + s2 * a) / 255;
+ d3 = (d3 * (255 - a) + s3 * a) / 255;
+
+ *(grub_uint16_t *) dstptr = (d1 & 0x1f) | ((d2 & 0x3f) << 5)
+ | ((d3 & 0x1f) << 11);
+ }
+
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr += 2;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
diff --git a/video/fb/video_fb.c b/video/fb/video_fb.c
index a35dd7a..5f2917d 100644
--- a/video/fb/video_fb.c
+++ b/video/fb/video_fb.c
@@ -587,6 +587,37 @@ common_blitter (struct grub_video_fbblit_info *target,
return;
}
}
+ else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
+ {
+ if (target->mode_info->bpp == 32)
+ {
+ grub_video_fbblit_replace_32bit_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->bpp == 24)
+ {
+ grub_video_fbblit_replace_24bit_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->bpp == 16)
+ {
+ grub_video_fbblit_replace_16bit_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->bpp == 8)
+ {
+ grub_video_fbblit_replace_8bit_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ }
/* No optimized replace operator found, use default (slow) blitter. */
grub_video_fbblit_replace (target, source, x, y, width, height,
@@ -674,6 +705,41 @@ common_blitter (struct grub_video_fbblit_info *target,
return;
}
}
+ else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
+ {
+ if (target->mode_info->blit_format
+ == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888
+ || target->mode_info->blit_format
+ == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+ {
+ grub_video_fbblit_blend_XXXA8888_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format
+ == GRUB_VIDEO_BLIT_FORMAT_BGR_888
+ || target->mode_info->blit_format
+ == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+ {
+ grub_video_fbblit_blend_XXX888_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format
+ == GRUB_VIDEO_BLIT_FORMAT_BGR_565
+ || target->mode_info->blit_format
+ == GRUB_VIDEO_BLIT_FORMAT_RGB_565)
+ {
+ grub_video_fbblit_blend_XXX565_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+
+ }
+
/* No optimized blend operation found, use default (slow) blitter. */
grub_video_fbblit_blend (target, source, x, y, width, height,
diff --git a/video/video.c b/video/video.c
index 36ebfd1..c1d66bd 100644
--- a/video/video.c
+++ b/video/video.c
@@ -181,6 +181,8 @@ grub_video_get_blit_format (struct grub_video_mode_info *mode_info)
return GRUB_VIDEO_BLIT_FORMAT_RGB_565;
}
}
+ else if (mode_info->bpp == 1)
+ return GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED;
/* Backup route. Unknown format. */
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] Optimised 1bit blitters
2009-08-21 15:33 [PATCH] Optimised 1bit blitters Vladimir 'phcoder' Serbinenko
@ 2009-08-23 10:48 ` Robert Millan
2009-08-23 11:05 ` Vladimir 'phcoder' Serbinenko
2009-08-25 14:06 ` Michal Suchanek
0 siblings, 2 replies; 7+ messages in thread
From: Robert Millan @ 2009-08-23 10:48 UTC (permalink / raw)
To: The development of GRUB 2
On Fri, Aug 21, 2009 at 05:33:30PM +0200, Vladimir 'phcoder' Serbinenko wrote:
> + for (j = 0; j < height; j++)
> + {
> + for (i = 0; i < width; i++)
> + {
It's a bit odd, but GCC doesn't seem to optimize those in a single loop. Could
you use "i = 0; i < height * width; i++" instead? (for this and the other
similar instances)
I can't comment much on the rest of this patch, as my understanding of
graphics is limited. But please wait a few days before commit, hopefully
someone else will review.
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Optimised 1bit blitters
2009-08-23 10:48 ` Robert Millan
@ 2009-08-23 11:05 ` Vladimir 'phcoder' Serbinenko
2009-08-23 23:07 ` Robert Millan
2009-08-25 14:06 ` Michal Suchanek
1 sibling, 1 reply; 7+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-08-23 11:05 UTC (permalink / raw)
To: The development of GRUB 2
On Sun, Aug 23, 2009 at 12:48 PM, Robert Millan<rmh@aybabtu.com> wrote:
> On Fri, Aug 21, 2009 at 05:33:30PM +0200, Vladimir 'phcoder' Serbinenko wrote:
>> + for (j = 0; j < height; j++)
>> + {
>> + for (i = 0; i < width; i++)
>> + {
>
> It's a bit odd, but GCC doesn't seem to optimize those in a single loop. Could
> you use "i = 0; i < height * width; i++" instead? (for this and the other
> similar instances)
There are some operations to do after completing inner loop.
--
Regards
Vladimir 'phcoder' Serbinenko
Personal git repository: http://repo.or.cz/w/grub2/phcoder.git
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Optimised 1bit blitters
2009-08-23 11:05 ` Vladimir 'phcoder' Serbinenko
@ 2009-08-23 23:07 ` Robert Millan
0 siblings, 0 replies; 7+ messages in thread
From: Robert Millan @ 2009-08-23 23:07 UTC (permalink / raw)
To: The development of GRUB 2
On Sun, Aug 23, 2009 at 01:05:45PM +0200, Vladimir 'phcoder' Serbinenko wrote:
> On Sun, Aug 23, 2009 at 12:48 PM, Robert Millan<rmh@aybabtu.com> wrote:
> > On Fri, Aug 21, 2009 at 05:33:30PM +0200, Vladimir 'phcoder' Serbinenko wrote:
> >> + for (j = 0; j < height; j++)
> >> + {
> >> + for (i = 0; i < width; i++)
> >> + {
> >
> > It's a bit odd, but GCC doesn't seem to optimize those in a single loop. Could
> > you use "i = 0; i < height * width; i++" instead? (for this and the other
> > similar instances)
> There are some operations to do after completing inner loop.
Oh, right. Sorry I missread it. In that case, I have no objection but please
let it rest a few days to see if someone else will review it.
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Optimised 1bit blitters
2009-08-23 10:48 ` Robert Millan
2009-08-23 11:05 ` Vladimir 'phcoder' Serbinenko
@ 2009-08-25 14:06 ` Michal Suchanek
2009-08-25 14:41 ` Vladimir 'phcoder' Serbinenko
1 sibling, 1 reply; 7+ messages in thread
From: Michal Suchanek @ 2009-08-25 14:06 UTC (permalink / raw)
To: The development of GRUB 2
2009/8/23 Robert Millan <rmh@aybabtu.com>:
> On Fri, Aug 21, 2009 at 05:33:30PM +0200, Vladimir 'phcoder' Serbinenko wrote:
>> + for (j = 0; j < height; j++)
>> + {
>> + for (i = 0; i < width; i++)
>> + {
>
> It's a bit odd, but GCC doesn't seem to optimize those in a single loop. Could
> you use "i = 0; i < height * width; i++" instead? (for this and the other
> similar instances)
>
> I can't comment much on the rest of this patch, as my understanding of
> graphics is limited. But please wait a few days before commit, hopefully
> someone else will review.
Well, this is not rocket science. You cache a function call which
would be done on every iteration otherwise. This is not feasible with
other bitmap types (except perhaps 8bit index->8bit index) because
they use many more colours.
How well tested is this? There are quite a few blitters and some may
not be ever used in current code.
The comment above the blend functions should probably not say they are
replace blitters.
Thanks
Michal
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Optimised 1bit blitters
2009-08-25 14:06 ` Michal Suchanek
@ 2009-08-25 14:41 ` Vladimir 'phcoder' Serbinenko
2009-08-28 13:54 ` Vladimir 'phcoder' Serbinenko
0 siblings, 1 reply; 7+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-08-25 14:41 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 1646 bytes --]
On Tue, Aug 25, 2009 at 4:06 PM, Michal Suchanek<hramrach@centrum.cz> wrote:
> 2009/8/23 Robert Millan <rmh@aybabtu.com>:
>> On Fri, Aug 21, 2009 at 05:33:30PM +0200, Vladimir 'phcoder' Serbinenko wrote:
>>> + for (j = 0; j < height; j++)
>>> + {
>>> + for (i = 0; i < width; i++)
>>> + {
>>
>> It's a bit odd, but GCC doesn't seem to optimize those in a single loop. Could
>> you use "i = 0; i < height * width; i++" instead? (for this and the other
>> similar instances)
>>
>> I can't comment much on the rest of this patch, as my understanding of
>> graphics is limited. But please wait a few days before commit, hopefully
>> someone else will review.
>
> Well, this is not rocket science. You cache a function call which
> would be done on every iteration otherwise. This is not feasible with
> other bitmap types (except perhaps 8bit index->8bit index) because
> they use many more colours.
It's possible with RGB(A) because color transformation is formula-based.
>
> How well tested is this? There are quite a few blitters and some may
> not be ever used in current code.
I modified videotest to test every blitting function. This part isn't
included in the patch because it's dirty.
>
> The comment above the blend functions should probably not say they are
> replace blitters.
>
Thanks.
> Thanks
>
> Michal
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>
--
Regards
Vladimir 'phcoder' Serbinenko
Personal git repository: http://repo.or.cz/w/grub2/phcoder.git
[-- Attachment #2: 1bit.diff --]
[-- Type: text/plain, Size: 23018 bytes --]
diff --git a/ChangeLog b/ChangeLog
index d30cfd1..df4cff3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2009-08-21 Vladimir Serbinenko <phcoder@gmail.com>
+
+ 1-bit optimised blitters.
+
+ * include/grub/fbblit.h (grub_video_fbblit_replace_32bit_1bit): New
+ prototype.
+ (grub_video_fbblit_replace_24bit_1bit): Likewise.
+ (grub_video_fbblit_replace_16bit_1bit): Likewise.
+ (grub_video_fbblit_replace_8bit_1bit): Likewise.
+ (grub_video_fbblit_blend_XXXA8888_1bit): Likewise.
+ (grub_video_fbblit_blend_XXX888_1bit): Likewise.
+ (grub_video_fbblit_blend_XXX565_1bit): Likewise.
+ * video/fb/fbblit.c (grub_video_fbblit_replace_32bit_1bit): New
+ function.
+ (grub_video_fbblit_replace_24bit_1bit): Likewise.
+ (grub_video_fbblit_replace_16bit_1bit): Likewise.
+ (grub_video_fbblit_replace_8bit_1bit): Likewise.
+ (grub_video_fbblit_blend_XXXA8888_1bit): Likewise.
+ (grub_video_fbblit_blend_XXX888_1bit): Likewise.
+ (grub_video_fbblit_blend_XXX565_1bit): Likewise.
+ * video/fb/video_fb.c (common_blitter): Use 1-bit optimised blitters
+ when possible.
+ * video/video.c (grub_video_get_blit_format): Return
+ GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED if bpp = 1.
+
2009-08-25 Vladimir Serbinenko <phcoder@gmail.com>
Fix breakage in grub-setup.
diff --git a/include/grub/fbblit.h b/include/grub/fbblit.h
index 664f508..af97dfb 100644
--- a/include/grub/fbblit.h
+++ b/include/grub/fbblit.h
@@ -131,4 +131,52 @@ grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst,
int width, int height,
int offset_x, int offset_y);
+void
+grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
+
+void
+grub_video_fbblit_replace_24bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
+
+void
+grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
+
+void
+grub_video_fbblit_replace_8bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
+
+void
+grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
+
+void
+grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
+
+void
+grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y);
#endif /* ! GRUB_FBBLIT_HEADER */
diff --git a/video/fb/fbblit.c b/video/fb/fbblit.c
index 5b613bc..a0f44d2 100644
--- a/video/fb/fbblit.c
+++ b/video/fb/fbblit.c
@@ -90,6 +90,302 @@ grub_video_fbblit_replace_directN (struct grub_video_fbblit_info *dst,
}
}
+/* Optimized replacing blitter for 1-bit to 32bit. */
+void
+grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint32_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ if (*srcptr & srcmask)
+ *(grub_uint32_t *) dstptr = fgcolor;
+ else
+ *(grub_uint32_t *) dstptr = bgcolor;
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr += 4;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
+
+
+/* Optimized replacing blitter for 1-bit to 24-bit. */
+void
+grub_video_fbblit_replace_24bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint32_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width - 1; i++)
+ {
+ if (*srcptr & srcmask)
+ *(grub_uint32_t *) dstptr = fgcolor;
+ else
+ *(grub_uint32_t *) dstptr = bgcolor;
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr += 3;
+ }
+
+ if (*srcptr & srcmask)
+ {
+ *dstptr++ = fgcolor & 0xff;
+ *dstptr++ = (fgcolor & 0xff00) >> 8;
+ *dstptr++ = (fgcolor & 0xff0000) >> 16;
+ }
+ else
+ {
+ *dstptr++ = bgcolor & 0xff;
+ *dstptr++ = (bgcolor & 0xff00) >> 8;
+ *dstptr++ = (bgcolor & 0xff0000) >> 16;
+ }
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
+
+/* Optimized replacing blitter for 1-bit to 16-bit. */
+void
+grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint16_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ if (*srcptr & srcmask)
+ *(grub_uint16_t *) dstptr = fgcolor;
+ else
+ *(grub_uint16_t *) dstptr = bgcolor;
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr += 2;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
+
+/* Optimized replacing blitter for 1-bit to 8-bit. */
+void
+grub_video_fbblit_replace_8bit_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint8_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ if (*srcptr & srcmask)
+ *(grub_uint8_t *) dstptr = fgcolor;
+ else
+ *(grub_uint8_t *) dstptr = bgcolor;
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr++;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
+
/* Optimized replacing blitter for RGBX8888 to BGRX8888. */
void
grub_video_fbblit_replace_BGRX8888_RGBX8888 (struct grub_video_fbblit_info *dst,
@@ -826,3 +1122,294 @@ grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst,
}
}
}
+
+/* Optimized blending blitter for 1-bit to XXXA8888. */
+void
+grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint32_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ grub_uint32_t color;
+ grub_uint8_t a;
+
+ if (*srcptr & srcmask)
+ color = fgcolor;
+ else
+ color = bgcolor;
+ a = (color >> 24) & 0xff;
+
+ if (a == 255)
+ *(grub_uint32_t *) dstptr = color;
+ else if (a != 0)
+ {
+ grub_uint8_t s1 = (color >> 0) & 0xFF;
+ grub_uint8_t s2 = (color >> 8) & 0xFF;
+ grub_uint8_t s3 = (color >> 16) & 0xFF;
+
+ grub_uint8_t d1 = (*(grub_uint32_t *) dstptr >> 0) & 0xFF;
+ grub_uint8_t d2 = (*(grub_uint32_t *) dstptr >> 8) & 0xFF;
+ grub_uint8_t d3 = (*(grub_uint32_t *) dstptr >> 16) & 0xFF;
+
+ d1 = (d1 * (255 - a) + s1 * a) / 255;
+ d2 = (d2 * (255 - a) + s2 * a) / 255;
+ d3 = (d3 * (255 - a) + s3 * a) / 255;
+
+ *(grub_uint32_t *) dstptr = (a << 24) | (d3 << 16) | (d2 << 8)
+ | d1;
+ }
+
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr += 4;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
+
+/* Optimized blending blitter for 1-bit to XXX888. */
+void
+grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint32_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ grub_uint32_t color;
+ grub_uint8_t a;
+ if (*srcptr & srcmask)
+ {
+ color = fgcolor;
+ a = src->mode_info->fg_alpha;
+ }
+ else
+ {
+ color = bgcolor;
+ a = src->mode_info->bg_alpha;
+ }
+
+ if (a == 255)
+ {
+ ((grub_uint8_t *) dstptr)[0] = color & 0xff;
+ ((grub_uint8_t *) dstptr)[1] = (color & 0xff00) >> 8;
+ ((grub_uint8_t *) dstptr)[2] = (color & 0xff0000) >> 16;
+ }
+ else if (a != 0)
+ {
+ grub_uint8_t s1 = (color >> 0) & 0xFF;
+ grub_uint8_t s2 = (color >> 8) & 0xFF;
+ grub_uint8_t s3 = (color >> 16) & 0xFF;
+
+ grub_uint8_t d1 = (*(grub_uint32_t *) dstptr >> 0) & 0xFF;
+ grub_uint8_t d2 = (*(grub_uint32_t *) dstptr >> 8) & 0xFF;
+ grub_uint8_t d3 = (*(grub_uint32_t *) dstptr >> 16) & 0xFF;
+
+ ((grub_uint8_t *) dstptr)[0] = (d1 * (255 - a) + s1 * a) / 255;
+ ((grub_uint8_t *) dstptr)[1] = (d2 * (255 - a) + s2 * a) / 255;
+ ((grub_uint8_t *) dstptr)[2] = (d3 * (255 - a) + s3 * a) / 255;
+ }
+
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr += 3;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
+
+/* Optimized blending blitter for 1-bit to XXX888. */
+void
+grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst,
+ struct grub_video_fbblit_info *src,
+ int x, int y,
+ int width, int height,
+ int offset_x, int offset_y)
+{
+ int i;
+ int j;
+ grub_uint8_t *srcptr;
+ grub_uint8_t *dstptr;
+ grub_uint8_t srcmask;
+ unsigned int dstrowskip;
+ unsigned int srcrowskipbyte, srcrowskipbit;
+ grub_uint16_t fgcolor, bgcolor;
+ int bit_index;
+
+ /* Calculate the number of bytes to advance from the end of one line
+ to the beginning of the next line. */
+ dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+ srcrowskipbyte = (src->mode_info->width - width) >> 3;
+ srcrowskipbit = (src->mode_info->width - width) & 7;
+
+ bit_index = offset_y * src->mode_info->width + offset_x;
+ srcptr = (grub_uint8_t *) src->data + (bit_index >> 3);
+ srcmask = 1 << (~bit_index & 7);
+ dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y);
+
+ fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red,
+ src->mode_info->fg_green,
+ src->mode_info->fg_blue,
+ src->mode_info->fg_alpha);
+
+ bgcolor = grub_video_fb_map_rgba (src->mode_info->bg_red,
+ src->mode_info->bg_green,
+ src->mode_info->bg_blue,
+ src->mode_info->bg_alpha);
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ grub_uint32_t color;
+ grub_uint8_t a;
+ if (*srcptr & srcmask)
+ {
+ color = fgcolor;
+ a = src->mode_info->fg_alpha;
+ }
+ else
+ {
+ color = bgcolor;
+ a = src->mode_info->bg_alpha;
+ }
+
+ if (a == 255)
+ *(grub_uint16_t *) dstptr = color;
+ else if (a != 0)
+ {
+ grub_uint8_t s1 = (color >> 0) & 0x1F;
+ grub_uint8_t s2 = (color >> 5) & 0x3F;
+ grub_uint8_t s3 = (color >> 11) & 0x1F;
+
+ grub_uint8_t d1 = (*(grub_uint16_t *) dstptr >> 0) & 0x1F;
+ grub_uint8_t d2 = (*(grub_uint16_t *) dstptr >> 5) & 0x3F;
+ grub_uint8_t d3 = (*(grub_uint16_t *) dstptr >> 11) & 0x1F;
+
+ d1 = (d1 * (255 - a) + s1 * a) / 255;
+ d2 = (d2 * (255 - a) + s2 * a) / 255;
+ d3 = (d3 * (255 - a) + s3 * a) / 255;
+
+ *(grub_uint16_t *) dstptr = (d1 & 0x1f) | ((d2 & 0x3f) << 5)
+ | ((d3 & 0x1f) << 11);
+ }
+
+ srcmask >>= 1;
+ if (!srcmask)
+ {
+ srcptr++;
+ srcmask = 0x80;
+ }
+
+ dstptr += 2;
+ }
+
+ srcptr += srcrowskipbyte;
+ if (srcmask >> srcrowskipbit)
+ srcmask >>= srcrowskipbit;
+ else
+ {
+ srcptr++;
+ srcmask <<= 8 - srcrowskipbit;
+ }
+ dstptr += dstrowskip;
+ }
+}
diff --git a/video/fb/video_fb.c b/video/fb/video_fb.c
index a35dd7a..5f2917d 100644
--- a/video/fb/video_fb.c
+++ b/video/fb/video_fb.c
@@ -587,6 +587,37 @@ common_blitter (struct grub_video_fbblit_info *target,
return;
}
}
+ else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
+ {
+ if (target->mode_info->bpp == 32)
+ {
+ grub_video_fbblit_replace_32bit_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->bpp == 24)
+ {
+ grub_video_fbblit_replace_24bit_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->bpp == 16)
+ {
+ grub_video_fbblit_replace_16bit_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->bpp == 8)
+ {
+ grub_video_fbblit_replace_8bit_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ }
/* No optimized replace operator found, use default (slow) blitter. */
grub_video_fbblit_replace (target, source, x, y, width, height,
@@ -674,6 +705,41 @@ common_blitter (struct grub_video_fbblit_info *target,
return;
}
}
+ else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
+ {
+ if (target->mode_info->blit_format
+ == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888
+ || target->mode_info->blit_format
+ == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+ {
+ grub_video_fbblit_blend_XXXA8888_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format
+ == GRUB_VIDEO_BLIT_FORMAT_BGR_888
+ || target->mode_info->blit_format
+ == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+ {
+ grub_video_fbblit_blend_XXX888_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+ else if (target->mode_info->blit_format
+ == GRUB_VIDEO_BLIT_FORMAT_BGR_565
+ || target->mode_info->blit_format
+ == GRUB_VIDEO_BLIT_FORMAT_RGB_565)
+ {
+ grub_video_fbblit_blend_XXX565_1bit (target, source,
+ x, y, width, height,
+ offset_x, offset_y);
+ return;
+ }
+
+ }
+
/* No optimized blend operation found, use default (slow) blitter. */
grub_video_fbblit_blend (target, source, x, y, width, height,
diff --git a/video/video.c b/video/video.c
index 36ebfd1..c1d66bd 100644
--- a/video/video.c
+++ b/video/video.c
@@ -181,6 +181,8 @@ grub_video_get_blit_format (struct grub_video_mode_info *mode_info)
return GRUB_VIDEO_BLIT_FORMAT_RGB_565;
}
}
+ else if (mode_info->bpp == 1)
+ return GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED;
/* Backup route. Unknown format. */
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] Optimised 1bit blitters
2009-08-25 14:41 ` Vladimir 'phcoder' Serbinenko
@ 2009-08-28 13:54 ` Vladimir 'phcoder' Serbinenko
0 siblings, 0 replies; 7+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-08-28 13:54 UTC (permalink / raw)
To: The development of GRUB 2
comitted
On Tue, Aug 25, 2009 at 4:41 PM, Vladimir 'phcoder'
Serbinenko<phcoder@gmail.com> wrote:
> On Tue, Aug 25, 2009 at 4:06 PM, Michal Suchanek<hramrach@centrum.cz> wrote:
>> 2009/8/23 Robert Millan <rmh@aybabtu.com>:
>>> On Fri, Aug 21, 2009 at 05:33:30PM +0200, Vladimir 'phcoder' Serbinenko wrote:
>>>> + for (j = 0; j < height; j++)
>>>> + {
>>>> + for (i = 0; i < width; i++)
>>>> + {
>>>
>>> It's a bit odd, but GCC doesn't seem to optimize those in a single loop. Could
>>> you use "i = 0; i < height * width; i++" instead? (for this and the other
>>> similar instances)
>>>
>>> I can't comment much on the rest of this patch, as my understanding of
>>> graphics is limited. But please wait a few days before commit, hopefully
>>> someone else will review.
>>
>> Well, this is not rocket science. You cache a function call which
>> would be done on every iteration otherwise. This is not feasible with
>> other bitmap types (except perhaps 8bit index->8bit index) because
>> they use many more colours.
> It's possible with RGB(A) because color transformation is formula-based.
>>
>> How well tested is this? There are quite a few blitters and some may
>> not be ever used in current code.
> I modified videotest to test every blitting function. This part isn't
> included in the patch because it's dirty.
>>
>> The comment above the blend functions should probably not say they are
>> replace blitters.
>>
> Thanks.
>> Thanks
>>
>> Michal
>>
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>>
>
>
>
> --
> Regards
> Vladimir 'phcoder' Serbinenko
>
> Personal git repository: http://repo.or.cz/w/grub2/phcoder.git
>
--
Regards
Vladimir 'phcoder' Serbinenko
Personal git repository: http://repo.or.cz/w/grub2/phcoder.git
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-08-28 13:54 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-21 15:33 [PATCH] Optimised 1bit blitters Vladimir 'phcoder' Serbinenko
2009-08-23 10:48 ` Robert Millan
2009-08-23 11:05 ` Vladimir 'phcoder' Serbinenko
2009-08-23 23:07 ` Robert Millan
2009-08-25 14:06 ` Michal Suchanek
2009-08-25 14:41 ` Vladimir 'phcoder' Serbinenko
2009-08-28 13:54 ` Vladimir 'phcoder' Serbinenko
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.