diff --git a/ChangeLog b/ChangeLog index 685934009..22626adf3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,101 @@ +2008-09-07 Vesa Jääskeläinen + + Based on patch created by Colin D Bennett . + Adds optimization support for BGR based modes. + + * include/grub/i386/pc/vbeblit.h (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8) Removed. + (grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8): Likewise. + (grub_video_i386_vbeblit_R8G8B8_R8G8B8A8): Likewise. + (grub_video_i386_vbeblit_R8G8B8_R8G8B8X8): Likewise. + (grub_video_i386_vbeblit_index_R8G8B8A8): Likewise. + (grub_video_i386_vbeblit_index_R8G8B8X8): Likewise. + (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8): Likewise. + (grub_video_i386_vbeblit_R8G8B8_R8G8B8): Likewise. + (grub_video_i386_vbeblit_index_R8G8B8): Likewise. + (grub_video_i386_vbeblit_index_index): Likewise. + (grub_video_i386_vbeblit_replace_directN): Added. + (grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888): Likewise. + (grub_video_i386_vbeblit_replace_BGRX8888_RGB888): Likewise. + (grub_video_i386_vbeblit_replace_BGR888_RGBX8888): Likewise. + (grub_video_i386_vbeblit_replace_BGR888_RGB888): Likewise. + (grub_video_i386_vbeblit_replace_RGBX8888_RGB888): Likewise. + (grub_video_i386_vbeblit_replace_RGB888_RGBX8888): Likewise. + (grub_video_i386_vbeblit_replace_index_RGBX8888): Likewise. + (grub_video_i386_vbeblit_replace_index_RGB888): Likewise. + (grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888): Likewise. + (grub_video_i386_vbeblit_blend_BGR888_RGBA8888): Likewise. + (grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888): Likewise. + (grub_video_i386_vbeblit_blend_RGB888_RGBA8888): Likewise. + (grub_video_i386_vbeblit_blend_index_RGBA8888): Likewise. + + * include/grub/i386/pc/vbefill.h (grub_video_i386_vbefill_R8G8B8A8) Removed. + (grub_video_i386_vbefill_R8G8B8): Likewise. + (grub_video_i386_vbefill_index): Likewise. + (grub_video_i386_vbefill_direct32): Added. + (grub_video_i386_vbefill_direct24): Likewise. + (grub_video_i386_vbefill_direct16): Likewise. + (grub_video_i386_vbefill_direct8): Likewise. + + * include/grub/video.h (grub_video_blit_format): Removed + GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8, GRUB_VIDEO_BLIT_FORMAT_R8G8B8. + (grub_video_blit_format): Added GRUB_VIDEO_BLIT_FORMAT_RGBA_8888, + GRUB_VIDEO_BLIT_FORMAT_BGRA_8888, GRUB_VIDEO_BLIT_FORMAT_RGB_888, + GRUB_VIDEO_BLIT_FORMAT_BGR_888, GRUB_VIDEO_BLIT_FORMAT_RGB_565, + GRUB_VIDEO_BLIT_FORMAT_BGR_565. + + * video/video.c (grub_video_get_blit_format): Updated to use new + blit formats. Added handling for 16 bit color modes. + + * video/i386/pc/vbe.c (grub_video_vbe_fill_rect): Updated to use new + fillers. + (common_blitter): Updated to use new blitters. + + * video/i386/pc/vbeblit.c (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8): + Removed. + (grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8): Likewise. + (grub_video_i386_vbeblit_R8G8B8_R8G8B8A8): Likewise. + (grub_video_i386_vbeblit_R8G8B8_R8G8B8X8): Likewise. + (grub_video_i386_vbeblit_index_R8G8B8A8): Likewise. + (grub_video_i386_vbeblit_index_R8G8B8X8): Likewise. + (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8): Likewise. + (grub_video_i386_vbeblit_R8G8B8_R8G8B8): Likewise. + (grub_video_i386_vbeblit_index_R8G8B8): Likewise. + (grub_video_i386_vbeblit_index_index): Likewise. + (grub_video_i386_vbeblit_replace_directN): Added. + (grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888): Likewise. + (grub_video_i386_vbeblit_replace_BGRX8888_RGB888): Likewise. + (grub_video_i386_vbeblit_replace_BGR888_RGBX8888): Likewise. + (grub_video_i386_vbeblit_replace_BGR888_RGB888): Likewise. + (grub_video_i386_vbeblit_replace_RGBX8888_RGB888): Likewise. + (grub_video_i386_vbeblit_replace_RGB888_RGBX8888): Likewise. + (grub_video_i386_vbeblit_replace_index_RGBX8888): Likewise. + (grub_video_i386_vbeblit_replace_index_RGB888): Likewise. + (grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888): Likewise. + (grub_video_i386_vbeblit_blend_BGR888_RGBA8888): Likewise. + (grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888): Likewise. + (grub_video_i386_vbeblit_blend_RGB888_RGBA8888): Likewise. + (grub_video_i386_vbeblit_blend_index_RGBA8888): Likewise. + + * video/i386/pc/vbefill.c (grub_video_i386_vbefill_R8G8B8A8): Removed. + (grub_video_i386_vbefill_R8G8B8): Likewise. + (grub_video_i386_vbefill_index): Likewise. + (grub_video_i386_vbefill_direct32): Added. + (grub_video_i386_vbefill_direct24): Likewise. + (grub_video_i386_vbefill_direct16): Likewise. + (grub_video_i386_vbefill_direct8): Likewise. + + * video/readers/jpeg.c (grub_jpeg_decode_sos): Adapt to new blitter + types. + + * video/readers/tga.c (grub_video_reader_tga): Adapt to new blitter + types. + + * video/readers/png.c (grub_png_decode_image_header): Adapt to new + blitter types. + + * video/bitmap.c (grub_video_bitmap_create): Adapt to new blitter + types. + 2008-09-06 Felix Zielcke * disk/raid.c (insert_array): Set `array->chunk_size' to 64 for diff --git a/include/grub/i386/pc/vbeblit.h b/include/grub/i386/pc/vbeblit.h index 796c4888e..5a2aa7af0 100644 --- a/include/grub/i386/pc/vbeblit.h +++ b/include/grub/i386/pc/vbeblit.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007 Free Software Foundation, Inc. + * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,64 +25,70 @@ 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); +grub_video_i386_vbeblit_replace (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); +grub_video_i386_vbeblit_replace_directN (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); +grub_video_i386_vbeblit_replace_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_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); +grub_video_i386_vbeblit_replace_BGRX8888_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_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); +grub_video_i386_vbeblit_replace_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_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); +grub_video_i386_vbeblit_replace_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_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); +grub_video_i386_vbeblit_replace_RGBX8888_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_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); +grub_video_i386_vbeblit_replace_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_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); +grub_video_i386_vbeblit_replace_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_index_index (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); +grub_video_i386_vbeblit_replace_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); void grub_video_i386_vbeblit_blend (struct grub_video_i386_vbeblit_info *dst, @@ -91,9 +97,38 @@ grub_video_i386_vbeblit_blend (struct grub_video_i386_vbeblit_info *dst, int offset_x, int offset_y); void -grub_video_i386_vbeblit_replace (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); +grub_video_i386_vbeblit_blend_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_blend_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_blend_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); + +void +grub_video_i386_vbeblit_blend_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_blend_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); #endif /* ! GRUB_VBEBLIT_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/vbefill.h b/include/grub/i386/pc/vbefill.h index 3cc790b9e..efc6378d4 100644 --- a/include/grub/i386/pc/vbefill.h +++ b/include/grub/i386/pc/vbefill.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007 Free Software Foundation, Inc. + * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,24 +24,29 @@ struct grub_video_i386_vbeblit_info; -void -grub_video_i386_vbefill_R8G8B8A8 (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); - -void -grub_video_i386_vbefill_index (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 (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_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_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_direct16 (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_direct8 (struct grub_video_i386_vbeblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height); + #endif /* ! GRUB_VBEFILL_MACHINE_HEADER */ diff --git a/include/grub/video.h b/include/grub/video.h index b6c8fcdc8..13993267d 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -26,7 +26,7 @@ specific coding format. */ typedef grub_uint32_t grub_video_color_t; -/* This structure is driver specific and should not be accessed directly by +/* This structure is driver specific and should not be accessed directly by outside code. */ struct grub_video_render_target; @@ -55,14 +55,22 @@ struct grub_video_bitmap; /* Defined blitting formats. */ enum grub_video_blit_format { - /* Follow exactly field & mask information. */ + /* Generic RGBA, use fields & masks. */ GRUB_VIDEO_BLIT_FORMAT_RGBA, - /* Make optimization assumption. */ - GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8, - /* Follow exactly field & mask information. */ + + /* Optimized RGBA's. */ + GRUB_VIDEO_BLIT_FORMAT_RGBA_8888, + GRUB_VIDEO_BLIT_FORMAT_BGRA_8888, + + /* Generic RGB, use fields & masks. */ GRUB_VIDEO_BLIT_FORMAT_RGB, - /* Make optimization assumption. */ - GRUB_VIDEO_BLIT_FORMAT_R8G8B8, + + /* Optimized RGB's. */ + GRUB_VIDEO_BLIT_FORMAT_RGB_888, + GRUB_VIDEO_BLIT_FORMAT_BGR_888, + GRUB_VIDEO_BLIT_FORMAT_RGB_565, + GRUB_VIDEO_BLIT_FORMAT_BGR_565, + /* When needed, decode color or just use value as is. */ GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR }; @@ -84,7 +92,7 @@ struct grub_video_mode_info /* Height of the screen. */ unsigned int height; - /* Mode type bitmask. Contains information like is it Index color or + /* Mode type bitmask. Contains information like is it Index color or RGB mode. */ unsigned int mode_type; @@ -124,7 +132,7 @@ struct grub_video_mode_info /* How many bits are reserved in color. */ unsigned int reserved_mask_size; - /* What is location of reserved color bits. In Index Color mode, + /* What is location of reserved color bits. In Index Color mode, this is 0. */ unsigned int reserved_field_pos; }; diff --git a/video/bitmap.c b/video/bitmap.c index edbe8240d..8fda51166 100644 --- a/video/bitmap.c +++ b/video/bitmap.c @@ -78,7 +78,7 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap, 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 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap, 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; diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c index edd73d50d..41660ac06 100644 --- a/video/i386/pc/vbe.c +++ b/video/i386/pc/vbe.c @@ -217,7 +217,7 @@ grub_vbe_set_video_mode (grub_uint32_t mode, case 8: framebuffer.bytes_per_pixel = 1; break; default: grub_vbe_bios_set_mode (old_mode, 0); - return grub_error (GRUB_ERR_BAD_DEVICE, + return grub_error (GRUB_ERR_BAD_DEVICE, "cannot set VBE mode %x", mode); break; @@ -231,9 +231,9 @@ grub_vbe_set_video_mode (grub_uint32_t mode, /* Make sure that the BIOS can reach the palette. */ grub_memcpy (palette, vga_colors, sizeof (vga_colors)); - status = grub_vbe_bios_set_palette_data (sizeof (vga_colors) - / sizeof (struct grub_vbe_palette_data), - 0, + status = grub_vbe_bios_set_palette_data (sizeof (vga_colors) + / sizeof (struct grub_vbe_palette_data), + 0, palette); /* Just ignore the status. */ @@ -413,7 +413,7 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, unsigned int i; /* Decode depth from mode_type. If it is zero, then autodetect. */ - depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; /* Walk thru mode list and try to find matching mode. */ @@ -490,7 +490,7 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, /* Try to initialize best mode found. */ if (best_mode != 0) { - /* If this fails, then we have mode selection heuristics problem, + /* If this fails, then we have mode selection heuristics problem, or adapter failure. */ grub_vbe_set_video_mode (best_mode, &active_mode_info); if (grub_errno != GRUB_ERR_NONE) @@ -538,8 +538,8 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, render_target->data = framebuffer.ptr; /* Copy default palette to initialize emulated palette. */ - for (i = 0; - i < (sizeof (vga_colors) + for (i = 0; + i < (sizeof (vga_colors) / sizeof (struct grub_vbe_palette_data)); i++) { @@ -560,7 +560,7 @@ static grub_err_t grub_video_vbe_get_info (struct grub_video_mode_info *mode_info) { /* Copy mode info from active render target. */ - grub_memcpy (mode_info, &render_target->mode_info, + grub_memcpy (mode_info, &render_target->mode_info, sizeof (struct grub_video_mode_info)); return GRUB_ERR_NONE; @@ -575,9 +575,9 @@ grub_video_vbe_set_palette (unsigned int start, unsigned int count, if (framebuffer.index_color_mode) { /* TODO: Implement setting indexed color mode palette to hardware. */ - //status = grub_vbe_bios_set_palette_data (sizeof (vga_colors) - // / sizeof (struct grub_vbe_palette_data), - // 0, + //status = grub_vbe_bios_set_palette_data (sizeof (vga_colors) + // / sizeof (struct grub_vbe_palette_data), + // 0, // palette); } @@ -646,6 +646,7 @@ grub_video_vbe_get_viewport (unsigned int *x, unsigned int *y, return GRUB_ERR_NONE; } +/* Maps color name to target optimized color format. */ static grub_video_color_t grub_video_vbe_map_color (grub_uint32_t color_name) { @@ -671,11 +672,12 @@ grub_video_vbe_map_color (grub_uint32_t color_name) return 0; } +/* Maps RGB to target optimized color format. */ grub_video_color_t grub_video_vbe_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue) { - if ((render_target->mode_info.mode_type + if ((render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) { int minindex = 0; @@ -728,11 +730,12 @@ grub_video_vbe_map_rgb (grub_uint8_t red, grub_uint8_t green, } +/* Maps RGBA to target optimized color format. */ grub_video_color_t grub_video_vbe_map_rgba (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue, grub_uint8_t alpha) { - if ((render_target->mode_info.mode_type + if ((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. */ @@ -755,6 +758,7 @@ grub_video_vbe_map_rgba (grub_uint8_t red, grub_uint8_t green, } } +/* Splits target optimized format to components. */ grub_err_t grub_video_vbe_unmap_color (grub_video_color_t color, grub_uint8_t *red, grub_uint8_t *green, grub_uint8_t *blue, grub_uint8_t *alpha) @@ -765,10 +769,11 @@ grub_err_t grub_video_vbe_unmap_color (grub_video_color_t color, target_info.data = render_target->data; grub_video_vbe_unmap_color_int (&target_info, color, red, green, blue, alpha); - + return GRUB_ERR_NONE; } +/* Splits color in source format to components. */ void grub_video_vbe_unmap_color_int (struct grub_video_i386_vbeblit_info * source, grub_video_color_t color, @@ -778,7 +783,7 @@ grub_video_vbe_unmap_color_int (struct grub_video_i386_vbeblit_info * source, struct grub_video_mode_info *mode_info; mode_info = source->mode_info; - if ((mode_info->mode_type + if ((mode_info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) { /* If we have an out-of-bounds color, return transparent black. */ @@ -875,25 +880,42 @@ grub_video_vbe_fill_rect (grub_video_color_t color, int x, int y, target.mode_info = &render_target->mode_info; target.data = render_target->data; - /* Try to figure out more optimized version. */ - if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8) + /* Try to figure out more optimized version. Note that color is already + mapped to target format so we can make assumptions based on that. */ + if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) { - grub_video_i386_vbefill_R8G8B8A8 (&target, color, x, y, + grub_video_i386_vbefill_direct32 (&target, color, x, y, width, height); return GRUB_ERR_NONE; } - - if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8) + else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) { - grub_video_i386_vbefill_R8G8B8 (&target, color, x, y, - width, height); + grub_video_i386_vbefill_direct32 (&target, color, x, y, + width, height); return GRUB_ERR_NONE; } - - if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) { - grub_video_i386_vbefill_index (&target, color, x, y, - width, height); + grub_video_i386_vbefill_direct24 (&target, color, x, y, + width, height); + return GRUB_ERR_NONE; + } + else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_565) + { + grub_video_i386_vbefill_direct16 (&target, color, x, y, + width, height); + return GRUB_ERR_NONE; + } + else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_565) + { + grub_video_i386_vbefill_direct16 (&target, color, x, y, + width, height); + return GRUB_ERR_NONE; + } + else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + grub_video_i386_vbefill_direct8 (&target, color, x, y, + width, height); return GRUB_ERR_NONE; } @@ -965,15 +987,15 @@ grub_video_vbe_blit_glyph (struct grub_font_glyph * glyph, /* Draw glyph. */ for (j = 0; j < height; j++) for (i = 0; i < width; i++) - if ((glyph->bitmap[((i + x_offset) / 8) - + (j + y_offset) * (charwidth / 8)] + if ((glyph->bitmap[((i + x_offset) / 8) + + (j + y_offset) * (charwidth / 8)] & (1 << ((charwidth - (i + x_offset) - 1) % 8)))) set_pixel (&target, x+i, y+j, color); return GRUB_ERR_NONE; } -/* NOTE: This function assumes that given coordinates are within bounds of +/* NOTE: This function assumes that given coordinates are within bounds of handled data. */ static void common_blitter (struct grub_video_i386_vbeblit_info *target, @@ -985,146 +1007,193 @@ common_blitter (struct grub_video_i386_vbeblit_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_R8G8B8A8) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8) - { - grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8) - { - grub_video_i386_vbeblit_R8G8B8_R8G8B8X8 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - grub_video_i386_vbeblit_index_R8G8B8X8 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - } - - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8) - { - grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8) - { - grub_video_i386_vbeblit_R8G8B8_R8G8B8 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - grub_video_i386_vbeblit_index_R8G8B8 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - } - - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - grub_video_i386_vbeblit_index_index (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - } + if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) + { + if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_replace_index_RGBX8888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + } + 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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_replace_index_RGB888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + } + 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) + { + grub_video_i386_vbeblit_replace_directN (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + } + else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + grub_video_i386_vbeblit_replace_directN (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + } /* No optimized replace operator found, use default (slow) blitter. */ grub_video_i386_vbeblit_replace (target, source, x, y, width, height, - offset_x, offset_y); + offset_x, offset_y); } else { /* Try to figure out more optimized blend operator. */ - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8) - { - grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } + if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) + { + if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_blend_index_RGBA8888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + } + else if (source->mode_info->blit_format == 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_R8G8B8) - { - grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - grub_video_i386_vbeblit_index_R8G8B8A8 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - } - - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8) - { - grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8) - { - grub_video_i386_vbeblit_R8G8B8_R8G8B8 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - grub_video_i386_vbeblit_index_R8G8B8 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - } - - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - grub_video_i386_vbeblit_index_index (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - } + if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_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) + { + grub_video_i386_vbeblit_replace_index_RGB888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + } /* No optimized blend operation found, use default (slow) blitter. */ grub_video_i386_vbeblit_blend (target, source, x, y, width, height, - offset_x, offset_y); + offset_x, offset_y); } } @@ -1148,10 +1217,10 @@ grub_video_vbe_blit_bitmap (struct grub_video_bitmap *bitmap, return GRUB_ERR_NONE; if ((y + (int)bitmap->mode_info.height) < 0) return GRUB_ERR_NONE; - if ((offset_x >= (int)bitmap->mode_info.width) + if ((offset_x >= (int)bitmap->mode_info.width) || (offset_x + (int)width < 0)) return GRUB_ERR_NONE; - if ((offset_y >= (int)bitmap->mode_info.height) + if ((offset_y >= (int)bitmap->mode_info.height) || (offset_y + (int)height < 0)) return GRUB_ERR_NONE; @@ -1239,10 +1308,10 @@ grub_video_vbe_blit_render_target (struct grub_video_render_target *source, return GRUB_ERR_NONE; if ((y + (int)source->mode_info.height) < 0) return GRUB_ERR_NONE; - if ((offset_x >= (int)source->mode_info.width) + if ((offset_x >= (int)source->mode_info.width) || (offset_x + (int)width < 0)) return GRUB_ERR_NONE; - if ((offset_y >= (int)source->mode_info.height) + if ((offset_y >= (int)source->mode_info.height) || (offset_y + (int)height < 0)) return GRUB_ERR_NONE; @@ -1304,7 +1373,7 @@ grub_video_vbe_blit_render_target (struct grub_video_render_target *source, target_info.data = render_target->data; /* Do actual blitting. */ - common_blitter (&target_info, &source_info, oper, x, y, width, height, + common_blitter (&target_info, &source_info, oper, x, y, width, height, offset_x, offset_y); return GRUB_ERR_NONE; @@ -1350,7 +1419,7 @@ grub_video_vbe_scroll (grub_video_color_t color, int dx, int dy) } /* 2. Check if there is need to copy data. */ - if ((grub_abs (dx) < render_target->viewport.width) + if ((grub_abs (dx) < render_target->viewport.width) && (grub_abs (dy) < render_target->viewport.height)) { /* 3. Move data in render target. */ @@ -1389,7 +1458,7 @@ grub_video_vbe_scroll (grub_video_color_t color, int dx, int dy) /* 4b. Fill left & right parts. */ if (dx > 0) - grub_video_vbe_fill_rect (color, 0, 0, + grub_video_vbe_fill_rect (color, 0, 0, dx, render_target->viewport.height); else if (dx < 0) { @@ -1403,7 +1472,7 @@ grub_video_vbe_scroll (grub_video_color_t color, int dx, int dy) return GRUB_ERR_NONE; } -static grub_err_t +static grub_err_t grub_video_vbe_swap_buffers (void) { /* TODO: Implement buffer swapping. */ @@ -1445,7 +1514,7 @@ grub_video_vbe_create_render_target (struct grub_video_render_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 + 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; @@ -1513,11 +1582,11 @@ grub_video_vbe_set_active_render_target (struct grub_video_render_target *target } if (target == GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "double buffering not implemented yet."); if (! target->data) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid render target given."); render_target = target; @@ -1529,7 +1598,7 @@ static grub_err_t grub_video_vbe_get_active_render_target (struct grub_video_render_target **target) { *target = render_target; - + return GRUB_ERR_NONE; } diff --git a/video/i386/pc/vbeblit.c b/video/i386/pc/vbeblit.c index c5582f96a..4121bfe6c 100644 --- a/video/i386/pc/vbeblit.c +++ b/video/i386/pc/vbeblit.c @@ -34,308 +34,245 @@ #include #include +/* Generic replacing blitter (slow). Works for every supported format. */ 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) +grub_video_i386_vbeblit_replace (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) { - grub_uint32_t color; int i; + int j; + grub_uint8_t src_red; + grub_uint8_t src_green; + grub_uint8_t src_blue; + grub_uint8_t src_alpha; + grub_video_color_t src_color; + grub_video_color_t dst_color; + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + src_color = get_pixel (src, i + offset_x, j + offset_y); + + grub_video_vbe_unmap_color_int (src, src_color, &src_red, &src_green, + &src_blue, &src_alpha); + + dst_color = grub_video_vbe_map_rgba (src_red, src_green, + src_blue, src_alpha); + + set_pixel (dst, x + i, y + j, dst_color); + } + } +} + +/* Block copy replacing blitter. Works with modes multiple of 8 bits. */ +void +grub_video_i386_vbeblit_replace_directN (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) +{ int j; grub_uint32_t *srcptr; grub_uint32_t *dstptr; - unsigned int sr; - unsigned int sg; - unsigned int sb; - unsigned int a; - unsigned int dr; - unsigned int dg; - unsigned int db; + int bpp; - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ + bpp = src->mode_info->bytes_per_pixel; for (j = 0; j < height; j++) { srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j); + grub_memmove (dstptr, srcptr, width * bpp); + } +} + +/* Optimized replacing blitter for RGBX8888 to BGRX8888. */ +void +grub_video_i386_vbeblit_replace_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) +{ + int i; + int j; + grub_uint8_t *srcptr; + grub_uint8_t *dstptr; + unsigned int srcrowskip; + unsigned int dstrowskip; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; + dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + srcptr = (grub_uint8_t *) get_data_ptr (src, offset_x, offset_y); + dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { for (i = 0; i < width; i++) { + grub_uint8_t r = *srcptr++; + grub_uint8_t g = *srcptr++; + grub_uint8_t b = *srcptr++; + grub_uint8_t a = *srcptr++; + + *dstptr++ = b; + *dstptr++ = g; + *dstptr++ = r; + *dstptr++ = a; + } + + srcptr += srcrowskip; + dstptr += dstrowskip; + } +} + +/* Optimized replacing blitter for RGB888 to BGRX8888. */ +void +grub_video_i386_vbeblit_replace_BGRX8888_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) +{ + int i; + int j; + grub_uint8_t *srcptr; + grub_uint8_t *dstptr; + unsigned int srcrowskip; + unsigned int dstrowskip; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; + dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + srcptr = (grub_uint8_t *) get_data_ptr (src, offset_x, offset_y); + dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + grub_uint8_t r = *srcptr++; + grub_uint8_t g = *srcptr++; + grub_uint8_t b = *srcptr++; + + *dstptr++ = b; + *dstptr++ = g; + *dstptr++ = r; + + /* Set alpha component as opaque. */ + *dstptr++ = 255; + } + + srcptr += srcrowskip; + dstptr += dstrowskip; + } +} + +/* Optimized replacing blitter for RGBX8888 to BGR888. */ +void +grub_video_i386_vbeblit_replace_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) +{ + grub_uint32_t *srcptr; + grub_uint8_t *dstptr; + unsigned int srcrowskip; + unsigned int dstrowskip; + int i; + int j; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; + dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + srcptr = (grub_uint32_t *) get_data_ptr (src, offset_x, offset_y); + dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + grub_uint32_t color; + grub_uint8_t sr; + grub_uint8_t sg; + grub_uint8_t sb; + color = *srcptr++; - a = color >> 24; - - if (a == 0) - { - dstptr++; - continue; - } - - if (a == 255) - { - *dstptr++ = color; - continue; - } - sr = (color >> 0) & 0xFF; sg = (color >> 8) & 0xFF; sb = (color >> 16) & 0xFF; - color = *dstptr; - - dr = (color >> 0) & 0xFF; - dg = (color >> 8) & 0xFF; - db = (color >> 16) & 0xFF; - - dr = (dr * (255 - a) + sr * a) / 255; - dg = (dg * (255 - a) + sg * a) / 255; - db = (db * (255 - a) + sb * a) / 255; - - color = (a << 24) | (db << 16) | (dg << 8) | dr; - - *dstptr++ = color; + *dstptr++ = sb; + *dstptr++ = sg; + *dstptr++ = sr; } + + srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); + dstptr += dstrowskip; } } +/* Optimized replacing blitter for RGB888 to BGR888. */ 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) +grub_video_i386_vbeblit_replace_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) { - int j; - grub_uint32_t *srcptr; - grub_uint32_t *dstptr; - int pitch; - - pitch = src->mode_info->bytes_per_pixel; - - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j); - - grub_memmove (dstptr, srcptr, width * pitch); - } -} - -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) -{ - grub_uint32_t color; int i; int j; - grub_uint32_t *srcptr; + grub_uint8_t *srcptr; grub_uint8_t *dstptr; - unsigned int sr; - unsigned int sg; - unsigned int sb; - unsigned int a; - unsigned int dr; - unsigned int dg; - unsigned int db; + unsigned int srcrowskip; + unsigned int dstrowskip; - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; + dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + srcptr = (grub_uint8_t *) get_data_ptr (src, offset_x, offset_y); + dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { - color = *srcptr++; + grub_uint8_t r = *srcptr++; + grub_uint8_t g = *srcptr++; + grub_uint8_t b = *srcptr++; - a = color >> 24; - - if (a == 0) - { - dstptr += 3; - continue; - } - - sr = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sb = (color >> 16) & 0xFF; - - if (a == 255) - { - *dstptr++ = sr; - *dstptr++ = sg; - *dstptr++ = sb; - - continue; - } - - dr = dstptr[0]; - dg = dstptr[1]; - db = dstptr[2]; - - dr = (dr * (255 - a) + sr * a) / 255; - dg = (dg * (255 - a) + sg * a) / 255; - db = (db * (255 - a) + sb * a) / 255; - - *dstptr++ = dr; - *dstptr++ = dg; - *dstptr++ = db; + *dstptr++ = b; + *dstptr++ = g; + *dstptr++ = r; } + + srcptr += srcrowskip; + dstptr += dstrowskip; } } +/* Optimized replacing blitter for RGB888 to RGBX8888. */ 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) -{ - grub_uint32_t color; - int i; - int j; - grub_uint32_t *srcptr; - grub_uint8_t *dstptr; - unsigned int sr; - unsigned int sg; - unsigned int sb; - - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - { - color = *srcptr++; - - sr = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sb = (color >> 16) & 0xFF; - - *dstptr++ = sr; - *dstptr++ = sg; - *dstptr++ = sb; - } - } -} - -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) -{ - grub_uint32_t color; - int i; - int j; - grub_uint32_t *srcptr; - grub_uint8_t *dstptr; - unsigned int sr; - unsigned int sg; - unsigned int sb; - unsigned int a; - unsigned char dr; - unsigned char dg; - unsigned char db; - unsigned char da; - - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - { - color = *srcptr++; - - a = color >> 24; - - if (a == 0) - { - dstptr++; - continue; - } - - sr = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sb = (color >> 16) & 0xFF; - - if (a == 255) - { - color = grub_video_vbe_map_rgb(sr, sg, sb); - *dstptr++ = color & 0xFF; - continue; - } - - grub_video_vbe_unmap_color_int (dst, *dstptr, &dr, &dg, &db, &da); - - dr = (dr * (255 - a) + sr * a) / 255; - dg = (dg * (255 - a) + sg * a) / 255; - db = (db * (255 - a) + sb * a) / 255; - - color = grub_video_vbe_map_rgb(dr, dg, db); - - *dstptr++ = color & 0xFF; - } - } -} - -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) -{ - grub_uint32_t color; - int i; - int j; - grub_uint32_t *srcptr; - grub_uint8_t *dstptr; - unsigned int sr; - unsigned int sg; - unsigned int sb; - - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - { - color = *srcptr++; - - sr = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sb = (color >> 16) & 0xFF; - - color = grub_video_vbe_map_rgb(sr, sg, sb); - *dstptr++ = color & 0xFF; - } - } -} - -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) +grub_video_i386_vbeblit_replace_RGBX8888_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) { grub_uint32_t color; int i; @@ -346,9 +283,6 @@ grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_i386_vbeblit_info *ds unsigned int sg; unsigned int sb; - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ - for (j = 0; j < height; j++) { srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y); @@ -360,6 +294,7 @@ grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_i386_vbeblit_info *ds sg = *srcptr++; sb = *srcptr++; + /* Set alpha as opaque. */ color = 0xFF000000 | (sb << 16) | (sg << 8) | sr; *dstptr++ = color; @@ -367,36 +302,86 @@ grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_i386_vbeblit_info *ds } } +/* Optimized replacing blitter for RGBX8888 to RGB888. */ 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) +grub_video_i386_vbeblit_replace_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) { + grub_uint32_t color; + int i; int j; - grub_uint8_t *srcptr; + grub_uint32_t *srcptr; grub_uint8_t *dstptr; - int pitch; - - pitch = src->mode_info->bytes_per_pixel; - - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ + unsigned int sr; + unsigned int sg; + unsigned int sb; for (j = 0; j < height; j++) { - srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y); + srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - grub_memmove (dstptr, srcptr, width * pitch); + for (i = 0; i < width; i++) + { + color = *srcptr++; + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + *dstptr++ = sr; + *dstptr++ = sg; + *dstptr++ = sb; + } } } +/* Optimized replacing blitter for RGBX8888 to indexed color. */ void -grub_video_i386_vbeblit_index_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) +grub_video_i386_vbeblit_replace_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) +{ + grub_uint32_t color; + int i; + int j; + grub_uint32_t *srcptr; + grub_uint8_t *dstptr; + unsigned int sr; + unsigned int sg; + unsigned int sb; + + for (j = 0; j < height; j++) + { + srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + { + color = *srcptr++; + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + color = grub_video_vbe_map_rgb(sr, sg, sb); + *dstptr++ = color & 0xFF; + } + } +} + +/* Optimized replacing blitter for RGB888 to indexed color. */ +void +grub_video_i386_vbeblit_replace_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) { grub_uint32_t color; int i; @@ -407,9 +392,6 @@ grub_video_i386_vbeblit_index_R8G8B8 (struct grub_video_i386_vbeblit_info *dst, unsigned int sg; unsigned int sb; - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ - for (j = 0; j < height; j++) { srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y); @@ -428,31 +410,7 @@ grub_video_i386_vbeblit_index_R8G8B8 (struct grub_video_i386_vbeblit_info *dst, } } -void -grub_video_i386_vbeblit_index_index (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) -{ - int j; - grub_uint8_t *srcptr; - grub_uint8_t *dstptr; - int pitch; - - pitch = src->mode_info->bytes_per_pixel; - - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - - grub_memmove (dstptr, srcptr, width * pitch); - } -} - +/* Generic blending blitter. Works for every supported format. */ void grub_video_i386_vbeblit_blend (struct grub_video_i386_vbeblit_info *dst, struct grub_video_i386_vbeblit_info *src, @@ -462,9 +420,6 @@ grub_video_i386_vbeblit_blend (struct grub_video_i386_vbeblit_info *dst, int i; int j; - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ - for (j = 0; j < height; j++) { for (i = 0; i < width; i++) @@ -516,35 +471,358 @@ grub_video_i386_vbeblit_blend (struct grub_video_i386_vbeblit_info *dst, } } +/* Optimized blending blitter for RGBA8888 to BGRA8888. */ void -grub_video_i386_vbeblit_replace (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) +grub_video_i386_vbeblit_blend_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) { + grub_uint32_t *srcptr; + grub_uint32_t *dstptr; + unsigned int srcrowskip; + unsigned int dstrowskip; int i; int j; - grub_uint8_t src_red; - grub_uint8_t src_green; - grub_uint8_t src_blue; - grub_uint8_t src_alpha; - grub_video_color_t src_color; - grub_video_color_t dst_color; - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; + dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + srcptr = (grub_uint32_t *) get_data_ptr (src, offset_x, offset_y); + dstptr = (grub_uint32_t *) get_data_ptr (dst, x, y); for (j = 0; j < height; j++) - { - for (i = 0; i < width; i++) { - src_color = get_pixel (src, i + offset_x, j + offset_y); - grub_video_vbe_unmap_color_int (src, src_color, &src_red, &src_green, - &src_blue, &src_alpha); + for (i = 0; i < width; i++) + { + grub_uint32_t color; + unsigned int sr; + unsigned int sg; + unsigned int sb; + unsigned int a; + unsigned int dr; + unsigned int dg; + unsigned int db; - dst_color = grub_video_vbe_map_rgba (src_red, src_green, - src_blue, src_alpha); - set_pixel (dst, x + i, y + j, dst_color); + color = *srcptr++; + + a = color >> 24; + + if (a == 0) + { + /* Skip transparent source pixels. */ + dstptr++; + continue; + } + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + if (a == 255) + { + /* Opaque pixel shortcut. */ + dr = sr; + dg = sg; + db = sb; + } + else + { + /* General pixel color blending. */ + color = *dstptr; + + dr = (color >> 16) & 0xFF; + dr = (dr * (255 - a) + sr * a) / 255; + dg = (color >> 8) & 0xFF; + dg = (dg * (255 - a) + sg * a) / 255; + db = (color >> 0) & 0xFF; + db = (db * (255 - a) + sb * a) / 255; + } + + color = (a << 24) | (dr << 16) | (dg << 8) | db; + + *dstptr++ = color; + } + + srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); + dstptr = (grub_uint32_t *) (((grub_uint8_t *) dstptr) + dstrowskip); + } +} + +/* Optimized blending blitter for RGBA8888 to BGR888. */ +void +grub_video_i386_vbeblit_blend_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) +{ + grub_uint32_t *srcptr; + grub_uint8_t *dstptr; + unsigned int srcrowskip; + unsigned int dstrowskip; + int i; + int j; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; + dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + srcptr = (grub_uint32_t *) get_data_ptr (src, offset_x, offset_y); + dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + grub_uint32_t color; + unsigned int sr; + unsigned int sg; + unsigned int sb; + unsigned int a; + unsigned int dr; + unsigned int dg; + unsigned int db; + + color = *srcptr++; + + a = color >> 24; + + if (a == 0) + { + /* Skip transparent source pixels. */ + dstptr += 3; + continue; + } + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + if (a == 255) + { + /* Opaque pixel shortcut. */ + dr = sr; + dg = sg; + db = sb; + } + else + { + /* General pixel color blending. */ + color = *dstptr; + + db = dstptr[0]; + db = (db * (255 - a) + sb * a) / 255; + dg = dstptr[1]; + dg = (dg * (255 - a) + sg * a) / 255; + dr = dstptr[2]; + dr = (dr * (255 - a) + sr * a) / 255; + } + + *dstptr++ = db; + *dstptr++ = dg; + *dstptr++ = dr; + } + + srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); + dstptr += dstrowskip; + } +} + +/* Optimized blending blitter for RGBA888 to RGBA8888. */ +void +grub_video_i386_vbeblit_blend_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) +{ + grub_uint32_t color; + int i; + int j; + grub_uint32_t *srcptr; + grub_uint32_t *dstptr; + unsigned int sr; + unsigned int sg; + unsigned int sb; + unsigned int a; + unsigned int dr; + unsigned int dg; + unsigned int db; + + for (j = 0; j < height; j++) + { + srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + { + color = *srcptr++; + + a = color >> 24; + + if (a == 0) + { + dstptr++; + continue; + } + + if (a == 255) + { + *dstptr++ = color; + continue; + } + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + color = *dstptr; + + dr = (color >> 0) & 0xFF; + dg = (color >> 8) & 0xFF; + db = (color >> 16) & 0xFF; + + dr = (dr * (255 - a) + sr * a) / 255; + dg = (dg * (255 - a) + sg * a) / 255; + db = (db * (255 - a) + sb * a) / 255; + + color = (a << 24) | (db << 16) | (dg << 8) | dr; + + *dstptr++ = color; + } + } +} + +/* Optimized blending blitter for RGBA8888 to RGB888. */ +void +grub_video_i386_vbeblit_blend_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) +{ + grub_uint32_t color; + int i; + int j; + grub_uint32_t *srcptr; + grub_uint8_t *dstptr; + unsigned int sr; + unsigned int sg; + unsigned int sb; + unsigned int a; + unsigned int dr; + unsigned int dg; + unsigned int db; + + for (j = 0; j < height; j++) + { + srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + { + color = *srcptr++; + + a = color >> 24; + + if (a == 0) + { + dstptr += 3; + continue; + } + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + if (a == 255) + { + *dstptr++ = sr; + *dstptr++ = sg; + *dstptr++ = sb; + + continue; + } + + dr = dstptr[0]; + dg = dstptr[1]; + db = dstptr[2]; + + dr = (dr * (255 - a) + sr * a) / 255; + dg = (dg * (255 - a) + sg * a) / 255; + db = (db * (255 - a) + sb * a) / 255; + + *dstptr++ = dr; + *dstptr++ = dg; + *dstptr++ = db; + } + } +} + +/* Optimized blending blitter for RGBA8888 to indexed color. */ +void +grub_video_i386_vbeblit_blend_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) +{ + grub_uint32_t color; + int i; + int j; + grub_uint32_t *srcptr; + grub_uint8_t *dstptr; + unsigned int sr; + unsigned int sg; + unsigned int sb; + unsigned int a; + unsigned char dr; + unsigned char dg; + unsigned char db; + unsigned char da; + + for (j = 0; j < height; j++) + { + srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + { + color = *srcptr++; + + a = color >> 24; + + if (a == 0) + { + dstptr++; + continue; + } + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + if (a == 255) + { + color = grub_video_vbe_map_rgb(sr, sg, sb); + *dstptr++ = color & 0xFF; + continue; + } + + grub_video_vbe_unmap_color_int (dst, *dstptr, &dr, &dg, &db, &da); + + dr = (dr * (255 - a) + sr * a) / 255; + dg = (dg * (255 - a) + sg * a) / 255; + db = (db * (255 - a) + sb * a) / 255; + + color = grub_video_vbe_map_rgb(dr, dg, db); + + *dstptr++ = color & 0xFF; + } } - } } diff --git a/video/i386/pc/vbefill.c b/video/i386/pc/vbefill.c index 8ba550ad9..3a98a715a 100644 --- a/video/i386/pc/vbefill.c +++ b/video/i386/pc/vbefill.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007 Free Software Foundation, Inc. + * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,77 +33,7 @@ #include #include -void -grub_video_i386_vbefill_R8G8B8A8 (struct grub_video_i386_vbeblit_info *dst, - grub_video_color_t color, int x, int y, - int width, int height) -{ - int i; - int j; - grub_uint32_t *dstptr; - - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ - - for (j = 0; j < height; j++) - { - dstptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - *dstptr++ = color; - } -} - -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) -{ - int i; - int j; - grub_uint8_t *dstptr; - grub_uint8_t fillr = (grub_uint8_t)((color >> 0) & 0xFF); - grub_uint8_t fillg = (grub_uint8_t)((color >> 8) & 0xFF); - grub_uint8_t fillb = (grub_uint8_t)((color >> 16) & 0xFF); - - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ - - for (j = 0; j < height; j++) - { - dstptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - { - *dstptr++ = fillr; - *dstptr++ = fillg; - *dstptr++ = fillb; - } - } -} - -void -grub_video_i386_vbefill_index (struct grub_video_i386_vbeblit_info *dst, - grub_video_color_t color, int x, int y, - int width, int height) -{ - int i; - int j; - grub_uint8_t *dstptr; - grub_uint8_t fill = (grub_uint8_t)color & 0xFF; - - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ - - for (j = 0; j < height; j++) - { - dstptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - *dstptr++ = fill; - } -} - +/* Generic filler that works for every supported mode. */ void grub_video_i386_vbefill (struct grub_video_i386_vbeblit_info *dst, grub_video_color_t color, int x, int y, @@ -112,10 +42,136 @@ grub_video_i386_vbefill (struct grub_video_i386_vbeblit_info *dst, int i; int j; - /* We do not need to worry about data being out of bounds - as we assume that everything has been checked before. */ - for (j = 0; j < height; j++) for (i = 0; i < width; i++) set_pixel (dst, x+i, y+j, color); } + +/* Optimized filler for direct color 32 bit modes. It is assumed that color + is already mapped to destination format. */ +void +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) +{ + int i; + int j; + grub_uint32_t *dstptr; + grub_size_t rowskip; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + /* Get the start address. */ + dstptr = (grub_uint32_t *) grub_video_vbe_get_video_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + *dstptr++ = color; + + /* Advance the dest pointer to the right location on the next line. */ + dstptr = (grub_uint32_t *) (((char *) dstptr) + rowskip); + } +} + +/* Optimized filler for direct color 24 bit modes. It is assumed that color + is already mapped to destination format. */ +void +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) +{ + int i; + int j; + grub_size_t rowskip; + grub_uint8_t *dstptr; + grub_uint8_t fill0 = (grub_uint8_t)((color >> 0) & 0xFF); + grub_uint8_t fill1 = (grub_uint8_t)((color >> 8) & 0xFF); + grub_uint8_t fill2 = (grub_uint8_t)((color >> 16) & 0xFF); + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + /* Get the start address. */ + dstptr = (grub_uint8_t *) grub_video_vbe_get_video_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + *dstptr++ = fill0; + *dstptr++ = fill1; + *dstptr++ = fill2; + } + + /* Advance the dest pointer to the right location on the next line. */ + dstptr += rowskip; + } +} + +/* Optimized filler for direct color 16 bit modes. It is assumed that color + is already mapped to destination format. */ +void +grub_video_i386_vbefill_direct16 (struct grub_video_i386_vbeblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height) +{ + int i; + int j; + grub_size_t rowskip; + grub_uint8_t *dstptr; + grub_uint8_t fill0 = (grub_uint8_t)((color >> 0) & 0xFF); + grub_uint8_t fill1 = (grub_uint8_t)((color >> 8) & 0xFF); + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + /* Get the start address. */ + dstptr = (grub_uint8_t *) grub_video_vbe_get_video_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + *dstptr++ = fill0; + *dstptr++ = fill1; + } + + /* Advance the dest pointer to the right location on the next line. */ + dstptr += rowskip; + } +} + +/* Optimized filler for index color. It is assumed that color + is already mapped to destination format. */ +void +grub_video_i386_vbefill_direct8 (struct grub_video_i386_vbeblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height) +{ + int i; + int j; + grub_size_t rowskip; + grub_uint8_t *dstptr; + grub_uint8_t fill = (grub_uint8_t)color & 0xFF; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + /* Get the start address. */ + dstptr = (grub_uint8_t *) grub_video_vbe_get_video_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + *dstptr++ = fill; + + /* Advance the dest pointer to the right location on the next line. */ + dstptr += rowskip; + } +} diff --git a/video/readers/jpeg.c b/video/readers/jpeg.c index 03f3a9437..327c9f91c 100644 --- a/video/readers/jpeg.c +++ b/video/readers/jpeg.c @@ -542,7 +542,7 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) 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; diff --git a/video/readers/png.c b/video/readers/png.c index ceb77e72c..3364d56c0 100644 --- a/video/readers/png.c +++ b/video/readers/png.c @@ -231,7 +231,7 @@ grub_png_decode_image_header (struct grub_png_data *data) { 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 @@ grub_png_decode_image_header (struct grub_png_data *data) { 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; } diff --git a/video/readers/tga.c b/video/readers/tga.c index e99841532..de56008cb 100644 --- a/video/readers/tga.c +++ b/video/readers/tga.c @@ -397,7 +397,7 @@ grub_video_reader_tga (struct grub_video_bitmap **bitmap, { 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_reader_tga (struct grub_video_bitmap **bitmap, { 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); diff --git a/video/video.c b/video/video.c index c365afeb4..1caf8861b 100644 --- a/video/video.c +++ b/video/video.c @@ -108,7 +108,7 @@ grub_video_setup (unsigned int width, unsigned int height, } /* We couldn't find suitable adapter for specified mode. */ - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't locate valid adapter for mode"); } @@ -140,7 +140,7 @@ grub_video_get_info (struct grub_video_mode_info *mode_info) grub_errno = GRUB_ERR_NONE; return grub_errno; } - + return grub_video_adapter_active->get_info (mode_info); } @@ -152,40 +152,82 @@ grub_video_get_blit_format (struct grub_video_mode_info *mode_info) if (mode_info->bpp == 32) { 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)) - { - return GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8; - } + && (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; + } + else 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_RGBA_8888; + } } - /* Check if we have any known 24 bit modes. */ - if (mode_info->bpp == 24) + else if (mode_info->bpp == 24) { 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; - } + && (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; + } + else 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_RGB_888; + } } + /* Check if we have any known 16 bit modes. */ + else if (mode_info->bpp == 16) + { + if ((mode_info->red_mask_size == 5) + && (mode_info->red_field_pos == 11) + && (mode_info->green_mask_size == 6) + && (mode_info->green_field_pos == 5) + && (mode_info->blue_mask_size == 5) + && (mode_info->blue_field_pos == 0)) + { + return GRUB_VIDEO_BLIT_FORMAT_BGR_565; + } + else if ((mode_info->red_mask_size == 5) + && (mode_info->red_field_pos == 0) + && (mode_info->green_mask_size == 6) + && (mode_info->green_field_pos == 5) + && (mode_info->blue_mask_size == 5) + && (mode_info->blue_field_pos == 11)) + { + return GRUB_VIDEO_BLIT_FORMAT_RGB_565; + } + } + + /* Backup route. Unknown format. */ /* If there are more than 8 bits per color, assume RGB(A) mode. */ if (mode_info->bpp > 8) { if (mode_info->reserved_mask_size > 0) - { - return GRUB_VIDEO_BLIT_FORMAT_RGBA; - } - return GRUB_VIDEO_BLIT_FORMAT_RGB; + { + return GRUB_VIDEO_BLIT_FORMAT_RGBA; + } + else + { + return GRUB_VIDEO_BLIT_FORMAT_RGB; + } } /* Assume as indexcolor mode. */ @@ -269,8 +311,8 @@ grub_video_map_rgba (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue, /* Unmap video color back to RGBA components. */ grub_err_t -grub_video_unmap_color (grub_video_color_t color, grub_uint8_t *red, - grub_uint8_t *green, grub_uint8_t *blue, +grub_video_unmap_color (grub_video_color_t color, grub_uint8_t *red, + grub_uint8_t *green, grub_uint8_t *blue, grub_uint8_t *alpha) { if (! grub_video_adapter_active)