diff --git a/ChangeLog b/ChangeLog index 8ac2d7186..dbcbfc90c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +2006-03-31 Vesa Jaaskelainen + + * DISTLIST: Added include/grub/i386/pc/vbeblit.h, + include/grub/i386/pc/vbefill.h, video/i386/pc/vbeblit.c, + video/i386/pc/vbefill.c. + + * conf/i386-pc.rmk (vbe_mod_SOURCES): Added video/i386/pc/vbeblit.c, + video/i386/pc/vbefill.c. + + * include/grub/video.h (grub_video_blit_format): New enum. + (grub_video_mode_info): Added new member blit_format. + (grub_video_get_blit_format): New function prototype. + + * include/grub/i386/pc/vbe.h (grub_video_vbe_get_video_ptr): New + function prototype. + (grub_video_vbe_map_rgb): Likewise. + (grub_video_vbe_unmap_color): Likewise. + + * include/grub/i386/pc/vbeblit.h: New file. + + * include/grub/i386/pc/vbefill.h: New file. + + * video/video.c (grub_video_get_blit_format): New function. + (grub_video_vbe_get_video_ptr): Re-declared as non-static. + (grub_video_vbe_map_rgb): Likewise. + (grub_video_vbe_unmap_color): Likewise. + + * video/i386/pc/vbe.c (grub_video_vbe_fill_rect): Changed to use more + optimized fills. + (grub_video_vbe_blit_render_target): Changed to use more optimized + blits. + (grub_video_vbe_setup): Added detection for optimized settings. + (grub_video_vbe_create_render_target): Likewise. + + * video/i386/pc/vbeblit.c: New file. + + * video/i386/pc/vbefill.c: New file. + 2006-03-30 Vesa Jaaskelainen * font/manager.c (grub_font_get_glyph): Removed font fixup from diff --git a/DISTLIST b/DISTLIST index 1d3f3eaf9..0deb9be73 100644 --- a/DISTLIST +++ b/DISTLIST @@ -124,6 +124,8 @@ include/grub/i386/pc/multiboot.h include/grub/i386/pc/serial.h include/grub/i386/pc/time.h include/grub/i386/pc/vbe.h +include/grub/i386/pc/vbeblit.h +include/grub/i386/pc/vbefill.h include/grub/i386/pc/vga.h include/grub/i386/pc/util/biosdisk.h include/grub/ieee1275/ieee1275.h @@ -235,3 +237,5 @@ util/powerpc/ieee1275/grub-mkimage.c util/powerpc/ieee1275/misc.c video/video.c video/i386/pc/vbe.c +video/i386/pc/vbeblit.c +video/i386/pc/vbefill.c diff --git a/conf/i386-pc.mk b/conf/i386-pc.mk index bac43b4b7..8b711936c 100644 --- a/conf/i386-pc.mk +++ b/conf/i386-pc.mk @@ -2108,9 +2108,10 @@ multiboot_mod_CFLAGS = $(COMMON_CFLAGS) multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) # For vbe.mod. -vbe_mod_SOURCES = video/i386/pc/vbe.c -CLEANFILES += vbe.mod mod-vbe.o mod-vbe.c pre-vbe.o vbe_mod-video_i386_pc_vbe.o def-vbe.lst und-vbe.lst -MOSTLYCLEANFILES += vbe_mod-video_i386_pc_vbe.d +vbe_mod_SOURCES = video/i386/pc/vbe.c video/i386/pc/vbeblit.c \ + video/i386/pc/vbefill.c +CLEANFILES += vbe.mod mod-vbe.o mod-vbe.c pre-vbe.o vbe_mod-video_i386_pc_vbe.o vbe_mod-video_i386_pc_vbeblit.o vbe_mod-video_i386_pc_vbefill.o def-vbe.lst und-vbe.lst +MOSTLYCLEANFILES += vbe_mod-video_i386_pc_vbe.d vbe_mod-video_i386_pc_vbeblit.d vbe_mod-video_i386_pc_vbefill.d DEFSYMFILES += def-vbe.lst UNDSYMFILES += und-vbe.lst @@ -2119,7 +2120,7 @@ vbe.mod: pre-vbe.o mod-vbe.o $(LD) $(vbe_mod_LDFLAGS) $(LDFLAGS) -r -d -o $@ $^ $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ -pre-vbe.o: vbe_mod-video_i386_pc_vbe.o +pre-vbe.o: vbe_mod-video_i386_pc_vbe.o vbe_mod-video_i386_pc_vbeblit.o vbe_mod-video_i386_pc_vbefill.o -rm -f $@ $(LD) $(vbe_mod_LDFLAGS) -r -d -o $@ $^ @@ -2155,6 +2156,44 @@ fs-vbe_mod-video_i386_pc_vbe.lst: video/i386/pc/vbe.c genfslist.sh set -e; $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh vbe > $@ || (rm -f $@; exit 1) +vbe_mod-video_i386_pc_vbeblit.o: video/i386/pc/vbeblit.c + $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -c -o $@ $< + +vbe_mod-video_i386_pc_vbeblit.d: video/i386/pc/vbeblit.c + set -e; $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -M $< | sed 's,vbeblit\.o[ :]*,vbe_mod-video_i386_pc_vbeblit.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include vbe_mod-video_i386_pc_vbeblit.d + +CLEANFILES += cmd-vbe_mod-video_i386_pc_vbeblit.lst fs-vbe_mod-video_i386_pc_vbeblit.lst +COMMANDFILES += cmd-vbe_mod-video_i386_pc_vbeblit.lst +FSFILES += fs-vbe_mod-video_i386_pc_vbeblit.lst + +cmd-vbe_mod-video_i386_pc_vbeblit.lst: video/i386/pc/vbeblit.c gencmdlist.sh + set -e; $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh vbe > $@ || (rm -f $@; exit 1) + +fs-vbe_mod-video_i386_pc_vbeblit.lst: video/i386/pc/vbeblit.c genfslist.sh + set -e; $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh vbe > $@ || (rm -f $@; exit 1) + + +vbe_mod-video_i386_pc_vbefill.o: video/i386/pc/vbefill.c + $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -c -o $@ $< + +vbe_mod-video_i386_pc_vbefill.d: video/i386/pc/vbefill.c + set -e; $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -M $< | sed 's,vbefill\.o[ :]*,vbe_mod-video_i386_pc_vbefill.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include vbe_mod-video_i386_pc_vbefill.d + +CLEANFILES += cmd-vbe_mod-video_i386_pc_vbefill.lst fs-vbe_mod-video_i386_pc_vbefill.lst +COMMANDFILES += cmd-vbe_mod-video_i386_pc_vbefill.lst +FSFILES += fs-vbe_mod-video_i386_pc_vbefill.lst + +cmd-vbe_mod-video_i386_pc_vbefill.lst: video/i386/pc/vbefill.c gencmdlist.sh + set -e; $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh vbe > $@ || (rm -f $@; exit 1) + +fs-vbe_mod-video_i386_pc_vbefill.lst: video/i386/pc/vbefill.c genfslist.sh + set -e; $(CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(CPPFLAGS) $(CFLAGS) $(vbe_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh vbe > $@ || (rm -f $@; exit 1) + + vbe_mod_CFLAGS = $(COMMON_CFLAGS) vbe_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index f75ab7f3e..d878b136c 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -174,7 +174,8 @@ multiboot_mod_CFLAGS = $(COMMON_CFLAGS) multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) # For vbe.mod. -vbe_mod_SOURCES = video/i386/pc/vbe.c +vbe_mod_SOURCES = video/i386/pc/vbe.c video/i386/pc/vbeblit.c \ + video/i386/pc/vbefill.c vbe_mod_CFLAGS = $(COMMON_CFLAGS) vbe_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index b03bf97c6..e33cfac3e 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005 Free Software Foundation, Inc. + * Copyright (C) 2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,6 +23,7 @@ #include #include #include +#include /* Default video mode to be used. */ #define GRUB_VBE_DEFAULT_VIDEO_MODE 0x101 @@ -203,4 +204,18 @@ grub_err_t grub_vbe_get_video_mode (grub_uint32_t *mode); grub_err_t grub_vbe_get_video_mode_info (grub_uint32_t mode, struct grub_vbe_mode_info_block *mode_info); +/* VBE module internal prototypes (should not be used from elsewhere). */ +grub_uint8_t * grub_video_vbe_get_video_ptr (struct grub_video_render_target *source, + grub_uint32_t x, + grub_uint32_t y); + +grub_video_color_t grub_video_vbe_map_rgb (grub_uint8_t red, + grub_uint8_t green, + grub_uint8_t blue); + +void grub_video_vbe_unmap_color (struct grub_video_render_target * source, + grub_video_color_t color, grub_uint8_t *red, + grub_uint8_t *green, grub_uint8_t *blue, + grub_uint8_t *alpha); + #endif /* ! GRUB_VBE_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/vbeblit.h b/include/grub/i386/pc/vbeblit.h new file mode 100644 index 000000000..890b57700 --- /dev/null +++ b/include/grub/i386/pc/vbeblit.h @@ -0,0 +1,66 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef GRUB_VBEBLIT_MACHINE_HEADER +#define GRUB_VBEBLIT_MACHINE_HEADER 1 + +void +grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (struct grub_video_render_target *dst, + struct grub_video_render_target *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_render_target *dst, + struct grub_video_render_target *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_render_target *dst, + struct grub_video_render_target *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_render_target *dst, + struct grub_video_render_target *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_render_target *dst, + struct grub_video_render_target *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_render_target *dst, + struct grub_video_render_target *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_render_target *dst, + struct grub_video_render_target *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 new file mode 100644 index 000000000..14f7b5323 --- /dev/null +++ b/include/grub/i386/pc/vbefill.h @@ -0,0 +1,40 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef GRUB_VBEFILL_MACHINE_HEADER +#define GRUB_VBEFILL_MACHINE_HEADER 1 + +#include + +void +grub_video_i386_vbefill_R8G8B8A8 (struct grub_video_render_target *dst, + grub_video_color_t color, int x, int y, + int width, int height); + +void +grub_video_i386_vbefill_R8G8B8 (struct grub_video_render_target *dst, + grub_video_color_t color, int x, int y, + int width, int height); + +void +grub_video_i386_vbefill_index (struct grub_video_render_target *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 934e7b939..7a894e3b9 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -46,6 +46,21 @@ struct grub_video_render_target; #define GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER ((struct grub_video_render_target *) 0) #define GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER ((struct grub_video_render_target *) 1) +/* Defined blitting formats. */ +enum grub_video_blit_format + { + /* Follow exactly field & mask information. */ + GRUB_VIDEO_BLIT_FORMAT_RGBA, + /* Make optimization assumption. */ + GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8, + /* Follow exactly field & mask information. */ + GRUB_VIDEO_BLIT_FORMAT_RGB, + /* Make optimization assumption. */ + GRUB_VIDEO_BLIT_FORMAT_R8G8B8, + /* When needed, decode color or just use value as is. */ + GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR + }; + struct grub_video_mode_info { /* Width of the screen. */ @@ -70,6 +85,9 @@ struct grub_video_mode_info /* In index color mode, number of colors. In RGB mode this is 256. */ unsigned int number_of_colors; + /* Optimization hint how binary data is coded. */ + enum grub_video_blit_format blit_format; + /* How many bits are reserved for red color. */ unsigned int red_mask_size; @@ -235,6 +253,8 @@ grub_err_t EXPORT_FUNC(grub_video_restore) (void); grub_err_t EXPORT_FUNC(grub_video_get_info) (struct grub_video_mode_info *mode_info); +enum grub_video_blit_format EXPORT_FUNC(grub_video_get_blit_format) (struct grub_video_mode_info *mode_info); + grub_err_t EXPORT_FUNC(grub_video_set_palette) (unsigned int start, unsigned int count, struct grub_video_palette_data *palette_data); diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c index c7e701669..f92c130d7 100644 --- a/video/i386/pc/vbe.c +++ b/video/i386/pc/vbe.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -73,20 +75,10 @@ static grub_uint32_t initial_mode; static grub_uint32_t mode_in_use = 0x55aa; static grub_uint16_t *mode_list; -static grub_video_color_t -grub_video_vbe_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue); - static 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); -static void -grub_video_vbe_unmap_color (struct grub_video_render_target * source, - grub_video_color_t color, - grub_uint8_t *red, grub_uint8_t *green, - grub_uint8_t *blue, grub_uint8_t *alpha); - - static void * real2pm (grub_vbe_farptr_t ptr) { @@ -314,7 +306,7 @@ grub_vbe_get_video_mode_info (grub_uint32_t mode, return GRUB_ERR_NONE; } -static grub_uint8_t * +grub_uint8_t * grub_video_vbe_get_video_ptr (struct grub_video_render_target *source, grub_uint32_t x, grub_uint32_t y) { @@ -648,6 +640,8 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, render_target->mode_info.blue_field_pos = active_mode_info.blue_field_position; render_target->mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size; render_target->mode_info.reserved_field_pos = active_mode_info.rsvd_field_position; + + render_target->mode_info.blit_format = grub_video_get_blit_format (&render_target->mode_info); /* Reset viewport to match new mode. */ render_target->viewport.x = 0; @@ -793,7 +787,7 @@ grub_video_vbe_map_color (grub_uint32_t color_name) return 0; } -static grub_video_color_t +grub_video_color_t grub_video_vbe_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue) { @@ -877,7 +871,7 @@ grub_video_vbe_map_rgba (grub_uint8_t red, grub_uint8_t green, } } -static void +void grub_video_vbe_unmap_color (struct grub_video_render_target * source, grub_video_color_t color, grub_uint8_t *red, grub_uint8_t *green, @@ -976,7 +970,29 @@ grub_video_vbe_fill_rect (grub_video_color_t color, int x, int y, x += render_target->viewport.x; y += render_target->viewport.y; - /* Fill area. */ + /* Try to figure out more optimized version. */ + if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8) + { + grub_video_i386_vbefill_R8G8B8A8 (render_target, color, x, y, + width, height); + return GRUB_ERR_NONE; + } + + if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8) + { + grub_video_i386_vbefill_R8G8B8 (render_target, color, x, y, + width, height); + return GRUB_ERR_NONE; + } + + if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + grub_video_i386_vbefill_index (render_target, color, x, y, + width, height); + return GRUB_ERR_NONE; + } + + /* Use backup method to fill area. */ for (j = 0; j < height; j++) for (i = 0; i < width; i++) grub_video_vbe_draw_pixel (x+i, y+j, color); @@ -1180,7 +1196,73 @@ grub_video_vbe_blit_render_target (struct grub_video_render_target *source, x += render_target->viewport.x; y += render_target->viewport.y; - /* Render. */ + /* Try to figure out more optimized version. */ + if (source->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8) + { + if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8) + { + grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (render_target, source, + x, y, width, height, + offset_x, offset_y); + return GRUB_ERR_NONE; + } + + if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8) + { + grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (render_target, source, + x, y, width, height, + offset_x, offset_y); + return GRUB_ERR_NONE; + } + + if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + grub_video_i386_vbeblit_index_R8G8B8A8 (render_target, source, + x, y, width, height, + offset_x, offset_y); + return GRUB_ERR_NONE; + } + } + + if (source->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8) + { + if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8) + { + grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (render_target, source, + x, y, width, height, + offset_x, offset_y); + return GRUB_ERR_NONE; + } + + if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8) + { + grub_video_i386_vbeblit_R8G8B8_R8G8B8 (render_target, source, + x, y, width, height, + offset_x, offset_y); + return GRUB_ERR_NONE; + } + + if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + grub_video_i386_vbeblit_index_R8G8B8 (render_target, source, + x, y, width, height, + offset_x, offset_y); + return GRUB_ERR_NONE; + } + } + + if (source->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + grub_video_i386_vbeblit_index_index (render_target, source, + x, y, width, height, + offset_x, offset_y); + return GRUB_ERR_NONE; + } + } + + /* Use backup method to render. */ for (j = 0; j < height; j++) { for (i = 0; i < width; i++) @@ -1380,6 +1462,8 @@ grub_video_vbe_create_render_target (struct grub_video_render_target **result, 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/video/i386/pc/vbeblit.c b/video/i386/pc/vbeblit.c new file mode 100644 index 000000000..e14233af2 --- /dev/null +++ b/video/i386/pc/vbeblit.c @@ -0,0 +1,369 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void +grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (struct grub_video_render_target *dst, + struct grub_video_render_target *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; + + /* 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 *)grub_video_vbe_get_video_ptr (src, offset_x, + j + offset_y); + + dstptr = (grub_uint32_t *)grub_video_vbe_get_video_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; + } + } +} + +void +grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (struct grub_video_render_target *dst, + struct grub_video_render_target *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; + + /* 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 *)grub_video_vbe_get_video_ptr (src, offset_x, + j + offset_y); + + dstptr = (grub_uint8_t *)grub_video_vbe_get_video_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; + } + } +} + +void +grub_video_i386_vbeblit_index_R8G8B8A8 (struct grub_video_render_target *dst, + struct grub_video_render_target *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 *)grub_video_vbe_get_video_ptr (src, offset_x, + j + offset_y); + + dstptr = (grub_uint8_t *)grub_video_vbe_get_video_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 (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_R8G8B8A8_R8G8B8 (struct grub_video_render_target *dst, + struct grub_video_render_target *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 *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_uint8_t *)grub_video_vbe_get_video_ptr (src, offset_x, + j + offset_y); + + dstptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + { + sr = *srcptr++; + sg = *srcptr++; + sb = *srcptr++; + + color = 0xFF000000 | (sb << 16) | (sg << 8) | sr; + + *dstptr++ = color; + } + } +} + + +void +grub_video_i386_vbeblit_R8G8B8_R8G8B8 (struct grub_video_render_target *dst, + struct grub_video_render_target *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; + + /* 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 *)grub_video_vbe_get_video_ptr (src, + offset_x, + j + offset_y); + + dstptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (dst, + x, + y + j); + + for (i = 0; i < width; i++) + { + *dstptr ++ = *srcptr++; + *dstptr ++ = *srcptr++; + *dstptr ++ = *srcptr++; + } + } +} + +void +grub_video_i386_vbeblit_index_R8G8B8 (struct grub_video_render_target *dst, + struct grub_video_render_target *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_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_uint8_t *)grub_video_vbe_get_video_ptr (src, offset_x, + j + offset_y); + + dstptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + { + sr = *srcptr++; + sg = *srcptr++; + sb = *srcptr++; + + color = grub_video_vbe_map_rgb(sr, sg, sb); + + *dstptr++ = color & 0xFF; + } + } +} + + +void +grub_video_i386_vbeblit_index_index (struct grub_video_render_target *dst, + struct grub_video_render_target *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; + + /* 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 *)grub_video_vbe_get_video_ptr (src, offset_x, + j + offset_y); + + dstptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + *dstptr++ = *srcptr++; + } +} diff --git a/video/i386/pc/vbefill.c b/video/i386/pc/vbefill.c new file mode 100644 index 000000000..9c8cf19eb --- /dev/null +++ b/video/i386/pc/vbefill.c @@ -0,0 +1,101 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void +grub_video_i386_vbefill_R8G8B8A8 (struct grub_video_render_target *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_render_target *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_render_target *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; + } +} diff --git a/video/video.c b/video/video.c index affe72868..3401a5508 100644 --- a/video/video.c +++ b/video/video.c @@ -132,6 +132,53 @@ grub_video_get_info (struct grub_video_mode_info *mode_info) return grub_video_adapter_active->get_info (mode_info); } +enum grub_video_blit_format +grub_video_get_blit_format (struct grub_video_mode_info *mode_info) +{ + /* Check if we have any knwon 32 bit modes. */ + 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; + } + } + + /* Check if we have any known 24 bit modes. */ + 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; + } + } + + /* 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; + } + + /* Assume as indexcolor mode. */ + return GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR; +} + grub_err_t grub_video_set_palette (unsigned int start, unsigned int count, struct grub_video_palette_data *palette_data)