From 18f0215d54546b2d4ccb1ff4877c48d5de00e1b3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 4 May 2013 13:58:30 +0200 Subject: [PATCH 422/471] Speed-up gfxterm by saving intermediate results in index+alpha format. --- ChangeLog | 5 + grub-core/term/gfxterm.c | 2 +- grub-core/video/fb/fbblit.c | 370 ++++++++++++++++++++++++++++++++++++++++++ grub-core/video/fb/video_fb.c | 298 ++++++++++++++++++++-------------- include/grub/video.h | 5 + include/grub/video_fb.h | 54 ++++++ 6 files changed, 613 insertions(+), 121 deletions(-) diff --git a/ChangeLog b/ChangeLog index d5f9bb9..74cb13d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2013-05-04 Vladimir Serbinenko + Speed-up gfxterm by saving intermediate results in index+alpha + format. + +2013-05-04 Vladimir Serbinenko + * grub-core/tests/lib/functional_test.c: Don't stop on first failed test. diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 1e33a34..54636d7 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -254,7 +254,7 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y, grub_video_create_render_target (&text_layer, virtual_screen.width, virtual_screen.height, - GRUB_VIDEO_MODE_TYPE_RGB + GRUB_VIDEO_MODE_TYPE_INDEX_COLOR | GRUB_VIDEO_MODE_TYPE_ALPHA); if (grub_errno != GRUB_ERR_NONE) return grub_errno; diff --git a/grub-core/video/fb/fbblit.c b/grub-core/video/fb/fbblit.c index 541a0ce..c206ac8 100644 --- a/grub-core/video/fb/fbblit.c +++ b/grub-core/video/fb/fbblit.c @@ -389,6 +389,376 @@ grub_video_fbblit_replace_8bit_1bit (struct grub_video_fbblit_info *dst, } } +void +grub_video_fbblit_replace_32bit_indexa (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_uint32_t *dstptr; + unsigned int dstrowskip; + unsigned int srcrowskip; + grub_uint32_t palette[17]; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); + + /* 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; + srcrowskip = src->mode_info->pitch - width; + + for (i = 0; i < 16; i++) + palette[i] = grub_video_fb_map_color (i); + palette[16] = grub_video_fb_map_rgba (0, 0, 0, 0); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + if (*srcptr == 0xf0) + *dstptr = palette[16]; + else + *dstptr = palette[*srcptr & 0xf]; + srcptr++; + dstptr++; + } + + srcptr += srcrowskip; + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); + } +} + +/* Optimized replacing blitter for 1-bit to 16bit. */ +void +grub_video_fbblit_replace_24bit_indexa (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; + unsigned int dstrowskip; + unsigned int srcrowskip; + grub_uint32_t palette[17]; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); + + /* 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; + srcrowskip = src->mode_info->pitch - width; + + for (i = 0; i < 16; i++) + palette[i] = grub_video_fb_map_color (i); + palette[16] = grub_video_fb_map_rgba (0, 0, 0, 0); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + register grub_uint32_t col; + if (*srcptr == 0xf0) + col = palette[16]; + else + col = palette[*srcptr & 0xf]; +#ifdef GRUB_CPU_WORDS_BIGENDIAN + *dstptr++ = col >> 16; + *dstptr++ = col >> 8; + *dstptr++ = col >> 0; +#else + *dstptr++ = col >> 0; + *dstptr++ = col >> 8; + *dstptr++ = col >> 16; +#endif + srcptr++; + } + + srcptr += srcrowskip; + dstptr += dstrowskip; + } +} + +/* Optimized replacing blitter for 1-bit to 16bit. */ +void +grub_video_fbblit_replace_16bit_indexa (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_uint16_t *dstptr; + unsigned int dstrowskip; + unsigned int srcrowskip; + grub_uint16_t palette[17]; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); + + /* 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; + srcrowskip = src->mode_info->pitch - width; + + for (i = 0; i < 16; i++) + palette[i] = grub_video_fb_map_color (i); + palette[16] = grub_video_fb_map_rgba (0, 0, 0, 0); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + if (*srcptr == 0xf0) + *dstptr = palette[16]; + else + *dstptr = palette[*srcptr & 0xf]; + srcptr++; + dstptr++; + } + + srcptr += srcrowskip; + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); + } +} + +/* Optimized replacing blitter for 1-bit to 8bit. */ +void +grub_video_fbblit_replace_8bit_indexa (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; + unsigned int dstrowskip; + unsigned int srcrowskip; + grub_uint8_t palette[17]; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); + + /* 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; + srcrowskip = src->mode_info->pitch - width; + + for (i = 0; i < 16; i++) + palette[i] = grub_video_fb_map_color (i); + palette[16] = grub_video_fb_map_rgba (0, 0, 0, 0); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + if (*srcptr == 0xf0) + *dstptr = palette[16]; + else + *dstptr = palette[*srcptr & 0xf]; + srcptr++; + dstptr++; + } + + srcptr += srcrowskip; + dstptr += dstrowskip; + } +} + + +void +grub_video_fbblit_blend_32bit_indexa (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_uint32_t *dstptr; + unsigned int dstrowskip; + unsigned int srcrowskip; + grub_uint32_t palette[16]; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); + + /* 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; + srcrowskip = src->mode_info->pitch - width; + + for (i = 0; i < 16; i++) + palette[i] = grub_video_fb_map_color (i); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + if (*srcptr != 0xf0) + *dstptr = palette[*srcptr & 0xf]; + srcptr++; + dstptr++; + } + + srcptr += srcrowskip; + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); + } +} + +/* Optimized replacing blitter for 1-bit to 16bit. */ +void +grub_video_fbblit_blend_24bit_indexa (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; + unsigned int dstrowskip; + unsigned int srcrowskip; + grub_uint32_t palette[16]; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); + + /* 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; + srcrowskip = src->mode_info->pitch - width; + + for (i = 0; i < 16; i++) + palette[i] = grub_video_fb_map_color (i); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + register grub_uint32_t col; + if (*srcptr != 0xf0) + { + col = palette[*srcptr & 0xf]; +#ifdef GRUB_CPU_WORDS_BIGENDIAN + *dstptr++ = col >> 16; + *dstptr++ = col >> 8; + *dstptr++ = col >> 0; +#else + *dstptr++ = col >> 0; + *dstptr++ = col >> 8; + *dstptr++ = col >> 16; +#endif + } + else + dstptr += 3; + srcptr++; + } + + srcptr += srcrowskip; + dstptr += dstrowskip; + } +} + +/* Optimized replacing blitter for 1-bit to 16bit. */ +void +grub_video_fbblit_blend_16bit_indexa (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_uint16_t *dstptr; + unsigned int dstrowskip; + unsigned int srcrowskip; + grub_uint16_t palette[17]; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); + + /* 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; + srcrowskip = src->mode_info->pitch - width; + + for (i = 0; i < 16; i++) + palette[i] = grub_video_fb_map_color (i); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + if (*srcptr != 0xf0) + *dstptr = palette[*srcptr & 0xf]; + srcptr++; + dstptr++; + } + + srcptr += srcrowskip; + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); + } +} + +/* Optimized replacing blitter for 1-bit to 8bit. */ +void +grub_video_fbblit_blend_8bit_indexa (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; + unsigned int dstrowskip; + unsigned int srcrowskip; + grub_uint8_t palette[16]; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); + + /* 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; + srcrowskip = src->mode_info->pitch - width; + + for (i = 0; i < 16; i++) + palette[i] = grub_video_fb_map_color (i); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + if (*srcptr != 0xf0) + *dstptr = palette[*srcptr & 0xf]; + srcptr++; + dstptr++; + } + + srcptr += srcrowskip; + dstptr += dstrowskip; + } +} + + /* Optimized replacing blitter for RGBX8888 to BGRX8888. */ void grub_video_fbblit_replace_BGRX8888_RGBX8888 (struct grub_video_fbblit_info *dst, diff --git a/grub-core/video/fb/video_fb.c b/grub-core/video/fb/video_fb.c index 836842e..22a0128 100644 --- a/grub-core/video/fb/video_fb.c +++ b/grub-core/video/fb/video_fb.c @@ -542,11 +542,18 @@ grub_video_color_t grub_video_fb_map_rgba (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue, grub_uint8_t alpha) { + if ((framebuffer.render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) - /* No alpha available in index color modes, just use - same value as in only RGB modes. */ - return grub_video_fb_map_rgb (red, green, blue); + { + if ((framebuffer.render_target->mode_info.mode_type + & GRUB_VIDEO_MODE_TYPE_ALPHA) != 0 + && alpha == 0) + return 0xf0; + /* No alpha available in index color modes, just use + same value as in only RGB modes. */ + return grub_video_fb_map_rgb (red, green, blue); + } else if ((framebuffer.render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0) { @@ -605,6 +612,17 @@ grub_video_fb_unmap_color_int (struct grub_video_fbblit_info * source, if ((mode_info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) { + if ((framebuffer.render_target->mode_info.mode_type + & GRUB_VIDEO_MODE_TYPE_ALPHA) != 0 + && color == 0xf0) + { + *red = 0; + *green = 0; + *blue = 0; + *alpha = 0; + return; + } + /* If we have an out-of-bounds color, return transparent black. */ if (color > 255) { @@ -772,134 +790,153 @@ common_blitter (struct grub_video_fbblit_info *target, if (oper == GRUB_VIDEO_BLIT_REPLACE) { /* Try to figure out more optimized version for replace operator. */ - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) + switch (source->mode_info->blit_format) { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) + case GRUB_VIDEO_BLIT_FORMAT_RGBA_8888: + switch (target->mode_info->blit_format) { + case GRUB_VIDEO_BLIT_FORMAT_RGBA_8888: grub_video_fbblit_replace_directN (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) - { + case GRUB_VIDEO_BLIT_FORMAT_BGRA_8888: grub_video_fbblit_replace_BGRX8888_RGBX8888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888) - { + case GRUB_VIDEO_BLIT_FORMAT_BGR_888: grub_video_fbblit_replace_BGR888_RGBX8888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { + case GRUB_VIDEO_BLIT_FORMAT_RGB_888: grub_video_fbblit_replace_RGB888_RGBX8888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { + case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR: grub_video_fbblit_replace_index_RGBX8888 (target, source, x, y, width, height, offset_x, offset_y); return; + default: + break; } - } - else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + break; + case GRUB_VIDEO_BLIT_FORMAT_RGB_888: + switch (target->mode_info->blit_format) { + case GRUB_VIDEO_BLIT_FORMAT_BGRA_8888: grub_video_fbblit_replace_BGRX8888_RGB888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) - { + case GRUB_VIDEO_BLIT_FORMAT_RGBA_8888: grub_video_fbblit_replace_RGBX8888_RGB888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888) - { + case GRUB_VIDEO_BLIT_FORMAT_BGR_888: grub_video_fbblit_replace_BGR888_RGB888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { + case GRUB_VIDEO_BLIT_FORMAT_RGB_888: grub_video_fbblit_replace_directN (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { + case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR: grub_video_fbblit_replace_index_RGB888 (target, source, x, y, width, height, offset_x, offset_y); return; + default: + break; } - } - else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + break; + case GRUB_VIDEO_BLIT_FORMAT_BGRA_8888: + switch (target->mode_info->blit_format) { + case GRUB_VIDEO_BLIT_FORMAT_BGRA_8888: grub_video_fbblit_replace_directN (target, source, x, y, width, height, offset_x, offset_y); return; + default: + break; } - } - else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + break; + case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR: + switch (target->mode_info->blit_format) { + case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR: + case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR_ALPHA: grub_video_fbblit_replace_directN (target, source, x, y, width, height, offset_x, offset_y); return; + default: + break; } - } - else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) - { - if (target->mode_info->bpp == 32) + break; + case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR_ALPHA: + switch (target->mode_info->bytes_per_pixel) + { + case 4: + grub_video_fbblit_replace_32bit_indexa (target, source, + x, y, width, height, + offset_x, offset_y); + return; + case 3: + grub_video_fbblit_replace_24bit_indexa (target, source, + x, y, width, height, + offset_x, offset_y); + return; + case 2: + grub_video_fbblit_replace_16bit_indexa (target, source, + x, y, width, height, + offset_x, offset_y); + return; + case 1: + grub_video_fbblit_replace_8bit_indexa (target, source, + x, y, width, height, + offset_x, offset_y); + return; + default: + break; + } + break; + case GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED: + switch (target->mode_info->bytes_per_pixel) { + case 4: grub_video_fbblit_replace_32bit_1bit (target, source, x, y, width, height, offset_x, offset_y); return; - } #ifdef GRUB_HAVE_UNALIGNED_ACCESS - else if (target->mode_info->bpp == 24) - { + case 3: grub_video_fbblit_replace_24bit_1bit (target, source, x, y, width, height, offset_x, offset_y); return; - } #endif - else if (target->mode_info->bpp == 16) - { + case 2: grub_video_fbblit_replace_16bit_1bit (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->bpp == 8) - { + case 1: grub_video_fbblit_replace_8bit_1bit (target, source, x, y, width, height, offset_x, offset_y); return; } + break; + default: + break; } /* No optimized replace operator found, use default (slow) blitter. */ @@ -909,123 +946,131 @@ common_blitter (struct grub_video_fbblit_info *target, else { /* Try to figure out more optimized blend operator. */ - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) + switch (source->mode_info->blit_format) { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + case GRUB_VIDEO_BLIT_FORMAT_RGBA_8888: + switch (target->mode_info->blit_format) { + case GRUB_VIDEO_BLIT_FORMAT_BGRA_8888: grub_video_fbblit_blend_BGRA8888_RGBA8888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) - { + case GRUB_VIDEO_BLIT_FORMAT_RGBA_8888: grub_video_fbblit_blend_RGBA8888_RGBA8888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888) - { + case GRUB_VIDEO_BLIT_FORMAT_BGR_888: grub_video_fbblit_blend_BGR888_RGBA8888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { + case GRUB_VIDEO_BLIT_FORMAT_RGB_888: grub_video_fbblit_blend_RGB888_RGBA8888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { + case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR: grub_video_fbblit_blend_index_RGBA8888 (target, source, x, y, width, height, offset_x, offset_y); return; + default: + break; } - } - else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { + break; + case GRUB_VIDEO_BLIT_FORMAT_RGB_888: /* Note: There is really no alpha information here, so blend is changed to replace. */ - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + switch (target->mode_info->blit_format) { + case GRUB_VIDEO_BLIT_FORMAT_BGRA_8888: grub_video_fbblit_replace_BGRX8888_RGB888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) - { + case GRUB_VIDEO_BLIT_FORMAT_RGBA_8888: grub_video_fbblit_replace_RGBX8888_RGB888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888) - { + case GRUB_VIDEO_BLIT_FORMAT_BGR_888: grub_video_fbblit_replace_BGR888_RGB888 (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { + case GRUB_VIDEO_BLIT_FORMAT_RGB_888: grub_video_fbblit_replace_directN (target, source, x, y, width, height, offset_x, offset_y); return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { + case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR: grub_video_fbblit_replace_index_RGB888 (target, source, x, y, width, height, offset_x, offset_y); return; + default: + break; } - } - 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) + break; + case GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED: + switch (target->mode_info->blit_format) { + case GRUB_VIDEO_BLIT_FORMAT_BGRA_8888: + case GRUB_VIDEO_BLIT_FORMAT_RGBA_8888: grub_video_fbblit_blend_XXXA8888_1bit (target, source, x, y, width, height, offset_x, offset_y); return; - } #ifdef GRUB_HAVE_UNALIGNED_ACCESS - else if (target->mode_info->blit_format - == GRUB_VIDEO_BLIT_FORMAT_BGR_888 - || target->mode_info->blit_format - == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { + case GRUB_VIDEO_BLIT_FORMAT_BGR_888: + case GRUB_VIDEO_BLIT_FORMAT_RGB_888: grub_video_fbblit_blend_XXX888_1bit (target, source, x, y, width, height, offset_x, offset_y); return; - } #endif - else if (target->mode_info->blit_format - == GRUB_VIDEO_BLIT_FORMAT_BGR_565 - || target->mode_info->blit_format - == GRUB_VIDEO_BLIT_FORMAT_RGB_565) - { + case GRUB_VIDEO_BLIT_FORMAT_BGR_565: + case GRUB_VIDEO_BLIT_FORMAT_RGB_565: grub_video_fbblit_blend_XXX565_1bit (target, source, x, y, width, height, offset_x, offset_y); return; + default: + break; } - + break; + case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR_ALPHA: + switch (target->mode_info->bytes_per_pixel) + { + case 4: + grub_video_fbblit_blend_32bit_indexa (target, source, + x, y, width, height, + offset_x, offset_y); + return; + case 3: + grub_video_fbblit_blend_24bit_indexa (target, source, + x, y, width, height, + offset_x, offset_y); + return; + case 2: + grub_video_fbblit_blend_16bit_indexa (target, source, + x, y, width, height, + offset_x, offset_y); + return; + case 1: + grub_video_fbblit_blend_8bit_indexa (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + break; + default: + break; } - /* No optimized blend operation found, use default (slow) blitter. */ grub_video_fbblit_blend (target, source, x, y, width, height, offset_x, offset_y); @@ -1411,22 +1456,35 @@ grub_video_fb_create_render_target (struct grub_video_fbrender_target **result, /* Setup render target format. */ target->mode_info.width = width; target->mode_info.height = height; - target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB - | GRUB_VIDEO_MODE_TYPE_ALPHA; - target->mode_info.bpp = 32; - target->mode_info.bytes_per_pixel = 4; + switch (mode_type) + { + case GRUB_VIDEO_MODE_TYPE_INDEX_COLOR + | GRUB_VIDEO_MODE_TYPE_ALPHA: + target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR + | GRUB_VIDEO_MODE_TYPE_ALPHA; + target->mode_info.bpp = 8; + target->mode_info.bytes_per_pixel = 1; + target->mode_info.number_of_colors = 16; + target->mode_info.blit_format = GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR_ALPHA; + break; + default: + target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB + | GRUB_VIDEO_MODE_TYPE_ALPHA; + target->mode_info.bpp = 32; + target->mode_info.bytes_per_pixel = 4; + target->mode_info.red_mask_size = 8; + target->mode_info.red_field_pos = 0; + target->mode_info.green_mask_size = 8; + target->mode_info.green_field_pos = 8; + target->mode_info.blue_mask_size = 8; + target->mode_info.blue_field_pos = 16; + target->mode_info.reserved_mask_size = 8; + target->mode_info.reserved_field_pos = 24; + target->mode_info.number_of_colors = framebuffer.palette_size; /* Emulated palette. */ + target->mode_info.blit_format = GRUB_VIDEO_BLIT_FORMAT_RGBA_8888; + break; + } target->mode_info.pitch = target->mode_info.bytes_per_pixel * width; - target->mode_info.number_of_colors = framebuffer.palette_size; /* Emulated palette. */ - target->mode_info.red_mask_size = 8; - target->mode_info.red_field_pos = 0; - target->mode_info.green_mask_size = 8; - target->mode_info.green_field_pos = 8; - target->mode_info.blue_mask_size = 8; - target->mode_info.blue_field_pos = 16; - target->mode_info.reserved_mask_size = 8; - target->mode_info.reserved_field_pos = 24; - - target->mode_info.blit_format = grub_video_get_blit_format (&target->mode_info); /* Calculate size needed for the data. */ size = (width * target->mode_info.bytes_per_pixel) * height; diff --git a/include/grub/video.h b/include/grub/video.h index 36e863b..b2d1458 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -101,6 +101,11 @@ enum grub_video_blit_format /* When needed, decode color or just use value as is. */ GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR, + /* Like index but only 16-colors and F0 is a special value for transparency. + Could be extended to 4 bits of alpha and 4 bits of color if necessary. + Used internally for text rendering. + */ + GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR_ALPHA, /* Two color bitmap; bits packed: rows are not padded to byte boundary. */ GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED diff --git a/include/grub/video_fb.h b/include/grub/video_fb.h index ffe16c3..88bc75d 100644 --- a/include/grub/video_fb.h +++ b/include/grub/video_fb.h @@ -118,6 +118,60 @@ EXPORT_FUNC(grub_video_fb_get_active_render_target) (struct grub_video_fbrender_ grub_err_t EXPORT_FUNC(grub_video_fb_set_active_render_target) (struct grub_video_fbrender_target *target); +void +EXPORT_FUNC (grub_video_fbblit_blend_32bit_indexa) (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 +EXPORT_FUNC (grub_video_fbblit_blend_24bit_indexa) (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 +EXPORT_FUNC (grub_video_fbblit_blend_16bit_indexa) (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 +EXPORT_FUNC (grub_video_fbblit_blend_8bit_indexa) (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 +EXPORT_FUNC (grub_video_fbblit_replace_32bit_indexa) (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 +EXPORT_FUNC (grub_video_fbblit_replace_24bit_indexa) (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 +EXPORT_FUNC (grub_video_fbblit_replace_16bit_indexa) (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 +EXPORT_FUNC (grub_video_fbblit_replace_8bit_indexa) (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); + typedef grub_err_t (*grub_video_fb_set_page_t) (int page); grub_err_t -- 1.8.2.1