diff --git a/ChangeLog b/ChangeLog index 31b959586..6a4089c8b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,88 @@ +2006-07-29 Vesa Jaaskelainen + + * include/grub/bitmap.h: New file. + + * include/grub/i386/pc/vbeutil.h: Likewise. + + * video/bitmap.c: Likewise. + + * video/readers/tga.c: Likewise. + + * video/i386/pc/vbeutil.c: Likewise. + + * commands/videotest.c: Code cleanup and updated to reflect to new + video API. + + * term/gfxterm.c: Likewise. + + * video/video.c: Likewise. + + * conf/i386-pc.rmk (pkgdata_MODULES): Added tga.mod and bitmap.mod. + (vbe_mod_SOURCES): Added video/i386/pc/vbeutil.c. + (bitmap_mod_SOURCES): New entry. + (bitmap_mod_CFLAGS): Likewise. + (bitmap_mod_LDFLAGS): Likewise. + (tga_mod_SOURCES): Likewise. + (tga_mod_CFLAGS): Likewise. + (tga_mod_LDFLAGS): Likewise. + + * include/grub/video.h (grub_video_blit_operators): New enum type. + (grub_video_render_target): Changed as forward declaration and moved + actual definition to be video driver specific. + (grub_video_adapter.blit_bitmap): Added blitting operator. + (grub_video_adapter.blit_render_target): Likewise. + (grub_video_blit_bitmap): Likewise. + (grub_video_blit_render_target): Likewise. + + * include/grub/i386/pc/vbe.h (grub_video_render_target): Added + driver specific render target definition. + (grub_video_vbe_map_rgba): Added driver internal helper. + (grub_video_vbe_unmap_color): Updated to use + grub_video_i386_vbeblit_info. + (grub_video_vbe_get_video_ptr): Likewise. + + * include/grub/i386/pc/vbeblit.h + (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8): Updated to use + grub_video_i386_vbeblit_info. + (grub_video_i386_vbeblit_R8G8B8_R8G8B8A8): Likewise. + (grub_video_i386_vbeblit_index_R8G8B8A8): 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_R8G8B8X8_R8G8B8X8): New blitter function. + (grub_video_i386_vbeblit_R8G8B8_R8G8B8X8): Likewise. + (grub_video_i386_vbeblit_index_R8G8B8X8): Likewise. + (grub_video_i386_vbeblit_blend): Added generic blitter for blend + operator. + (grub_video_i386_vbeblit_replace): Added generic blitter for replace + operator. + + * video/i386/pc/vbeblit.c: Updated to reflect changes on + include/grub/i386/pc/vbeblit.h. + + * include/grub/i386/pc/vbefill.h (grub_video_i386_vbefill_R8G8B8A8): + Updated to use grub_video_i386_vbeblit_info. + (grub_video_i386_vbefill_R8G8B8): Likewise. + (grub_video_i386_vbefill_index): Likewise. + (grub_video_i386_vbefill): Added generic filler. + + * video/i386/pc/vbefill.c: Updated to reflect changes on + include/grub/i386/pc/vbefill.h. + + * video/i386/pc/vbe.c (grub_video_vbe_get_video_ptr): Updated to use + grub_video_i386_vbeblit_info. + (grub_video_vbe_unmap_color): Likewise. + (grub_video_vbe_blit_glyph): Likewise. + (grub_video_vbe_scroll): Likewise. + (grub_video_vbe_draw_pixel): Removed function. + (grub_video_vbe_get_pixel): Likewise. + (grub_video_vbe_fill_rect): Moved all blitters to vbefill.c and + updated code to use it. + (common_blitter): Added common blitter for render target and bitmap. + (grub_video_vbe_blit_bitmap): Updated to use common_blitter. + (grub_video_vbe_blit_render_target): Likewise. + 2006-07-30 Johan Rydberg * kern/efi/efi.c (grub_efi_set_text_mode): Assume console already diff --git a/commands/videotest.c b/commands/videotest.c index 2141f9d44..9978e1567 100644 --- a/commands/videotest.c +++ b/commands/videotest.c @@ -36,7 +36,7 @@ grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)), if (grub_video_setup (1024, 768, GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != GRUB_ERR_NONE) return grub_errno; - + grub_getkey (); grub_video_color_t color; @@ -48,21 +48,21 @@ grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)), struct grub_font_glyph glyph; struct grub_video_render_target *text_layer; grub_video_color_t palette[16]; - + grub_video_get_viewport (&x, &y, &width, &height); grub_video_create_render_target (&text_layer, width, height, GRUB_VIDEO_MODE_TYPE_RGB | GRUB_VIDEO_MODE_TYPE_ALPHA); - grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); color = grub_video_map_rgb (0, 0, 0); grub_video_fill_rect (color, 0, 0, width, height); - + color = grub_video_map_rgb (255, 0, 0); grub_video_fill_rect (color, 0, 0, 100, 100); - + color = grub_video_map_rgb (0, 255, 255); grub_video_fill_rect (color, 100, 100, 100, 100); @@ -73,18 +73,18 @@ grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)), width - 150 * 2, height - 150 * 2); color = grub_video_map_rgb (77, 33, 77); grub_video_fill_rect (color, 0, 0, width, height); - + grub_video_set_active_render_target (text_layer); - + color = grub_video_map_rgb (255, 255, 255); - - grub_font_get_glyph ('A', &glyph); + + grub_font_get_glyph ('A', &glyph); grub_video_blit_glyph (&glyph, color, 16, 16); - grub_font_get_glyph ('B', &glyph); + grub_font_get_glyph ('B', &glyph); grub_video_blit_glyph (&glyph, color, 16 * 2, 16); - grub_font_get_glyph ('*', &glyph); - + grub_font_get_glyph ('*', &glyph); + for (i = 0; i < 16; i++) { color = grub_video_map_color (i); @@ -98,18 +98,19 @@ grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)), { color = grub_video_map_rgb (i, 33, 77); grub_video_fill_rect (color, 0, 0, width, height); - grub_video_blit_render_target (text_layer, 0, 0, 0, 0, width, height); + grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, 0, 0, + 0, 0, width, height); } - + grub_getkey (); - + grub_video_delete_render_target (text_layer); - + grub_video_restore (); - + for (i = 0; i < 16; i++) grub_printf("color %d: %08x\n", i, palette[i]); - + grub_errno = GRUB_ERR_NONE; return grub_errno; } diff --git a/conf/i386-pc.mk b/conf/i386-pc.mk index 7ed204572..13115e122 100644 --- a/conf/i386-pc.mk +++ b/conf/i386-pc.mk @@ -1336,7 +1336,7 @@ grub-install: util/i386/pc/grub-install.in config.status pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod \ _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod \ vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \ - videotest.mod play.mod + videotest.mod play.mod bitmap.mod tga.mod # For _chain.mod. _chain_mod_SOURCES = loader/i386/pc/chainloader.c @@ -2101,13 +2101,13 @@ multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) # For vbe.mod. 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 und-vbe.lst + video/i386/pc/vbefill.c video/i386/pc/vbeutil.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 vbe_mod-video_i386_pc_vbeutil.o und-vbe.lst ifneq ($(vbe_mod_EXPORTS),no) CLEANFILES += def-vbe.lst DEFSYMFILES += def-vbe.lst endif -MOSTLYCLEANFILES += vbe_mod-video_i386_pc_vbe.d vbe_mod-video_i386_pc_vbeblit.d vbe_mod-video_i386_pc_vbefill.d +MOSTLYCLEANFILES += vbe_mod-video_i386_pc_vbe.d vbe_mod-video_i386_pc_vbeblit.d vbe_mod-video_i386_pc_vbefill.d vbe_mod-video_i386_pc_vbeutil.d UNDSYMFILES += und-vbe.lst vbe.mod: pre-vbe.o mod-vbe.o @@ -2115,7 +2115,7 @@ vbe.mod: pre-vbe.o mod-vbe.o $(TARGET_CC) $(vbe_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-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 vbe_mod-video_i386_pc_vbeblit.o vbe_mod-video_i386_pc_vbefill.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 vbe_mod-video_i386_pc_vbeutil.o -rm -f $@ $(TARGET_CC) $(vbe_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ @@ -2191,6 +2191,25 @@ fs-vbe_mod-video_i386_pc_vbefill.lst: video/i386/pc/vbefill.c genfslist.sh set -e; $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh vbe > $@ || (rm -f $@; exit 1) +vbe_mod-video_i386_pc_vbeutil.o: video/i386/pc/vbeutil.c + $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -c -o $@ $< + +vbe_mod-video_i386_pc_vbeutil.d: video/i386/pc/vbeutil.c + set -e; $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -M $< | sed 's,vbeutil\.o[ :]*,vbe_mod-video_i386_pc_vbeutil.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include vbe_mod-video_i386_pc_vbeutil.d + +CLEANFILES += cmd-vbe_mod-video_i386_pc_vbeutil.lst fs-vbe_mod-video_i386_pc_vbeutil.lst +COMMANDFILES += cmd-vbe_mod-video_i386_pc_vbeutil.lst +FSFILES += fs-vbe_mod-video_i386_pc_vbeutil.lst + +cmd-vbe_mod-video_i386_pc_vbeutil.lst: video/i386/pc/vbeutil.c gencmdlist.sh + set -e; $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh vbe > $@ || (rm -f $@; exit 1) + +fs-vbe_mod-video_i386_pc_vbeutil.lst: video/i386/pc/vbeutil.c genfslist.sh + set -e; $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh vbe > $@ || (rm -f $@; exit 1) + + vbe_mod_CFLAGS = $(COMMON_CFLAGS) vbe_mod_LDFLAGS = $(COMMON_LDFLAGS) @@ -2530,4 +2549,116 @@ fs-videotest_mod-commands_videotest.lst: commands/videotest.c genfslist.sh videotest_mod_CFLAGS = $(COMMON_CFLAGS) videotest_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For bitmap.mod +bitmap_mod_SOURCES = video/bitmap.c +CLEANFILES += bitmap.mod mod-bitmap.o mod-bitmap.c pre-bitmap.o bitmap_mod-video_bitmap.o und-bitmap.lst +ifneq ($(bitmap_mod_EXPORTS),no) +CLEANFILES += def-bitmap.lst +DEFSYMFILES += def-bitmap.lst +endif +MOSTLYCLEANFILES += bitmap_mod-video_bitmap.d +UNDSYMFILES += und-bitmap.lst + +bitmap.mod: pre-bitmap.o mod-bitmap.o + -rm -f $@ + $(TARGET_CC) $(bitmap_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ + +pre-bitmap.o: bitmap_mod-video_bitmap.o + -rm -f $@ + $(TARGET_CC) $(bitmap_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ + +mod-bitmap.o: mod-bitmap.c + $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bitmap_mod_CFLAGS) -c -o $@ $< + +mod-bitmap.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'bitmap' $< > $@ || (rm -f $@; exit 1) + +ifneq ($(bitmap_mod_EXPORTS),no) +def-bitmap.lst: pre-bitmap.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 bitmap/' > $@ +endif + +und-bitmap.lst: pre-bitmap.o + echo 'bitmap' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +bitmap_mod-video_bitmap.o: video/bitmap.c + $(TARGET_CC) -Ivideo -I$(srcdir)/video $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bitmap_mod_CFLAGS) -c -o $@ $< + +bitmap_mod-video_bitmap.d: video/bitmap.c + set -e; $(TARGET_CC) -Ivideo -I$(srcdir)/video $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bitmap_mod_CFLAGS) -M $< | sed 's,bitmap\.o[ :]*,bitmap_mod-video_bitmap.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include bitmap_mod-video_bitmap.d + +CLEANFILES += cmd-bitmap_mod-video_bitmap.lst fs-bitmap_mod-video_bitmap.lst +COMMANDFILES += cmd-bitmap_mod-video_bitmap.lst +FSFILES += fs-bitmap_mod-video_bitmap.lst + +cmd-bitmap_mod-video_bitmap.lst: video/bitmap.c gencmdlist.sh + set -e; $(TARGET_CC) -Ivideo -I$(srcdir)/video $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bitmap_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh bitmap > $@ || (rm -f $@; exit 1) + +fs-bitmap_mod-video_bitmap.lst: video/bitmap.c genfslist.sh + set -e; $(TARGET_CC) -Ivideo -I$(srcdir)/video $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bitmap_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh bitmap > $@ || (rm -f $@; exit 1) + + +bitmap_mod_CFLAGS = $(COMMON_CFLAGS) +bitmap_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For tga.mod +tga_mod_SOURCES = video/readers/tga.c +CLEANFILES += tga.mod mod-tga.o mod-tga.c pre-tga.o tga_mod-video_readers_tga.o und-tga.lst +ifneq ($(tga_mod_EXPORTS),no) +CLEANFILES += def-tga.lst +DEFSYMFILES += def-tga.lst +endif +MOSTLYCLEANFILES += tga_mod-video_readers_tga.d +UNDSYMFILES += und-tga.lst + +tga.mod: pre-tga.o mod-tga.o + -rm -f $@ + $(TARGET_CC) $(tga_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ + +pre-tga.o: tga_mod-video_readers_tga.o + -rm -f $@ + $(TARGET_CC) $(tga_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ + +mod-tga.o: mod-tga.c + $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tga_mod_CFLAGS) -c -o $@ $< + +mod-tga.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'tga' $< > $@ || (rm -f $@; exit 1) + +ifneq ($(tga_mod_EXPORTS),no) +def-tga.lst: pre-tga.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 tga/' > $@ +endif + +und-tga.lst: pre-tga.o + echo 'tga' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +tga_mod-video_readers_tga.o: video/readers/tga.c + $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tga_mod_CFLAGS) -c -o $@ $< + +tga_mod-video_readers_tga.d: video/readers/tga.c + set -e; $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tga_mod_CFLAGS) -M $< | sed 's,tga\.o[ :]*,tga_mod-video_readers_tga.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include tga_mod-video_readers_tga.d + +CLEANFILES += cmd-tga_mod-video_readers_tga.lst fs-tga_mod-video_readers_tga.lst +COMMANDFILES += cmd-tga_mod-video_readers_tga.lst +FSFILES += fs-tga_mod-video_readers_tga.lst + +cmd-tga_mod-video_readers_tga.lst: video/readers/tga.c gencmdlist.sh + set -e; $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tga_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh tga > $@ || (rm -f $@; exit 1) + +fs-tga_mod-video_readers_tga.lst: video/readers/tga.c genfslist.sh + set -e; $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tga_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh tga > $@ || (rm -f $@; exit 1) + + +tga_mod_CFLAGS = $(COMMON_CFLAGS) +tga_mod_LDFLAGS = $(COMMON_LDFLAGS) + include $(srcdir)/conf/common.mk diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index b2a045fb8..dd5117fb6 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -112,7 +112,7 @@ grub_install_SOURCES = util/i386/pc/grub-install.in pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod \ _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod \ vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \ - videotest.mod play.mod + videotest.mod play.mod bitmap.mod tga.mod # For _chain.mod. _chain_mod_SOURCES = loader/i386/pc/chainloader.c @@ -171,7 +171,7 @@ multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) # For vbe.mod. vbe_mod_SOURCES = video/i386/pc/vbe.c video/i386/pc/vbeblit.c \ - video/i386/pc/vbefill.c + video/i386/pc/vbefill.c video/i386/pc/vbeutil.c vbe_mod_CFLAGS = $(COMMON_CFLAGS) vbe_mod_LDFLAGS = $(COMMON_LDFLAGS) @@ -205,4 +205,14 @@ videotest_mod_SOURCES = commands/videotest.c videotest_mod_CFLAGS = $(COMMON_CFLAGS) videotest_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For bitmap.mod +bitmap_mod_SOURCES = video/bitmap.c +bitmap_mod_CFLAGS = $(COMMON_CFLAGS) +bitmap_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For tga.mod +tga_mod_SOURCES = video/readers/tga.c +tga_mod_CFLAGS = $(COMMON_CFLAGS) +tga_mod_LDFLAGS = $(COMMON_LDFLAGS) + include $(srcdir)/conf/common.mk diff --git a/include/grub/bitmap.h b/include/grub/bitmap.h new file mode 100644 index 000000000..9efa30507 --- /dev/null +++ b/include/grub/bitmap.h @@ -0,0 +1,71 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 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 + * 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 GRUB; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef GRUB_BITMAP_HEADER +#define GRUB_BITMAP_HEADER 1 + +#include +#include +#include +#include + +struct grub_video_bitmap +{ + /* Bitmap format description. */ + struct grub_video_mode_info mode_info; + + /* Pointer to bitmap data formatted according to mode_info. */ + void *data; +}; + +struct grub_video_bitmap_reader +{ + /* File extension for this bitmap type (including dot). */ + const char *extension; + + /* Reader function to load bitmap. */ + grub_err_t (*reader) (struct grub_video_bitmap **bitmap, + const char *filename); + + /* Next reader. */ + struct grub_video_bitmap_reader *next; +}; +typedef struct grub_video_bitmap_reader *grub_video_bitmap_reader_t; + +void grub_video_bitmap_reader_register (grub_video_bitmap_reader_t reader); +void grub_video_bitmap_reader_unregister (grub_video_bitmap_reader_t reader); + +grub_err_t grub_video_bitmap_create (struct grub_video_bitmap **bitmap, + unsigned int width, unsigned int height, + enum grub_video_blit_format blit_format); + +grub_err_t grub_video_bitmap_destroy (struct grub_video_bitmap *bitmap); + +grub_err_t grub_video_bitmap_load (struct grub_video_bitmap **bitmap, + const char *filename); + +unsigned int grub_video_bitmap_get_width (struct grub_video_bitmap *bitmap); +unsigned int grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap); + +void grub_video_bitmap_get_mode_info (struct grub_video_bitmap *bitmap, + struct grub_video_mode_info *mode_info); + +void *grub_video_bitmap_get_data (struct grub_video_bitmap *bitmap); + +#endif /* ! GRUB_BITMAP_HEADER */ diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index 5cb15bd19..3797ee5d1 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -205,13 +205,43 @@ 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, +struct grub_video_i386_vbeblit_info; + +struct grub_video_render_target +{ + /* Copy of the screen's mode info structure, except that width, height and + mode_type has been re-adjusted to requested render target settings. */ + struct grub_video_mode_info mode_info; + + struct + { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + } viewport; + + /* Indicates wether the data has been allocated by us and must be freed + when render target is destroyed. */ + int is_allocated; + + /* Pointer to data. Can either be in video card memory or in local host's + memory. */ + void *data; +}; + +grub_uint8_t * grub_video_vbe_get_video_ptr (struct grub_video_i386_vbeblit_info *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 grub_video_vbe_map_rgba (grub_uint8_t red, + grub_uint8_t green, + grub_uint8_t blue, + grub_uint8_t alpha); + +void grub_video_vbe_unmap_color (struct grub_video_i386_vbeblit_info *source, grub_video_color_t color, grub_uint8_t *red, grub_uint8_t *green, grub_uint8_t *blue, grub_uint8_t *alpha); diff --git a/include/grub/i386/pc/vbeblit.h b/include/grub/i386/pc/vbeblit.h index 890b57700..d90c5eea4 100644 --- a/include/grub/i386/pc/vbeblit.h +++ b/include/grub/i386/pc/vbeblit.h @@ -20,47 +20,81 @@ #ifndef GRUB_VBEBLIT_MACHINE_HEADER #define GRUB_VBEBLIT_MACHINE_HEADER 1 +/* NOTE: This header is private header for vbe driver and should not be used + in other parts of the code. */ + +struct grub_video_i386_vbeblit_info; + void -grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (struct grub_video_i386_vbeblit_info *dst, + struct grub_video_i386_vbeblit_info *src, int x, int y, int width, int height, int offset_x, int offset_y); void -grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8 (struct grub_video_i386_vbeblit_info *dst, + struct grub_video_i386_vbeblit_info *src, + int x, int y, int width, int height, + int offset_x, int offset_y); + +void +grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (struct grub_video_i386_vbeblit_info *dst, + struct grub_video_i386_vbeblit_info *src, int x, int y, int width, int height, int offset_x, int offset_y); void -grub_video_i386_vbeblit_index_R8G8B8A8 (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +grub_video_i386_vbeblit_R8G8B8_R8G8B8X8 (struct grub_video_i386_vbeblit_info *dst, + struct grub_video_i386_vbeblit_info *src, + int x, int y, int width, int height, + int offset_x, int offset_y); + +void +grub_video_i386_vbeblit_index_R8G8B8A8 (struct grub_video_i386_vbeblit_info *dst, + struct grub_video_i386_vbeblit_info *src, int x, int y, int width, int height, int offset_x, int offset_y); +void +grub_video_i386_vbeblit_index_R8G8B8X8 (struct grub_video_i386_vbeblit_info *dst, + struct grub_video_i386_vbeblit_info *src, + int x, int y, int width, int height, + int offset_x, int offset_y); void -grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_i386_vbeblit_info *dst, + struct grub_video_i386_vbeblit_info *src, int x, int y, int width, int height, int offset_x, int offset_y); void -grub_video_i386_vbeblit_R8G8B8_R8G8B8 (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +grub_video_i386_vbeblit_R8G8B8_R8G8B8 (struct grub_video_i386_vbeblit_info *dst, + struct grub_video_i386_vbeblit_info *src, int x, int y, int width, int height, int offset_x, int offset_y); void -grub_video_i386_vbeblit_index_R8G8B8 (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +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); void -grub_video_i386_vbeblit_index_index (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +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); +void +grub_video_i386_vbeblit_blend (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_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); + #endif /* ! GRUB_VBEBLIT_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/vbefill.h b/include/grub/i386/pc/vbefill.h index 14f7b5323..604473adf 100644 --- a/include/grub/i386/pc/vbefill.h +++ b/include/grub/i386/pc/vbefill.h @@ -20,21 +20,29 @@ #ifndef GRUB_VBEFILL_MACHINE_HEADER #define GRUB_VBEFILL_MACHINE_HEADER 1 -#include +/* NOTE: This header is private header for vbe driver and should not be used + in other parts of the code. */ + +struct grub_video_i386_vbeblit_info; void -grub_video_i386_vbefill_R8G8B8A8 (struct grub_video_render_target *dst, +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_render_target *dst, +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_render_target *dst, +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); + #endif /* ! GRUB_VBEFILL_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/vbeutil.h b/include/grub/i386/pc/vbeutil.h new file mode 100644 index 000000000..9073f2425 --- /dev/null +++ b/include/grub/i386/pc/vbeutil.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +/* NOTE: This header is private header for vbe driver and should not be used + in other parts of the code. */ + +#ifndef GRUB_VBEUTIL_MACHINE_HEADER +#define GRUB_VBEUTIL_MACHINE_HEADER 1 + +#include +#include + +struct grub_video_i386_vbeblit_info +{ + struct grub_video_mode_info *mode_info; + void *data; +}; + +grub_uint8_t *get_data_ptr (struct grub_video_i386_vbeblit_info *source, + unsigned int x, unsigned int y); + +grub_video_color_t get_pixel (struct grub_video_i386_vbeblit_info *source, + unsigned int x, unsigned int y); + +void set_pixel (struct grub_video_i386_vbeblit_info *source, + unsigned int x, unsigned int y, grub_video_color_t color); + +#endif /* ! GRUB_VBEUTIL_MACHINE_HEADER */ diff --git a/include/grub/video.h b/include/grub/video.h index 5c99e0d39..427cb7c42 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -23,10 +23,18 @@ #include #include +/* Video color in hardware dependant format. Users should not assume any + specific coding format. */ typedef grub_uint32_t grub_video_color_t; +/* This structure is driver specific and should not be accessed directly by + outside code. */ struct grub_video_render_target; +/* Forward declarations for used data structures. */ +struct grub_font_glyph; +struct grub_video_bitmap; + /* Defines used to describe video mode or rendering target. */ #define GRUB_VIDEO_MODE_TYPE_ALPHA 0x00000008 #define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED 0x00000004 @@ -60,6 +68,15 @@ enum grub_video_blit_format GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR }; +/* Define blitting operators. */ +enum grub_video_blit_operators + { + /* Replace target bitmap data with source. */ + GRUB_VIDEO_BLIT_REPLACE, + /* Blend target and source based on source's alpha value. */ + GRUB_VIDEO_BLIT_BLEND + }; + struct grub_video_mode_info { /* Width of the screen. */ @@ -113,29 +130,6 @@ struct grub_video_mode_info unsigned int reserved_field_pos; }; -struct grub_video_render_target -{ - /* Copy of the screen's mode info structure, except that width, height and - mode_type has been re-adjusted to requested render target settings. */ - struct grub_video_mode_info mode_info; - - struct - { - unsigned int x; - unsigned int y; - unsigned int width; - unsigned int height; - } viewport; - - /* Indicates wether the data has been allocated by us and must be freed - when render target is destroyed. */ - int is_allocated; - - /* Pointer to data. Can either be in video card memory or in local host's - memory. */ - void *data; -}; - struct grub_video_palette_data { grub_uint8_t r; /* Red color value (0-255). */ @@ -144,9 +138,6 @@ struct grub_video_palette_data grub_uint8_t a; /* Reserved bits value (0-255). */ }; -struct grub_font_glyph; -struct grub_video_bitmap; - struct grub_video_adapter { /* The video adapter name. */ @@ -190,10 +181,12 @@ struct grub_video_adapter grub_video_color_t color, int x, int y); grub_err_t (*blit_bitmap) (struct grub_video_bitmap *bitmap, + enum grub_video_blit_operators oper, int x, int y, int offset_x, int offset_y, unsigned int width, unsigned int height); grub_err_t (*blit_render_target) (struct grub_video_render_target *source, + enum grub_video_blit_operators oper, int x, int y, int offset_x, int offset_y, unsigned int width, unsigned int height); @@ -254,10 +247,12 @@ grub_err_t grub_video_blit_glyph (struct grub_font_glyph *glyph, grub_video_color_t color, int x, int y); grub_err_t grub_video_blit_bitmap (struct grub_video_bitmap *bitmap, + enum grub_video_blit_operators oper, int x, int y, int offset_x, int offset_y, unsigned int width, unsigned int height); grub_err_t grub_video_blit_render_target (struct grub_video_render_target *source, + enum grub_video_blit_operators oper, int x, int y, int offset_x, int offset_y, unsigned int width, diff --git a/term/gfxterm.c b/term/gfxterm.c index c30a90869..cfdae3bb8 100644 --- a/term/gfxterm.c +++ b/term/gfxterm.c @@ -89,7 +89,7 @@ struct grub_virtual_screen unsigned int cursor_x; unsigned int cursor_y; int cursor_state; - + /* Color settings. */ grub_video_color_t fg_color_setting; grub_video_color_t bg_color_setting; @@ -127,7 +127,7 @@ grub_virtual_screen_free (void) /* Reset virtual screen data. */ grub_memset (&virtual_screen, 0, sizeof (virtual_screen)); - + /* Free render targets. */ grub_video_delete_render_target (text_layer); text_layer = 0; @@ -158,8 +158,8 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y, /* Allocate memory for text buffer. */ virtual_screen.text_buffer = (struct grub_colored_char *) grub_malloc (virtual_screen.columns - * virtual_screen.rows - * sizeof (*virtual_screen.text_buffer)); + * virtual_screen.rows + * sizeof (*virtual_screen.text_buffer)); if (grub_errno != GRUB_ERR_NONE) return grub_errno; @@ -171,19 +171,19 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y, | GRUB_VIDEO_MODE_TYPE_ALPHA); if (grub_errno != GRUB_ERR_NONE) return grub_errno; - + /* As we want to have colors compatible with rendering target, - we can only have those after mode is initialized. */ + we can only have those after mode is initialized. */ grub_video_set_active_render_target (text_layer); - + virtual_screen.fg_color_setting = grub_video_map_color (DEFAULT_FG_COLOR); virtual_screen.bg_color_setting = grub_video_map_color (DEFAULT_BG_COLOR); virtual_screen.fg_color = virtual_screen.fg_color_setting; virtual_screen.bg_color = virtual_screen.bg_color_setting; virtual_screen.cursor_color = grub_video_map_color (DEFAULT_CURSOR_COLOR); - + grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); - + return grub_errno; } @@ -196,7 +196,7 @@ grub_gfxterm_init (void) int depth = -1; int flags = DEFAULT_VIDEO_FLAGS; grub_video_color_t color; - + /* Parse gfxmode environment variable if set. */ modevar = grub_env_get ("gfxmode"); if (modevar) @@ -204,18 +204,18 @@ grub_gfxterm_init (void) char *tmp; char *param; char *value; - + /* Take copy of env.var. as we don't want to modify that. */ tmp = grub_strdup (modevar); modevar = tmp; - + if (grub_errno != GRUB_ERR_NONE) - return grub_errno; - + return grub_errno; + /* Skip whitespace. */ while (grub_isspace (*tmp)) tmp++; - + /* Initialize token holders. */ param = tmp; value = NULL; @@ -233,10 +233,10 @@ grub_gfxterm_init (void) "Invalid argument: %s\n", param); } - + *param = 0; param++; - + width = grub_strtoul (value, 0, 0); if (grub_errno != GRUB_ERR_NONE) { @@ -267,7 +267,7 @@ grub_gfxterm_init (void) /* We have optional color depth value. */ *param = 0; param++; - + height = grub_strtoul (value, 0, 0); if (grub_errno != GRUB_ERR_NONE) { @@ -277,7 +277,7 @@ grub_gfxterm_init (void) "Invalid argument: %s\n", param); } - + /* Convert color depth value. */ value = param; depth = grub_strtoul (value, 0, 0); @@ -290,7 +290,7 @@ grub_gfxterm_init (void) param); } } - + /* Free memory. */ grub_free (modevar); } @@ -323,7 +323,7 @@ grub_gfxterm_init (void) /* Leave borders for virtual screen. */ width = mode_info.width - (2 * DEFAULT_BORDER_WIDTH); height = mode_info.height - (2 * DEFAULT_BORDER_WIDTH); - + /* Create virtual screen. */ if (grub_virtual_screen_setup (DEFAULT_BORDER_WIDTH, DEFAULT_BORDER_WIDTH, width, height) != GRUB_ERR_NONE) @@ -333,7 +333,7 @@ grub_gfxterm_init (void) } /* Mark whole screen as dirty. */ - dirty_region_reset (); + dirty_region_reset (); dirty_region_add (0, 0, mode_info.width, mode_info.height); return (grub_errno = GRUB_ERR_NONE); @@ -354,15 +354,15 @@ redraw_screen_rect (unsigned int x, unsigned int y, unsigned int width, unsigned int height) { grub_video_color_t color; - + grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); /* Render background layer. */ color = virtual_screen.bg_color; grub_video_fill_rect (color, x, y, width, height); - + /* Render text layer. */ - grub_video_blit_render_target (text_layer, x, y, + grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, x, y, x - virtual_screen.offset_x, y - virtual_screen.offset_y, width, height); @@ -393,7 +393,7 @@ dirty_region_add (int x, int y, unsigned int width, unsigned int height) { if ((width == 0) || (height == 0)) return; - + if (dirty_region_is_empty ()) { dirty_region.top_left_x = x; @@ -430,18 +430,18 @@ dirty_region_redraw (void) int y; int width; int height; - + if (dirty_region_is_empty ()) return; - + x = dirty_region.top_left_x; y = dirty_region.top_left_y; - + width = dirty_region.bottom_right_x - x + 1; height = dirty_region.bottom_right_y - y + 1; - + redraw_screen_rect (x, y, width, height); - + dirty_region_reset (); } @@ -451,7 +451,7 @@ write_char (void) struct grub_colored_char *p; struct grub_font_glyph glyph; grub_video_color_t color; - grub_video_color_t bgcolor; + grub_video_color_t bgcolor; unsigned int x; unsigned int y; @@ -474,7 +474,7 @@ write_char (void) /* Render glyph to text layer. */ grub_video_set_active_render_target (text_layer); grub_video_fill_rect (bgcolor, x, y, glyph.width, glyph.height); - grub_video_blit_glyph (&glyph, color, x, y); + grub_video_blit_glyph (&glyph, color, x, y); grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); /* Mark character to be drawn. */ @@ -517,7 +517,7 @@ scroll_up (void) /* Scroll text buffer with one line to up. */ grub_memmove (virtual_screen.text_buffer, - virtual_screen.text_buffer + virtual_screen.columns, + virtual_screen.text_buffer + virtual_screen.columns, sizeof (*virtual_screen.text_buffer) * virtual_screen.columns * (virtual_screen.rows - 1)); @@ -533,13 +533,13 @@ scroll_up (void) virtual_screen.text_buffer[i].width = 0; virtual_screen.text_buffer[i].index = 0; } - + /* Scroll physical screen. */ grub_video_set_active_render_target (text_layer); color = virtual_screen.bg_color; grub_video_scroll (color, 0, -virtual_screen.char_height); grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); - + /* Mark virtual screen to be redrawn. */ dirty_region_add_virtualscreen (); } @@ -555,47 +555,47 @@ grub_gfxterm_putchar (grub_uint32_t c) { /* Erase current cursor, if any. */ if (virtual_screen.cursor_state) - write_char (); + write_char (); switch (c) - { - case '\b': - if (virtual_screen.cursor_x > 0) - virtual_screen.cursor_x--; - break; - - case '\n': - if (virtual_screen.cursor_y >= virtual_screen.rows - 1) - scroll_up (); - else - virtual_screen.cursor_y++; - break; - - case '\r': - virtual_screen.cursor_x = 0; - break; - } + { + case '\b': + if (virtual_screen.cursor_x > 0) + virtual_screen.cursor_x--; + break; + + case '\n': + if (virtual_screen.cursor_y >= virtual_screen.rows - 1) + scroll_up (); + else + virtual_screen.cursor_y++; + break; + + case '\r': + virtual_screen.cursor_x = 0; + break; + } /* Redraw cursor if visible. */ if (virtual_screen.cursor_state) - write_cursor (); + write_cursor (); } else { struct grub_font_glyph glyph; struct grub_colored_char *p; - + /* Get properties of the character. */ grub_font_get_glyph (c, &glyph); /* If we are about to exceed line length, wrap to next line. */ if (virtual_screen.cursor_x + glyph.char_width > virtual_screen.columns) - grub_putchar ('\n'); + grub_putchar ('\n'); /* Find position on virtual screen, and fill information. */ p = (virtual_screen.text_buffer + - virtual_screen.cursor_x + - virtual_screen.cursor_y * virtual_screen.columns); + virtual_screen.cursor_x + + virtual_screen.cursor_y * virtual_screen.columns); p->code = c; p->fg_color = virtual_screen.fg_color; p->bg_color = virtual_screen.bg_color; @@ -604,35 +604,35 @@ grub_gfxterm_putchar (grub_uint32_t c) /* If we have large glyph, add fixup info. */ if (glyph.char_width > 1) - { - unsigned i; + { + unsigned i; + + for (i = 1; i < glyph.char_width; i++) + { + p[i].code = ' '; + p[i].width = glyph.char_width - 1; + p[i].index = i; + } + } - for (i = 1; i < glyph.char_width; i++) - { - p[i].code = ' '; - p[i].width = glyph.char_width - 1; - p[i].index = i; - } - } - /* Draw glyph. */ write_char (); - + /* Make sure we scroll screen when needed and wrap line correctly. */ virtual_screen.cursor_x += glyph.char_width; if (virtual_screen.cursor_x >= virtual_screen.columns) - { - virtual_screen.cursor_x = 0; - - if (virtual_screen.cursor_y >= virtual_screen.rows - 1) - scroll_up (); - else - virtual_screen.cursor_y++; - } + { + virtual_screen.cursor_x = 0; + + if (virtual_screen.cursor_y >= virtual_screen.rows - 1) + scroll_up (); + else + virtual_screen.cursor_y++; + } /* Draw cursor if visible. */ if (virtual_screen.cursor_state) - write_cursor (); + write_cursor (); } } @@ -640,7 +640,7 @@ static grub_ssize_t grub_gfxterm_getcharwidth (grub_uint32_t c) { struct grub_font_glyph glyph; - + grub_font_get_glyph (c, &glyph); return glyph.char_width; @@ -663,7 +663,7 @@ grub_gfxterm_gotoxy (grub_uint8_t x, grub_uint8_t y) { if (x >= virtual_screen.columns) x = virtual_screen.columns - 1; - + if (y >= virtual_screen.rows) y = virtual_screen.rows - 1; @@ -701,13 +701,13 @@ grub_gfxterm_cls (void) /* Clear virtual screen. */ grub_virtual_screen_cls (); - + /* Clear text layer. */ grub_video_set_active_render_target (text_layer); color = virtual_screen.bg_color_setting; grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height); grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); - + /* Mark virtual screen to be redrawn. */ dirty_region_add_virtualscreen (); } @@ -745,9 +745,9 @@ grub_gfxterm_setcursor (int on) if (virtual_screen.cursor_state != on) { if (virtual_screen.cursor_state) - write_char (); + write_char (); else - write_cursor (); + write_cursor (); virtual_screen.cursor_state = on; } @@ -776,7 +776,7 @@ static struct grub_term grub_video_term = .setcolorstate = grub_virtual_screen_setcolorstate, .setcolor = grub_virtual_screen_setcolor, .setcursor = grub_gfxterm_setcursor, - .refresh = grub_gfxterm_refresh, + .refresh = grub_gfxterm_refresh, .flags = 0, .next = 0 }; diff --git a/video/bitmap.c b/video/bitmap.c new file mode 100644 index 000000000..ec02c8a47 --- /dev/null +++ b/video/bitmap.c @@ -0,0 +1,257 @@ +/* + * 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 + +/* List of bitmap readers registered to system. */ +static grub_video_bitmap_reader_t bitmap_readers_list; + +/* Register bitmap reader. */ +void +grub_video_bitmap_reader_register (grub_video_bitmap_reader_t reader) +{ + reader->next = bitmap_readers_list; + bitmap_readers_list = reader; +} + +/* Unregister bitmap reader. */ +void +grub_video_bitmap_reader_unregister (grub_video_bitmap_reader_t reader) +{ + grub_video_bitmap_reader_t *p, q; + + for (p = &bitmap_readers_list, q = *p; q; p = &(q->next), q = q->next) + if (q == reader) + { + *p = q->next; + break; + } +} + +/* Creates new bitmap, saves created bitmap on success to *bitmap. */ +grub_err_t +grub_video_bitmap_create (struct grub_video_bitmap **bitmap, + unsigned int width, unsigned int height, + enum grub_video_blit_format blit_format) +{ + struct grub_video_mode_info *mode_info; + unsigned int size; + + if (!bitmap) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument."); + + *bitmap = 0; + + if (width == 0 || height == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument."); + + *bitmap = (struct grub_video_bitmap *)grub_malloc (sizeof (struct grub_video_bitmap)); + if (! *bitmap) + return grub_errno; + + mode_info = &((*bitmap)->mode_info); + + /* Populate mode_info. */ + mode_info->width = width; + mode_info->height = height; + mode_info->blit_format = blit_format; + + switch (blit_format) + { + case GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8: + mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_RGB + | GRUB_VIDEO_MODE_TYPE_ALPHA; + mode_info->bpp = 32; + mode_info->bytes_per_pixel = 4; + mode_info->number_of_colors = 256; + 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; + break; + + case GRUB_VIDEO_BLIT_FORMAT_R8G8B8: + mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + mode_info->bpp = 24; + mode_info->bytes_per_pixel = 3; + mode_info->number_of_colors = 256; + 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 = 0; + mode_info->reserved_field_pos = 0; + break; + + case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR: + mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + mode_info->bpp = 8; + mode_info->bytes_per_pixel = 1; + mode_info->number_of_colors = 256; + mode_info->red_mask_size = 0; + mode_info->red_field_pos = 0; + mode_info->green_mask_size = 0; + mode_info->green_field_pos = 0; + mode_info->blue_mask_size = 0; + mode_info->blue_field_pos = 0; + mode_info->reserved_mask_size = 0; + mode_info->reserved_field_pos = 0; + break; + + default: + grub_free (*bitmap); + *bitmap = 0; + + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Unsupported bitmap format"); + } + + mode_info->pitch = width * mode_info->bytes_per_pixel; + + /* Calculate size needed for the data. */ + size = (width * mode_info->bytes_per_pixel) * height; + + (*bitmap)->data = grub_malloc (size); + if (! (*bitmap)->data) + { + grub_free (*bitmap); + *bitmap = 0; + + return grub_errno; + } + + /* Clear bitmap. */ + grub_memset ((*bitmap)->data, 0, size); + + return GRUB_ERR_NONE; +} + +/* Frees all resources allocated by bitmap. */ +grub_err_t +grub_video_bitmap_destroy (struct grub_video_bitmap *bitmap) +{ + if (! bitmap) + return GRUB_ERR_NONE; + + grub_free (bitmap->data); + grub_free (bitmap); + + return GRUB_ERR_NONE; +} + +/* Match extension to filename. */ +static int +match_extension (const char *filename, const char *ext) +{ + int pos; + int ext_len; + + pos = grub_strlen (filename); + ext_len = grub_strlen (ext); + + if (! pos || ! ext_len || ext_len > pos) + return 0; + + pos -= ext_len; + + return grub_strcmp (filename + pos, ext) == 0; +} + +/* Loads bitmap using registered bitmap readers. */ +grub_err_t +grub_video_bitmap_load (struct grub_video_bitmap **bitmap, + const char *filename) +{ + grub_video_bitmap_reader_t reader = bitmap_readers_list; + + if (!bitmap) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument."); + + *bitmap = 0; + + while (reader) + { + if (match_extension (filename, reader->extension)) + return reader->reader (bitmap, filename); + + reader = reader->next; + } + + return grub_error(GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format"); +} + +/* Return bitmap width. */ +unsigned int +grub_video_bitmap_get_width (struct grub_video_bitmap *bitmap) +{ + if (!bitmap) + return 0; + + return bitmap->mode_info.width; +} + +/* Return bitmap height. */ +unsigned int +grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap) +{ + if (!bitmap) + return 0; + + return bitmap->mode_info.height; +} + +/* Return mode info for bitmap. */ +void grub_video_bitmap_get_mode_info (struct grub_video_bitmap *bitmap, + struct grub_video_mode_info *mode_info) +{ + if (!bitmap) + return; + + *mode_info = bitmap->mode_info; +} + +/* Return pointer to bitmap's raw data. */ +void *grub_video_bitmap_get_data (struct grub_video_bitmap *bitmap) +{ + if (!bitmap) + return 0; + + return bitmap->data; +} + +/* Initialize bitmap module. */ +GRUB_MOD_INIT(video_bitmap) +{ +} + +/* Finalize bitmap module. */ +GRUB_MOD_FINI(video_bitmap) +{ +} diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c index 846f12437..094dc676d 100644 --- a/video/i386/pc/vbe.c +++ b/video/i386/pc/vbe.c @@ -22,12 +22,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include /* Specify "standard" VGA palette, some video cards may need this and this will also be used when using RGB modes. */ @@ -75,10 +77,6 @@ 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_rgba (grub_uint8_t red, grub_uint8_t green, - grub_uint8_t blue, grub_uint8_t alpha); - static void * real2pm (grub_vbe_farptr_t ptr) { @@ -176,7 +174,7 @@ grub_vbe_set_video_mode (grub_uint32_t mode, default: return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "unsupported pixel format 0x%x", - active_mode_info.memory_model); + active_mode_info.memory_model); } } @@ -220,7 +218,7 @@ grub_vbe_set_video_mode (grub_uint32_t mode, default: grub_vbe_bios_set_mode (old_mode, 0); return grub_error (GRUB_ERR_BAD_DEVICE, - "cannot set VBE mode %x", + "cannot set VBE mode %x", mode); break; } @@ -238,7 +236,7 @@ grub_vbe_set_video_mode (grub_uint32_t mode, 0, palette); - /* Just ignore the status. */ + /* Just ignore the status. */ } /* Copy mode info for caller. */ @@ -299,35 +297,35 @@ grub_vbe_get_video_mode_info (grub_uint32_t mode, } grub_uint8_t * -grub_video_vbe_get_video_ptr (struct grub_video_render_target *source, +grub_video_vbe_get_video_ptr (struct grub_video_i386_vbeblit_info *source, grub_uint32_t x, grub_uint32_t y) { grub_uint8_t *ptr = 0; - switch (source->mode_info.bpp) + switch (source->mode_info->bpp) { case 32: ptr = (grub_uint8_t *)source->data - + y * source->mode_info.pitch + + y * source->mode_info->pitch + x * 4; break; case 24: ptr = (grub_uint8_t *)source->data - + y * source->mode_info.pitch + + y * source->mode_info->pitch + x * 3; break; case 16: case 15: ptr = (grub_uint8_t *)source->data - + y * source->mode_info.pitch + + y * source->mode_info->pitch + x * 2; break; case 8: ptr = (grub_uint8_t *)source->data - + y * source->mode_info.pitch + + y * source->mode_info->pitch + x; break; } @@ -335,112 +333,6 @@ grub_video_vbe_get_video_ptr (struct grub_video_render_target *source, return ptr; } -static void -grub_video_vbe_draw_pixel (grub_uint32_t x, grub_uint32_t y, - grub_video_color_t color) -{ - if (x >= render_target->mode_info.width) - return; - - if (y >= render_target->mode_info.height) - return; - - switch (render_target->mode_info.bpp) - { - case 32: - { - grub_uint32_t *ptr; - - ptr = (grub_uint32_t *)grub_video_vbe_get_video_ptr (render_target, - x, y); - - *ptr = color; - } - break; - - case 24: - { - grub_uint8_t *ptr; - grub_uint8_t *ptr2 = (grub_uint8_t *) &color; - - ptr = grub_video_vbe_get_video_ptr (render_target, x, y); - - ptr[0] = ptr2[0]; - ptr[1] = ptr2[1]; - ptr[2] = ptr2[2]; - } - break; - - case 16: - case 15: - { - grub_uint16_t *ptr; - - ptr = (grub_uint16_t *)grub_video_vbe_get_video_ptr (render_target, - x, y); - - *ptr = (grub_uint16_t) (color & 0xFFFF); - } - break; - - case 8: - { - grub_uint8_t *ptr; - - ptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (render_target, - x, y); - - *ptr = (grub_uint8_t) (color & 0xFF); - } - break; - - default: - break; - } -} - -static grub_video_color_t -grub_video_vbe_get_pixel (struct grub_video_render_target *source, - grub_uint32_t x, grub_uint32_t y) -{ - grub_video_color_t color = 0; - - if (x >= source->mode_info.width) - return 0; - - if (y >= source->mode_info.height) - return 0; - - switch (source->mode_info.bpp) - { - case 32: - color = *(grub_uint32_t *)grub_video_vbe_get_video_ptr (source, x, y); - break; - - case 24: - { - grub_uint8_t *ptr; - ptr = grub_video_vbe_get_video_ptr (source, x, y); - color = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16); - } - break; - - case 16: - case 15: - color = *(grub_uint16_t *)grub_video_vbe_get_video_ptr (source, x, y); - break; - - case 8: - color = *(grub_uint8_t *)grub_video_vbe_get_video_ptr (source, x, y); - break; - - default: - break; - } - - return color; -} - static grub_err_t grub_video_vbe_init (void) { @@ -482,7 +374,7 @@ grub_video_vbe_init (void) } /* Reset frame buffer and render target variables. */ - grub_memset (&framebuffer, 0, sizeof(framebuffer)); + grub_memset (&framebuffer, 0, sizeof(framebuffer)); render_target = &framebuffer.render_target; return GRUB_ERR_NONE; @@ -738,7 +630,7 @@ grub_video_vbe_set_viewport (unsigned int x, unsigned int y, render_target->viewport.y = y; render_target->viewport.width = width; render_target->viewport.height = height; - + return GRUB_ERR_NONE; } @@ -836,7 +728,7 @@ grub_video_vbe_map_rgb (grub_uint8_t red, grub_uint8_t green, } -static grub_video_color_t +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) { @@ -864,12 +756,15 @@ grub_video_vbe_map_rgba (grub_uint8_t red, grub_uint8_t green, } void -grub_video_vbe_unmap_color (struct grub_video_render_target * source, +grub_video_vbe_unmap_color (struct grub_video_i386_vbeblit_info * source, grub_video_color_t color, grub_uint8_t *red, grub_uint8_t *green, grub_uint8_t *blue, grub_uint8_t *alpha) { - if ((source->mode_info.mode_type + struct grub_video_mode_info *mode_info; + mode_info = source->mode_info; + + if ((mode_info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) { /* If we have out of bounds color, return trasnparent black. */ @@ -893,33 +788,33 @@ grub_video_vbe_unmap_color (struct grub_video_render_target * source, grub_uint32_t tmp; /* Get red component. */ - tmp = color >> source->mode_info.red_field_pos; - tmp &= (1 << source->mode_info.red_mask_size) - 1; - tmp <<= 8 - source->mode_info.red_mask_size; - tmp |= (1 << (8 - source->mode_info.red_mask_size)) - 1; + tmp = color >> mode_info->red_field_pos; + tmp &= (1 << mode_info->red_mask_size) - 1; + tmp <<= 8 - mode_info->red_mask_size; + tmp |= (1 << (8 - mode_info->red_mask_size)) - 1; *red = tmp & 0xFF; /* Get green component. */ - tmp = color >> source->mode_info.green_field_pos; - tmp &= (1 << source->mode_info.green_mask_size) - 1; - tmp <<= 8 - source->mode_info.green_mask_size; - tmp |= (1 << (8 - source->mode_info.green_mask_size)) - 1; + tmp = color >> mode_info->green_field_pos; + tmp &= (1 << mode_info->green_mask_size) - 1; + tmp <<= 8 - mode_info->green_mask_size; + tmp |= (1 << (8 - mode_info->green_mask_size)) - 1; *green = tmp & 0xFF; /* Get blue component. */ - tmp = color >> source->mode_info.blue_field_pos; - tmp &= (1 << source->mode_info.blue_mask_size) - 1; - tmp <<= 8 - source->mode_info.blue_mask_size; - tmp |= (1 << (8 - source->mode_info.blue_mask_size)) - 1; + tmp = color >> mode_info->blue_field_pos; + tmp &= (1 << mode_info->blue_mask_size) - 1; + tmp <<= 8 - mode_info->blue_mask_size; + tmp |= (1 << (8 - mode_info->blue_mask_size)) - 1; *blue = tmp & 0xFF; /* Get alpha component. */ - if (source->mode_info.reserved_mask_size > 0) + if (source->mode_info->reserved_mask_size > 0) { - tmp = color >> source->mode_info.reserved_field_pos; - tmp &= (1 << source->mode_info.reserved_mask_size) - 1; - tmp <<= 8 - source->mode_info.reserved_mask_size; - tmp |= (1 << (8 - source->mode_info.reserved_mask_size)) - 1; + tmp = color >> mode_info->reserved_field_pos; + tmp &= (1 << mode_info->reserved_mask_size) - 1; + tmp <<= 8 - mode_info->reserved_mask_size; + tmp |= (1 << (8 - mode_info->reserved_mask_size)) - 1; } else /* If there is no alpha component, assume it opaque. */ @@ -933,7 +828,7 @@ static grub_err_t grub_video_vbe_fill_rect (grub_video_color_t color, int x, int y, unsigned int width, unsigned int height) { - unsigned int i, j; + struct grub_video_i386_vbeblit_info target; /* Make sure there is something to do. */ if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0)) @@ -962,40 +857,44 @@ grub_video_vbe_fill_rect (grub_video_color_t color, int x, int y, x += render_target->viewport.x; y += render_target->viewport.y; + /* Use vbeblit_info to encapsulate rendering. */ + target.mode_info = &render_target->mode_info; + target.data = render_target->data; + /* Try to figure out more optimized version. */ - if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8) + if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8) { - grub_video_i386_vbefill_R8G8B8A8 (render_target, color, x, y, + grub_video_i386_vbefill_R8G8B8A8 (&target, color, x, y, width, height); return GRUB_ERR_NONE; } - if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8) + if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_R8G8B8) { - grub_video_i386_vbefill_R8G8B8 (render_target, color, x, y, + grub_video_i386_vbefill_R8G8B8 (&target, color, x, y, width, height); return GRUB_ERR_NONE; } - if (render_target->mode_info.blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) { - grub_video_i386_vbefill_index (render_target, color, x, y, + grub_video_i386_vbefill_index (&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); + /* No optimized version found, use default (slow) filler. */ + grub_video_i386_vbefill (&target, color, x, y, width, height); return GRUB_ERR_NONE; } +// TODO: Remove this method and replace with bitmap based glyphs static grub_err_t grub_video_vbe_blit_glyph (struct grub_font_glyph * glyph, grub_video_color_t color, int x, int y) { + struct grub_video_i386_vbeblit_info target; unsigned int width; unsigned int charwidth; unsigned int height; @@ -1045,79 +944,184 @@ grub_video_vbe_blit_glyph (struct grub_font_glyph * glyph, x += render_target->viewport.x; y += render_target->viewport.y; + /* Use vbeblit_info to encapsulate rendering. */ + target.mode_info = &render_target->mode_info; + target.data = render_target->data; + /* 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)] & (1 << ((charwidth - (i + x_offset) - 1) % 8)))) - grub_video_vbe_draw_pixel (x+i, y+j, color); + set_pixel (&target, x+i, y+j, color); return GRUB_ERR_NONE; } +/* NOTE: This function assumes that given coordiantes are within bounds of + handled data. */ +static void +common_blitter (struct grub_video_i386_vbeblit_info *target, + struct grub_video_i386_vbeblit_info *source, + enum grub_video_blit_operators oper, int x, int y, + unsigned int width, unsigned int height, + int offset_x, int offset_y) +{ + 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; + } + } + + /* No optimized replace operator found, use default (slow) blitter. */ + grub_video_i386_vbeblit_replace (target, source, x, y, width, height, + 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 (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; + } + } + + /* No optimized blend operation found, use default (slow) blitter. */ + grub_video_i386_vbeblit_blend (target, source, x, y, width, height, + offset_x, offset_y); + } +} + static grub_err_t -grub_video_vbe_blit_bitmap (struct grub_video_bitmap * bitmap, - int x, int y, int offset_x, int offset_y, +grub_video_vbe_blit_bitmap (struct grub_video_bitmap *bitmap, + enum grub_video_blit_operators oper, int x, int y, + int offset_x, int offset_y, unsigned int width, unsigned int height) { - /* Make sure there is something to do. */ - if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0)) - return GRUB_ERR_NONE; - if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0)) - return GRUB_ERR_NONE; - - /* Do not allow drawing out of viewport. */ - if (offset_x < 0) - { - width += offset_x; - x -= offset_x; - offset_x = 0; - } - - if (offset_y < 0) - { - height += offset_y; - y -= offset_y; - offset_y = 0; - } - - if (x < 0) - { - width += x; - offset_x += (unsigned int)-x; - x = 0; - } - if (y < 0) - { - height += y; - offset_y += (unsigned int)-y; - y = 0; - } - - if ((x + width) > render_target->viewport.width) - width = render_target->viewport.width - x; - if ((y + height) > render_target->viewport.height) - height = render_target->viewport.height - y; - - /* TODO: Limit drawing to bitmap dimensions. */ - - /* Add viewport offset. */ - x += render_target->viewport.x; - y += render_target->viewport.y; - - /* TODO: Render bitmap. */ - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_video_vbe_blit_render_target (struct grub_video_render_target *source, - int x, int y, int offset_x, int offset_y, - unsigned int width, unsigned int height) -{ - unsigned int i; - unsigned int j; + struct grub_video_i386_vbeblit_info source; + struct grub_video_i386_vbeblit_info target; /* Make sure there is something to do. */ if ((width == 0) || (height == 0)) @@ -1125,17 +1129,17 @@ grub_video_vbe_blit_render_target (struct grub_video_render_target *source, if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0)) return GRUB_ERR_NONE; if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0)) - return GRUB_ERR_NONE; - if ((x + (int)source->mode_info.width) < 0) 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 ((x + (int)bitmap->mode_info.width) < 0) + return GRUB_ERR_NONE; + if ((y + (int)bitmap->mode_info.height) < 0) + return GRUB_ERR_NONE; + if ((offset_x >= (int)bitmap->mode_info.width) || (offset_x + (int)width < 0)) return GRUB_ERR_NONE; - if ((offset_y >= (int)source->mode_info.height) + if ((offset_y >= (int)bitmap->mode_info.height) || (offset_y + (int)height < 0)) - return GRUB_ERR_NONE; + return GRUB_ERR_NONE; /* If we have negative coordinates, optimize drawing to minimum. */ if (offset_x < 0) @@ -1155,14 +1159,105 @@ grub_video_vbe_blit_render_target (struct grub_video_render_target *source, if (x < 0) { width += x; - offset_x += (unsigned int)-x; + offset_x -= x; x = 0; } if (y < 0) { height += y; - offset_y += (unsigned int)-y; + offset_y -= y; + y = 0; + } + + /* Do not allow drawing out of viewport. */ + if ((x + width) > render_target->viewport.width) + width = render_target->viewport.width - x; + if ((y + height) > render_target->viewport.height) + height = render_target->viewport.height - y; + + if ((offset_x + width) > bitmap->mode_info.width) + width = bitmap->mode_info.width - offset_x; + if ((offset_y + height) > bitmap->mode_info.height) + height = bitmap->mode_info.height - offset_y; + + /* Limit drawing to source render target dimensions. */ + if (width > bitmap->mode_info.width) + width = bitmap->mode_info.width; + + if (height > bitmap->mode_info.height) + height = bitmap->mode_info.height; + + /* Add viewport offset. */ + x += render_target->viewport.x; + y += render_target->viewport.y; + + /* Use vbeblit_info to encapsulate rendering. */ + source.mode_info = &bitmap->mode_info; + source.data = bitmap->data; + target.mode_info = &render_target->mode_info; + target.data = render_target->data; + + /* Do actual blitting. */ + common_blitter (&target, &source, oper, x, y, width, height, + offset_x, offset_y); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_vbe_blit_render_target (struct grub_video_render_target *source, + enum grub_video_blit_operators oper, + int x, int y, int offset_x, int offset_y, + unsigned int width, unsigned int height) +{ + struct grub_video_i386_vbeblit_info source_info; + struct grub_video_i386_vbeblit_info target_info; + + /* Make sure there is something to do. */ + if ((width == 0) || (height == 0)) + return GRUB_ERR_NONE; + if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0)) + return GRUB_ERR_NONE; + if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0)) + return GRUB_ERR_NONE; + if ((x + (int)source->mode_info.width) < 0) + return GRUB_ERR_NONE; + if ((y + (int)source->mode_info.height) < 0) + return GRUB_ERR_NONE; + 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) + || (offset_y + (int)height < 0)) + return GRUB_ERR_NONE; + + /* If we have negative coordinates, optimize drawing to minimum. */ + if (offset_x < 0) + { + width += offset_x; + x -= offset_x; + offset_x = 0; + } + + if (offset_y < 0) + { + height += offset_y; + y -= offset_y; + offset_y = 0; + } + + if (x < 0) + { + width += x; + offset_x -= x; + x = 0; + } + + if (y < 0) + { + height += y; + offset_y -= y; y = 0; } @@ -1188,122 +1283,15 @@ grub_video_vbe_blit_render_target (struct grub_video_render_target *source, x += render_target->viewport.x; y += render_target->viewport.y; - /* 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; - } + /* Use vbeblit_info to encapsulate rendering. */ + source_info.mode_info = &source->mode_info; + source_info.data = source->data; + target_info.mode_info = &render_target->mode_info; + target_info.data = render_target->data; - 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++) - { - grub_uint8_t src_red; - grub_uint8_t src_green; - grub_uint8_t src_blue; - grub_uint8_t src_alpha; - grub_uint8_t dst_red; - grub_uint8_t dst_green; - grub_uint8_t dst_blue; - grub_uint8_t dst_alpha; - grub_video_color_t src_color; - grub_video_color_t dst_color; - - src_color = grub_video_vbe_get_pixel (source, i + offset_x, j + offset_y); - grub_video_vbe_unmap_color (source, src_color, &src_red, &src_green, - &src_blue, &src_alpha); - - if (src_alpha == 0) - continue; - - if (src_alpha == 255) - { - dst_color = grub_video_vbe_map_rgba (src_red, src_green, - src_blue, src_alpha); - grub_video_vbe_draw_pixel (x + i, y + j, dst_color); - continue; - } - - dst_color = grub_video_vbe_get_pixel (render_target, x + i, y + j); - - grub_video_vbe_unmap_color (render_target, dst_color, &dst_red, - &dst_green, &dst_blue, &dst_alpha); - - dst_red = (((src_red * src_alpha) - + (dst_red * (255 - src_alpha))) / 255); - dst_green = (((src_green * src_alpha) - + (dst_green * (255 - src_alpha))) / 255); - dst_blue = (((src_blue * src_alpha) - + (dst_blue * (255 - src_alpha))) / 255); - - dst_alpha = src_alpha; - dst_color = grub_video_vbe_map_rgba (dst_red, dst_green, dst_blue, - dst_alpha); - - grub_video_vbe_draw_pixel (x + i, y + j, dst_color); - } - } + /* Do actual blitting. */ + common_blitter (&target_info, &source_info, oper, x, y, width, height, + offset_x, offset_y); return GRUB_ERR_NONE; } @@ -1352,16 +1340,20 @@ grub_video_vbe_scroll (grub_video_color_t color, int dx, int dy) && (grub_abs (dy) < render_target->viewport.height)) { /* 3. Move data in render target. */ + struct grub_video_i386_vbeblit_info target; grub_uint8_t *src; grub_uint8_t *dst; int j; + target.mode_info = &render_target->mode_info; + target.data = render_target->data; + for (j = 0; j < height; j++) { - dst = grub_video_vbe_get_video_ptr (render_target, dst_x, dst_y + j); - src = grub_video_vbe_get_video_ptr (render_target, src_x, src_y + j); + dst = grub_video_vbe_get_video_ptr (&target, dst_x, dst_y + j); + src = grub_video_vbe_get_video_ptr (&target, src_x, src_y + j); grub_memmove (dst, src, - width * render_target->mode_info.bytes_per_pixel); + width * target.mode_info->bytes_per_pixel); } } @@ -1544,7 +1536,7 @@ static struct grub_video_adapter grub_video_vbe_adapter = .delete_render_target = grub_video_vbe_delete_render_target, .set_active_render_target = grub_video_vbe_set_active_render_target, - .next = 0 + .next = 0 }; GRUB_MOD_INIT(video_i386_pc_vbe) diff --git a/video/i386/pc/vbeblit.c b/video/i386/pc/vbeblit.c index 9cce2541c..c462237b4 100644 --- a/video/i386/pc/vbeblit.c +++ b/video/i386/pc/vbeblit.c @@ -17,20 +17,27 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include +/* SPECIAL NOTES! + + Please note following when reading the code below: + + - In this driver we assume that every memory can be accessed by same memory + bus. If there are different address spaces do not use this code as a base + code for other archs. + + - Every function in this code assumes that bounds checking has been done in + previous phase and they are opted out in here. */ + #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, +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) { @@ -52,10 +59,8 @@ grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (struct grub_video_render_target *dst, 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); + 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++) { @@ -97,8 +102,33 @@ grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8 (struct grub_video_render_target *dst, } void -grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +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) +{ + 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) { @@ -120,10 +150,8 @@ grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (struct grub_video_render_target *dst, 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); + 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++) { @@ -166,8 +194,46 @@ grub_video_i386_vbeblit_R8G8B8_R8G8B8A8 (struct grub_video_render_target *dst, } void -grub_video_i386_vbeblit_index_R8G8B8A8 (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +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) { @@ -190,10 +256,8 @@ grub_video_i386_vbeblit_index_R8G8B8A8 (struct grub_video_render_target *dst, 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); + 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++) { @@ -232,8 +296,45 @@ grub_video_i386_vbeblit_index_R8G8B8A8 (struct grub_video_render_target *dst, } void -grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +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) { @@ -251,10 +352,8 @@ grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_render_target *dst, 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); + srcptr = (grub_uint8_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++) { @@ -270,41 +369,33 @@ grub_video_i386_vbeblit_R8G8B8A8_R8G8B8 (struct grub_video_render_target *dst, } void -grub_video_i386_vbeblit_R8G8B8_R8G8B8 (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +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) { - int i; 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 *)grub_video_vbe_get_video_ptr (src, - offset_x, - j + offset_y); + srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - 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++; - } + grub_memmove (dstptr, srcptr, width * pitch); } } void -grub_video_i386_vbeblit_index_R8G8B8 (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +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) { @@ -322,10 +413,8 @@ grub_video_i386_vbeblit_index_R8G8B8 (struct grub_video_render_target *dst, 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); + srcptr = (grub_uint8_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++) { @@ -341,27 +430,122 @@ grub_video_i386_vbeblit_index_R8G8B8 (struct grub_video_render_target *dst, } void -grub_video_i386_vbeblit_index_index (struct grub_video_render_target *dst, - struct grub_video_render_target *src, +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 i; 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 *)grub_video_vbe_get_video_ptr (src, offset_x, - j + offset_y); + srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - dstptr = (grub_uint8_t *)grub_video_vbe_get_video_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - *dstptr++ = *srcptr++; + grub_memmove (dstptr, srcptr, width * pitch); } } + +void +grub_video_i386_vbeblit_blend (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; + + /* 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++) + { + grub_uint8_t src_red; + grub_uint8_t src_green; + grub_uint8_t src_blue; + grub_uint8_t src_alpha; + grub_uint8_t dst_red; + grub_uint8_t dst_green; + grub_uint8_t dst_blue; + grub_uint8_t dst_alpha; + grub_video_color_t src_color; + grub_video_color_t dst_color; + + src_color = get_pixel (src, i + offset_x, j + offset_y); + grub_video_vbe_unmap_color (src, src_color, &src_red, &src_green, + &src_blue, &src_alpha); + + if (src_alpha == 0) + continue; + + if (src_alpha == 255) + { + dst_color = grub_video_vbe_map_rgba (src_red, src_green, + src_blue, src_alpha); + set_pixel (dst, x + i, y + j, dst_color); + continue; + } + + dst_color = get_pixel (dst, x + i, y + j); + + grub_video_vbe_unmap_color (dst, dst_color, &dst_red, + &dst_green, &dst_blue, &dst_alpha); + + dst_red = (((src_red * src_alpha) + + (dst_red * (255 - src_alpha))) / 255); + dst_green = (((src_green * src_alpha) + + (dst_green * (255 - src_alpha))) / 255); + dst_blue = (((src_blue * src_alpha) + + (dst_blue * (255 - src_alpha))) / 255); + + dst_alpha = src_alpha; + dst_color = grub_video_vbe_map_rgba (dst_red, dst_green, dst_blue, + dst_alpha); + + set_pixel (dst, x + i, y + j, dst_color); + } + } +} + +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) +{ + 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. */ + + 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 (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); + } + } +} diff --git a/video/i386/pc/vbefill.c b/video/i386/pc/vbefill.c index d31e21af4..3c6dbfbb2 100644 --- a/video/i386/pc/vbefill.c +++ b/video/i386/pc/vbefill.c @@ -17,19 +17,25 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include +/* SPECIAL NOTES! + + Please note following when reading the code below: + + - In this driver we assume that every memory can be accessed by same memory + bus. If there are different address spaces do not use this code as a base + code for other archs. + + - Every function in this code assumes that bounds checking has been done in + previous phase and they are opted out in here. */ + #include #include +#include #include -#include -#include -#include -#include #include void -grub_video_i386_vbefill_R8G8B8A8 (struct grub_video_render_target *dst, +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) { @@ -50,7 +56,7 @@ grub_video_i386_vbefill_R8G8B8A8 (struct grub_video_render_target *dst, } void -grub_video_i386_vbefill_R8G8B8 (struct grub_video_render_target *dst, +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) { @@ -78,7 +84,7 @@ grub_video_i386_vbefill_R8G8B8 (struct grub_video_render_target *dst, } void -grub_video_i386_vbefill_index (struct grub_video_render_target *dst, +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) { @@ -98,3 +104,19 @@ grub_video_i386_vbefill_index (struct grub_video_render_target *dst, *dstptr++ = fill; } } + +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) +{ + 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); +} diff --git a/video/i386/pc/vbeutil.c b/video/i386/pc/vbeutil.c new file mode 100644 index 000000000..116ee786e --- /dev/null +++ b/video/i386/pc/vbeutil.c @@ -0,0 +1,150 @@ +/* + * 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 + +grub_uint8_t * +get_data_ptr (struct grub_video_i386_vbeblit_info *source, + unsigned int x, unsigned int y) +{ + grub_uint8_t *ptr = 0; + + switch (source->mode_info->bpp) + { + case 32: + ptr = (grub_uint8_t *)source->data + + y * source->mode_info->pitch + + x * 4; + break; + + case 24: + ptr = (grub_uint8_t *)source->data + + y * source->mode_info->pitch + + x * 3; + break; + + case 16: + case 15: + ptr = (grub_uint8_t *)source->data + + y * source->mode_info->pitch + + x * 2; + break; + + case 8: + ptr = (grub_uint8_t *)source->data + + y * source->mode_info->pitch + + x; + break; + } + + return ptr; +} + +grub_video_color_t +get_pixel (struct grub_video_i386_vbeblit_info *source, + unsigned int x, unsigned int y) +{ + grub_video_color_t color = 0; + + switch (source->mode_info->bpp) + { + case 32: + color = *(grub_uint32_t *)get_data_ptr (source, x, y); + break; + + case 24: + { + grub_uint8_t *ptr; + ptr = get_data_ptr (source, x, y); + color = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16); + } + break; + + case 16: + case 15: + color = *(grub_uint16_t *)get_data_ptr (source, x, y); + break; + + case 8: + color = *(grub_uint8_t *)get_data_ptr (source, x, y); + break; + + default: + break; + } + + return color; +} + +void +set_pixel (struct grub_video_i386_vbeblit_info *source, + unsigned int x, unsigned int y, grub_video_color_t color) +{ + switch (source->mode_info->bpp) + { + case 32: + { + grub_uint32_t *ptr; + + ptr = (grub_uint32_t *)get_data_ptr (source, x, y); + + *ptr = color; + } + break; + + case 24: + { + grub_uint8_t *ptr; + grub_uint8_t *colorptr = (grub_uint8_t *)&color; + + ptr = get_data_ptr (source, x, y); + + ptr[0] = colorptr[0]; + ptr[1] = colorptr[1]; + ptr[2] = colorptr[2]; + } + break; + + case 16: + case 15: + { + grub_uint16_t *ptr; + + ptr = (grub_uint16_t *)get_data_ptr (source, x, y); + + *ptr = (grub_uint16_t) (color & 0xFFFF); + } + break; + + case 8: + { + grub_uint8_t *ptr; + + ptr = (grub_uint8_t *)get_data_ptr (source, x, y); + + *ptr = (grub_uint8_t) (color & 0xFF); + } + break; + + default: + break; + } +} diff --git a/video/readers/tga.c b/video/readers/tga.c new file mode 100644 index 000000000..bdc44fad4 --- /dev/null +++ b/video/readers/tga.c @@ -0,0 +1,496 @@ +/* + * 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 + +/* Uncomment following define to enable TGA debug. */ +//#define TGA_DEBUG + +#if defined(TGA_DEBUG) +#define dump_int_field(x) grub_printf( #x " = %d (0x%04x)\n", x, x); +#endif + +enum +{ + GRUB_TGA_IMAGE_TYPE_NONE = 0, + GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_INDEXCOLOR = 1, + GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR = 2, + GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_BLACK_AND_WHITE = 3, + GRUB_TGA_IMAGE_TYPE_RLE_INDEXCOLOR = 9, + GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR = 10, + GRUB_TGA_IMAGE_TYPE_RLE_BLACK_AND_WHITE = 11, +}; + +enum +{ + GRUB_TGA_COLOR_MAP_TYPE_NONE = 0, + GRUB_TGA_COLOR_MAP_TYPE_INCLUDED = 1 +}; + +enum +{ + GRUB_TGA_IMAGE_ORIGIN_RIGHT = 0x10, + GRUB_TGA_IMAGE_ORIGIN_TOP = 0x20 +}; + +struct grub_tga_header +{ + grub_uint8_t id_length; + grub_uint8_t color_map_type; + grub_uint8_t image_type; + + /* Color Map Specification. */ + grub_uint16_t color_map_first_index; + grub_uint16_t color_map_length; + grub_uint8_t color_map_bpp; + + /* Image Specification. */ + grub_uint16_t image_x_origin; + grub_uint16_t image_y_origin; + grub_uint16_t image_width; + grub_uint16_t image_height; + grub_uint8_t image_bpp; + grub_uint8_t image_descriptor; +} __attribute__ ((packed)); + +static grub_err_t +tga_load_truecolor_rle_R8G8B8 (struct grub_video_bitmap *bitmap, + struct grub_tga_header *header, + grub_file_t file) +{ + unsigned int x; + unsigned int y; + grub_uint8_t type; + grub_uint8_t *ptr; + grub_uint8_t tmp[4]; /* Size should be max_bpp / 8. */ + grub_uint8_t bytes_per_pixel; + + bytes_per_pixel = header->image_bpp / 8; + + for (y = 0; y < header->image_height; y++) + { + ptr = bitmap->data; + if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0) + ptr += y * bitmap->mode_info.pitch; + else + ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch; + + for (x = 0; x < header->image_width;) + { + if (grub_file_read (file, (char *)&type, sizeof (type)) != sizeof(type)) + return grub_errno; + + if (type & 0x80) + { + /* RLE-encoded packet. */ + type &= 0x7f; + type++; + + if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel) + != bytes_per_pixel) + return grub_errno; + + while (type) + { + if (x < header->image_width) + { + ptr[0] = tmp[2]; + ptr[1] = tmp[1]; + ptr[2] = tmp[0]; + ptr += 3; + } + + type--; + x++; + } + } + else + { + /* RAW-encoded packet. */ + type++; + + while (type) + { + if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel) + != bytes_per_pixel) + return grub_errno; + + if (x < header->image_width) + { + ptr[0] = tmp[2]; + ptr[1] = tmp[1]; + ptr[2] = tmp[0]; + ptr += 3; + } + + type--; + x++; + } + } + } + } + return GRUB_ERR_NONE; +} + +static grub_err_t +tga_load_truecolor_rle_R8G8B8A8 (struct grub_video_bitmap *bitmap, + struct grub_tga_header *header, + grub_file_t file) +{ + unsigned int x; + unsigned int y; + grub_uint8_t type; + grub_uint8_t *ptr; + grub_uint8_t tmp[4]; /* Size should be max_bpp / 8. */ + grub_uint8_t bytes_per_pixel; + + bytes_per_pixel = header->image_bpp / 8; + + for (y = 0; y < header->image_height; y++) + { + ptr = bitmap->data; + if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0) + ptr += y * bitmap->mode_info.pitch; + else + ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch; + + for (x = 0; x < header->image_width;) + { + if (grub_file_read (file, (char *)&type, sizeof (type)) != sizeof(type)) + return grub_errno; + + if (type & 0x80) + { + /* RLE-encoded packet. */ + type &= 0x7f; + type++; + + if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel) + != bytes_per_pixel) + return grub_errno; + + while (type) + { + if (x < header->image_width) + { + ptr[0] = tmp[2]; + ptr[1] = tmp[1]; + ptr[2] = tmp[0]; + ptr[3] = tmp[3]; + ptr += 4; + } + + type--; + x++; + } + } + else + { + /* RAW-encoded packet. */ + type++; + + while (type) + { + if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel) + != bytes_per_pixel) + return grub_errno; + + if (x < header->image_width) + { + ptr[0] = tmp[2]; + ptr[1] = tmp[1]; + ptr[2] = tmp[0]; + ptr[3] = tmp[3]; + ptr += 4; + } + + type--; + x++; + } + } + } + } + return GRUB_ERR_NONE; +} + +static grub_err_t +tga_load_truecolor_R8G8B8 (struct grub_video_bitmap *bitmap, + struct grub_tga_header *header, + grub_file_t file) +{ + unsigned int x; + unsigned int y; + grub_uint8_t *ptr; + grub_uint8_t tmp[4]; /* Size should be max_bpp / 8. */ + grub_uint8_t bytes_per_pixel; + + bytes_per_pixel = header->image_bpp / 8; + + for (y = 0; y < header->image_height; y++) + { + ptr = bitmap->data; + if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0) + ptr += y * bitmap->mode_info.pitch; + else + ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch; + + for (x = 0; x < header->image_width; x++) + { + if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel) + != bytes_per_pixel) + return grub_errno; + + ptr[0] = tmp[2]; + ptr[1] = tmp[1]; + ptr[2] = tmp[0]; + + ptr += 3; + } + } + return GRUB_ERR_NONE; +} + +static grub_err_t +tga_load_truecolor_R8G8B8A8 (struct grub_video_bitmap *bitmap, + struct grub_tga_header *header, + grub_file_t file) +{ + unsigned int x; + unsigned int y; + grub_uint8_t *ptr; + grub_uint8_t tmp[4]; /* Size should be max_bpp / 8. */ + grub_uint8_t bytes_per_pixel; + + bytes_per_pixel = header->image_bpp / 8; + + for (y = 0; y < header->image_height; y++) + { + ptr = bitmap->data; + if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0) + ptr += y * bitmap->mode_info.pitch; + else + ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch; + + for (x = 0; x < header->image_width; x++) + { + if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel) + != bytes_per_pixel) + return grub_errno; + + ptr[0] = tmp[2]; + ptr[1] = tmp[1]; + ptr[2] = tmp[0]; + ptr[3] = tmp[3]; + + ptr += 4; + } + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_reader_tga (struct grub_video_bitmap **bitmap, + const char *filename) +{ + grub_file_t file; + grub_ssize_t pos; + struct grub_tga_header header; + int has_alpha; + + file = grub_file_open (filename); + if (! file) + return grub_errno; + + /* TGA Specification states that we SHOULD start by reading + ID from end of file, but we really don't care about that as we are + not going to support developer area & extensions at this point. */ + + /* Read TGA header from begining of file. */ + if (grub_file_read (file, (char*)&header, sizeof (header)) + != sizeof (header)) + { + grub_file_close (file); + return grub_errno; + } + + /* Skip ID field. */ + pos = grub_file_tell (file); + pos += header.id_length; + grub_file_seek (file, pos); + if (grub_errno != GRUB_ERR_NONE) + { + grub_file_close (file); + return grub_errno; + } + +#if defined(TGA_DEBUG) + grub_printf("tga: header\n"); + dump_int_field(header.id_length); + dump_int_field(header.color_map_type); + dump_int_field(header.image_type); + dump_int_field(header.color_map_first_index); + dump_int_field(header.color_map_length); + dump_int_field(header.color_map_bpp); + dump_int_field(header.image_x_origin); + dump_int_field(header.image_y_origin); + dump_int_field(header.image_width); + dump_int_field(header.image_height); + dump_int_field(header.image_bpp); + dump_int_field(header.image_descriptor); +#endif + + /* Check that bitmap encoding is supported. */ + switch (header.image_type) + { + case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: + case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: + break; + + default: + grub_file_close (file); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "Unsupported bitmap format (unknown encoding)."); + } + + /* Check that bitmap depth is supported. */ + switch (header.image_bpp) + { + case 24: + has_alpha = 0; + break; + + case 32: + has_alpha = 1; + break; + + default: + grub_file_close (file); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "Unsupported bitmap format (bpp=%d).", + header.image_bpp); + } + + /* Allocate bitmap. If there is alpha information store it too. */ + if (has_alpha) + { + grub_video_bitmap_create (bitmap, header.image_width, + header.image_height, + GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8); + if (grub_errno != GRUB_ERR_NONE) + { + grub_file_close (file); + return grub_errno; + } + + /* Load bitmap data. */ + switch (header.image_type) + { + case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: + tga_load_truecolor_R8G8B8A8 (*bitmap, &header, file); + break; + + case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: + tga_load_truecolor_rle_R8G8B8A8 (*bitmap, &header, file); + break; + } + } + else + { + grub_video_bitmap_create (bitmap, header.image_width, + header.image_height, + GRUB_VIDEO_BLIT_FORMAT_R8G8B8); + if (grub_errno != GRUB_ERR_NONE) + { + grub_file_close (file); + return grub_errno; + } + + /* Load bitmap data. */ + switch (header.image_type) + { + case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: + tga_load_truecolor_R8G8B8 (*bitmap, &header, file); + break; + + case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: + tga_load_truecolor_rle_R8G8B8 (*bitmap, &header, file); + break; + } + } + + /* If there were loading proble, destroy bitmap. */ + if (grub_errno != GRUB_ERR_NONE) + { + grub_video_bitmap_destroy (*bitmap); + *bitmap = 0; + } + + grub_file_close (file); + return grub_errno; +} + +#if defined(TGA_DEBUG) +static grub_err_t +grub_cmd_tgatest (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_video_bitmap *bitmap = 0; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + + grub_video_reader_tga (&bitmap, args[0]); + if (grub_errno != GRUB_ERR_NONE) + return grub_errno; + + grub_video_bitmap_destroy (bitmap); + + return GRUB_ERR_NONE; +} +#endif + +static struct grub_video_bitmap_reader tga_reader = { + .extension = ".tga", + .reader = grub_video_reader_tga, + .next = 0 +}; + +GRUB_MOD_INIT(video_reader_tga) +{ + grub_video_bitmap_reader_register (&tga_reader); +#if defined(TGA_DEBUG) + grub_register_command ("tgatest", grub_cmd_tgatest, GRUB_COMMAND_FLAG_BOTH, + "tgatest FILE", "Tests loading of TGA bitmap.", 0); +#endif +} + +GRUB_MOD_FINI(video_reader_tga) +{ +#if defined(TGA_DEBUG) + grub_unregister_command ("tgatest"); +#endif + grub_video_bitmap_reader_unregister (&tga_reader); +} diff --git a/video/video.c b/video/video.c index ac0714fd2..61bac1c69 100644 --- a/video/video.c +++ b/video/video.c @@ -82,7 +82,7 @@ grub_video_setup (unsigned int width, unsigned int height, /* Loop thru all possible video adapter trying to find requested mode. */ for (p = grub_video_adapter_list; p; p = p->next) { - /* Try to initialize adapter, if can't skip to next. */ + /* Try to initialize adapter, if it fails, skip to next adapter. */ p->init (); if (grub_errno != GRUB_ERR_NONE) { @@ -142,7 +142,7 @@ grub_video_get_info (struct grub_video_mode_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. */ + /* Check if we have any known 32 bit modes. */ if (mode_info->bpp == 32) { if ((mode_info->red_mask_size == 8) @@ -286,13 +286,14 @@ grub_video_blit_glyph (struct grub_font_glyph *glyph, /* Blit bitmap to screen. */ grub_err_t grub_video_blit_bitmap (struct grub_video_bitmap *bitmap, + enum grub_video_blit_operators oper, int x, int y, int offset_x, int offset_y, unsigned int width, unsigned int height) { if (! grub_video_adapter_active) return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated"); - return grub_video_adapter_active->blit_bitmap (bitmap, x, y, + return grub_video_adapter_active->blit_bitmap (bitmap, oper, x, y, offset_x, offset_y, width, height); } @@ -300,14 +301,15 @@ grub_video_blit_bitmap (struct grub_video_bitmap *bitmap, /* Blit render target to active render target. */ grub_err_t grub_video_blit_render_target (struct grub_video_render_target *target, + enum grub_video_blit_operators oper, int x, int y, int offset_x, int offset_y, unsigned int width, unsigned int height) { if (! grub_video_adapter_active) return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated"); - return grub_video_adapter_active->blit_render_target (target, x, y, - offset_x, offset_y, + return grub_video_adapter_active->blit_render_target (target, oper, x, y, + offset_x, offset_y, width, height); }