diff --git a/conf/common.rmk b/conf/common.rmk index 3d74f90..41bfd30 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -521,13 +521,18 @@ lua_mod_LDFLAGS = $(COMMON_LDFLAGS) # Common Video Subsystem specific modules. pkglib_MODULES += video.mod videotest.mod bitmap.mod tga.mod jpeg.mod \ - png.mod font.mod gfxterm.mod + png.mod font.mod gfxterm.mod video_fb.mod # For video.mod. video_mod_SOURCES = video/video.c video_mod_CFLAGS = $(COMMON_CFLAGS) video_mod_LDFLAGS = $(COMMON_LDFLAGS) +video_fb_mod_SOURCES = video/fb/video_fb.c video/fb/fbblit.c \ + video/fb/fbfill.c video/fb/fbutil.c +video_fb_mod_CFLAGS = $(COMMON_CFLAGS) +video_fb_mod_LDFLAGS = $(COMMON_LDFLAGS) + # For videotest.mod. videotest_mod_SOURCES = commands/videotest.c videotest_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index abb6fd5..66fdbd4 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -277,8 +277,7 @@ multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS) # For vbe.mod. -vbe_mod_SOURCES = video/i386/pc/vbe.c video/i386/pc/vbeblit.c \ - video/i386/pc/vbefill.c video/i386/pc/vbeutil.c +vbe_mod_SOURCES = video/i386/pc/vbe.c vbe_mod_CFLAGS = $(COMMON_CFLAGS) vbe_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/include/grub/fbblit.h b/include/grub/fbblit.h new file mode 100644 index 0000000..664f508 --- /dev/null +++ b/include/grub/fbblit.h @@ -0,0 +1,134 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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, see . + */ + +#ifndef GRUB_FBBLIT_HEADER +#define GRUB_FBBLIT_HEADER 1 + +/* NOTE: This header is private header for fb driver and should not be used + in other parts of the code. */ + +struct grub_video_fbblit_info; + +void +grub_video_fbblit_replace (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_replace_directN (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_replace_BGRX8888_RGBX8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_replace_BGRX8888_RGB888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_replace_BGR888_RGBX8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_replace_BGR888_RGB888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_replace_RGBX8888_RGB888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_replace_RGB888_RGBX8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_replace_index_RGBX8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_replace_index_RGB888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_blend (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_blend_BGRA8888_RGBA8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_blend_BGR888_RGBA8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_blend_RGBA8888_RGBA8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_blend_RGB888_RGBA8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y); + +void +grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y); + +#endif /* ! GRUB_FBBLIT_HEADER */ diff --git a/include/grub/fbfill.h b/include/grub/fbfill.h new file mode 100644 index 0000000..11e22c6 --- /dev/null +++ b/include/grub/fbfill.h @@ -0,0 +1,52 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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, see . + */ + +#ifndef GRUB_FBFILL_HEADER +#define GRUB_FBFILL_HEADER 1 + +/* NOTE: This header is private header for fb driver and should not be used + in other parts of the code. */ + +struct grub_video_fbblit_info; + +void +grub_video_fbfill (struct grub_video_fbblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height); + +void +grub_video_fbfill_direct32 (struct grub_video_fbblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height); + +void +grub_video_fbfill_direct24 (struct grub_video_fbblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height); + +void +grub_video_fbfill_direct16 (struct grub_video_fbblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height); + +void +grub_video_fbfill_direct8 (struct grub_video_fbblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height); + +#endif /* ! GRUB_FBFILL_HEADER */ diff --git a/include/grub/fbutil.h b/include/grub/fbutil.h new file mode 100644 index 0000000..76e1e57 --- /dev/null +++ b/include/grub/fbutil.h @@ -0,0 +1,43 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007 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 3 of the License, or + * (at your option) any later version. + * + * GRUB 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, see . + */ + +/* 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_fbblit_info +{ + struct grub_video_mode_info *mode_info; + void *data; +}; + +grub_uint8_t *get_data_ptr (struct grub_video_fbblit_info *source, + unsigned int x, unsigned int y); + +grub_video_color_t get_pixel (struct grub_video_fbblit_info *source, + unsigned int x, unsigned int y); + +void set_pixel (struct grub_video_fbblit_info *source, + unsigned int x, unsigned int y, grub_video_color_t color); + +#endif /* ! GRUB_VBEUTIL_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index bd6ecd7..fb11678 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -19,10 +19,7 @@ #ifndef GRUB_VBE_MACHINE_HEADER #define GRUB_VBE_MACHINE_HEADER 1 -#include -#include -#include -#include +#include /* Default video mode to be used. */ #define GRUB_VBE_DEFAULT_VIDEO_MODE 0x101 @@ -224,54 +221,5 @@ grub_err_t grub_vbe_get_video_mode (grub_uint32_t *mode); grub_err_t grub_vbe_get_video_mode_info (grub_uint32_t mode, struct grub_vbe_mode_info_block *mode_info); -/* VBE module internal prototypes (should not be used from elsewhere). */ -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 whether 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); - -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); - -grub_err_t grub_video_vbe_unmap_color (grub_video_color_t color, - grub_uint8_t *red, - grub_uint8_t *green, - grub_uint8_t *blue, - grub_uint8_t *alpha); - -void grub_video_vbe_unmap_color_int (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); #endif /* ! GRUB_VBE_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/vbeblit.h b/include/grub/i386/pc/vbeblit.h deleted file mode 100644 index 5a2aa7a..0000000 --- a/include/grub/i386/pc/vbeblit.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB 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, see . - */ - -#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_replace (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_replace_directN (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_replace_BGR888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_replace_BGR888_RGB888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_replace_RGB888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_replace_index_RGBX8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_replace_index_RGB888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_blend (struct grub_video_i386_vbeblit_info *dst, - 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_BGRA8888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_blend_BGR888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_blend_RGB888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y); - -void -grub_video_i386_vbeblit_blend_index_RGBA8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y); - -#endif /* ! GRUB_VBEBLIT_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/vbefill.h b/include/grub/i386/pc/vbefill.h deleted file mode 100644 index efc6378..0000000 --- a/include/grub/i386/pc/vbefill.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB 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, see . - */ - -#ifndef GRUB_VBEFILL_MACHINE_HEADER -#define GRUB_VBEFILL_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_vbefill (struct grub_video_i386_vbeblit_info *dst, - grub_video_color_t color, int x, int y, - int width, int height); - -void -grub_video_i386_vbefill_direct32 (struct grub_video_i386_vbeblit_info *dst, - grub_video_color_t color, int x, int y, - int width, int height); - -void -grub_video_i386_vbefill_direct24 (struct grub_video_i386_vbeblit_info *dst, - grub_video_color_t color, int x, int y, - int width, int height); - -void -grub_video_i386_vbefill_direct16 (struct grub_video_i386_vbeblit_info *dst, - grub_video_color_t color, int x, int y, - int width, int height); - -void -grub_video_i386_vbefill_direct8 (struct grub_video_i386_vbeblit_info *dst, - grub_video_color_t color, int x, int y, - int width, int height); - -#endif /* ! GRUB_VBEFILL_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/vbeutil.h b/include/grub/i386/pc/vbeutil.h deleted file mode 100644 index 9b5be21..0000000 --- a/include/grub/i386/pc/vbeutil.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007 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 3 of the License, or - * (at your option) any later version. - * - * GRUB 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, see . - */ - -/* 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_fb.h b/include/grub/video_fb.h new file mode 100644 index 0000000..8c6987e --- /dev/null +++ b/include/grub/video_fb.h @@ -0,0 +1,136 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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, see . + */ + +#ifndef GRUB_VIDEO_FB_HEADER +#define GRUB_VIDEO_FB_HEADER 1 + +#include +#include +#include +#include + +/* FB module internal prototype (should not be used from elsewhere). */ + +struct grub_video_fbblit_info; + +struct grub_video_fbrender_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 whether 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_video_fbstd_colors[16]; + +grub_uint8_t * grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source, + grub_uint32_t x, grub_uint32_t y); + +grub_err_t +grub_video_fb_init (void); + +grub_err_t +grub_video_fb_fini (void); + +grub_err_t +grub_video_fb_get_info (struct grub_video_mode_info *mode_info); + +grub_err_t +grub_video_fb_get_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data); +grub_err_t +grub_video_fb_set_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data); +grub_err_t +grub_video_fb_set_viewport (unsigned int x, unsigned int y, + unsigned int width, unsigned int height); +grub_err_t +grub_video_fb_get_viewport (unsigned int *x, unsigned int *y, + unsigned int *width, unsigned int *height); + +grub_video_color_t +grub_video_fb_map_color (grub_uint32_t color_name); + +grub_video_color_t +grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green, + grub_uint8_t blue); + +grub_video_color_t +grub_video_fb_map_rgba (grub_uint8_t red, grub_uint8_t green, + grub_uint8_t blue, grub_uint8_t alpha); + +grub_err_t +grub_video_fb_unmap_color (grub_video_color_t color, + grub_uint8_t *red, grub_uint8_t *green, + grub_uint8_t *blue, grub_uint8_t *alpha); + +void +grub_video_fb_unmap_color_int (struct grub_video_fbblit_info * source, + grub_video_color_t color, + grub_uint8_t *red, grub_uint8_t *green, + grub_uint8_t *blue, grub_uint8_t *alpha); + +grub_err_t +grub_video_fb_fill_rect (grub_video_color_t color, int x, int y, + unsigned int width, unsigned int height); + +grub_err_t +grub_video_fb_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_fb_blit_render_target (struct grub_video_fbrender_target *source, + 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_fb_scroll (grub_video_color_t color, int dx, int dy); + +grub_err_t +grub_video_fb_create_render_target (struct grub_video_fbrender_target **result, + unsigned int width, unsigned int height, + unsigned int mode_type __attribute__ ((unused))); + +grub_err_t +grub_video_fb_delete_render_target (struct grub_video_fbrender_target *target); + +grub_err_t +grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **target); + +grub_err_t +grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *target); + +#endif /* ! GRUB_VIDEO_FB_HEADER */ diff --git a/loader/i386/linux.c b/loader/i386/linux.c index 6510db6..1748836 100644 --- a/loader/i386/linux.c +++ b/loader/i386/linux.c @@ -31,9 +31,7 @@ #include #include #include -/* FIXME: the definition of `struct grub_video_render_target' is - VBE-specific. */ -#include +#include #include #define GRUB_LINUX_CL_OFFSET 0x1000 @@ -403,14 +401,15 @@ static int grub_linux_setup_video (struct linux_kernel_params *params) { struct grub_video_mode_info mode_info; - struct grub_video_render_target *render_target; + struct grub_video_fbrender_target *render_target; int ret; ret = grub_video_get_info (&mode_info); if (ret) return 1; - ret = grub_video_get_active_render_target (&render_target); + ret = grub_video_get_active_render_target + ((struct grub_video_render_target **) &render_target); if (ret) return 1; diff --git a/loader/i386/pc/xnu.c b/loader/i386/pc/xnu.c index 037a713..2712a8a 100644 --- a/loader/i386/pc/xnu.c +++ b/loader/i386/pc/xnu.c @@ -21,8 +21,7 @@ #include #include #include -#include -#include +#include #define min(a,b) (((a) < (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b)) @@ -43,7 +42,7 @@ grub_err_t grub_xnu_set_video (struct grub_xnu_boot_params *params) { struct grub_video_mode_info mode_info; - struct grub_video_render_target *render_target; + struct grub_video_fbrender_target *render_target; int ret; int x,y; char *tmp, *modevar; @@ -71,7 +70,8 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) if (ret) return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters"); - ret = grub_video_get_active_render_target (&render_target); + ret = grub_video_get_active_render_target + ((struct grub_video_render_target **) &render_target); if (ret) return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters"); diff --git a/video/fb/fbblit.c b/video/fb/fbblit.c new file mode 100644 index 0000000..138eba8 --- /dev/null +++ b/video/fb/fbblit.c @@ -0,0 +1,828 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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, see . + */ + +/* 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 + +/* Generic replacing blitter (slow). Works for every supported format. */ +void +grub_video_fbblit_replace (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, int width, int height, + int offset_x, int offset_y) +{ + int i; + int j; + grub_uint8_t src_red; + grub_uint8_t src_green; + grub_uint8_t src_blue; + grub_uint8_t src_alpha; + grub_video_color_t src_color; + grub_video_color_t dst_color; + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + src_color = get_pixel (src, i + offset_x, j + offset_y); + + grub_video_fb_unmap_color_int (src, src_color, &src_red, &src_green, + &src_blue, &src_alpha); + + dst_color = grub_video_fb_map_rgba (src_red, src_green, + src_blue, src_alpha); + + set_pixel (dst, x + i, y + j, dst_color); + } + } +} + +/* Block copy replacing blitter. Works with modes multiple of 8 bits. */ +void +grub_video_fbblit_replace_directN (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, int width, int height, + int offset_x, int offset_y) +{ + int j; + grub_uint32_t *srcptr; + grub_uint32_t *dstptr; + int bpp; + + bpp = src->mode_info->bytes_per_pixel; + + for (j = 0; j < height; j++) + { + srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j); + + grub_memmove (dstptr, srcptr, width * bpp); + } +} + +/* Optimized replacing blitter for RGBX8888 to BGRX8888. */ +void +grub_video_fbblit_replace_BGRX8888_RGBX8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + int i; + int j; + grub_uint8_t *srcptr; + grub_uint8_t *dstptr; + unsigned int srcrowskip; + unsigned int dstrowskip; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; + dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + srcptr = (grub_uint8_t *) get_data_ptr (src, offset_x, offset_y); + dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + grub_uint8_t r = *srcptr++; + grub_uint8_t g = *srcptr++; + grub_uint8_t b = *srcptr++; + grub_uint8_t a = *srcptr++; + + *dstptr++ = b; + *dstptr++ = g; + *dstptr++ = r; + *dstptr++ = a; + } + + srcptr += srcrowskip; + dstptr += dstrowskip; + } +} + +/* Optimized replacing blitter for RGB888 to BGRX8888. */ +void +grub_video_fbblit_replace_BGRX8888_RGB888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + int i; + int j; + grub_uint8_t *srcptr; + grub_uint8_t *dstptr; + unsigned int srcrowskip; + unsigned int dstrowskip; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; + dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + srcptr = (grub_uint8_t *) get_data_ptr (src, offset_x, offset_y); + dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + grub_uint8_t r = *srcptr++; + grub_uint8_t g = *srcptr++; + grub_uint8_t b = *srcptr++; + + *dstptr++ = b; + *dstptr++ = g; + *dstptr++ = r; + + /* Set alpha component as opaque. */ + *dstptr++ = 255; + } + + srcptr += srcrowskip; + dstptr += dstrowskip; + } +} + +/* Optimized replacing blitter for RGBX8888 to BGR888. */ +void +grub_video_fbblit_replace_BGR888_RGBX8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + grub_uint32_t *srcptr; + grub_uint8_t *dstptr; + unsigned int srcrowskip; + unsigned int dstrowskip; + int i; + int j; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; + dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + srcptr = (grub_uint32_t *) get_data_ptr (src, offset_x, offset_y); + dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + grub_uint32_t color; + grub_uint8_t sr; + grub_uint8_t sg; + grub_uint8_t sb; + + color = *srcptr++; + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + *dstptr++ = sb; + *dstptr++ = sg; + *dstptr++ = sr; + } + + srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); + dstptr += dstrowskip; + } +} + +/* Optimized replacing blitter for RGB888 to BGR888. */ +void +grub_video_fbblit_replace_BGR888_RGB888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + int i; + int j; + grub_uint8_t *srcptr; + grub_uint8_t *dstptr; + unsigned int srcrowskip; + unsigned int dstrowskip; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; + dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + srcptr = (grub_uint8_t *) get_data_ptr (src, offset_x, offset_y); + dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + grub_uint8_t r = *srcptr++; + grub_uint8_t g = *srcptr++; + grub_uint8_t b = *srcptr++; + + *dstptr++ = b; + *dstptr++ = g; + *dstptr++ = r; + } + + srcptr += srcrowskip; + dstptr += dstrowskip; + } +} + +/* Optimized replacing blitter for RGB888 to RGBX8888. */ +void +grub_video_fbblit_replace_RGBX8888_RGB888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + grub_uint32_t color; + int i; + int j; + grub_uint8_t *srcptr; + grub_uint32_t *dstptr; + unsigned int sr; + unsigned int sg; + unsigned int sb; + + for (j = 0; j < height; 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++) + { + sr = *srcptr++; + sg = *srcptr++; + sb = *srcptr++; + + /* Set alpha as opaque. */ + color = 0xFF000000 | (sb << 16) | (sg << 8) | sr; + + *dstptr++ = color; + } + } +} + +/* Optimized replacing blitter for RGBX8888 to RGB888. */ +void +grub_video_fbblit_replace_RGB888_RGBX8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + grub_uint32_t color; + int i; + int j; + grub_uint32_t *srcptr; + grub_uint8_t *dstptr; + unsigned int sr; + unsigned int sg; + unsigned int sb; + + for (j = 0; j < height; j++) + { + srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + { + color = *srcptr++; + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + *dstptr++ = sr; + *dstptr++ = sg; + *dstptr++ = sb; + } + } +} + +/* Optimized replacing blitter for RGBX8888 to indexed color. */ +void +grub_video_fbblit_replace_index_RGBX8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + grub_uint32_t color; + int i; + int j; + grub_uint32_t *srcptr; + grub_uint8_t *dstptr; + unsigned int sr; + unsigned int sg; + unsigned int sb; + + for (j = 0; j < height; j++) + { + srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + { + color = *srcptr++; + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + color = grub_video_fb_map_rgb(sr, sg, sb); + *dstptr++ = color & 0xFF; + } + } +} + +/* Optimized replacing blitter for RGB888 to indexed color. */ +void +grub_video_fbblit_replace_index_RGB888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + grub_uint32_t color; + int i; + int j; + grub_uint8_t *srcptr; + grub_uint8_t *dstptr; + unsigned int sr; + unsigned int sg; + unsigned int sb; + + for (j = 0; j < height; j++) + { + srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + { + sr = *srcptr++; + sg = *srcptr++; + sb = *srcptr++; + + color = grub_video_fb_map_rgb(sr, sg, sb); + + *dstptr++ = color & 0xFF; + } + } +} + +/* Generic blending blitter. Works for every supported format. */ +void +grub_video_fbblit_blend (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, int width, int height, + int offset_x, int offset_y) +{ + int i; + int j; + + 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_fb_unmap_color_int (src, src_color, &src_red, &src_green, + &src_blue, &src_alpha); + + if (src_alpha == 0) + continue; + + if (src_alpha == 255) + { + dst_color = grub_video_fb_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_fb_unmap_color_int (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_fb_map_rgba (dst_red, dst_green, dst_blue, + dst_alpha); + + set_pixel (dst, x + i, y + j, dst_color); + } + } +} + +/* Optimized blending blitter for RGBA8888 to BGRA8888. */ +void +grub_video_fbblit_blend_BGRA8888_RGBA8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + grub_uint32_t *srcptr; + grub_uint32_t *dstptr; + unsigned int srcrowskip; + unsigned int dstrowskip; + int i; + int j; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; + dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + srcptr = (grub_uint32_t *) get_data_ptr (src, offset_x, offset_y); + dstptr = (grub_uint32_t *) get_data_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + grub_uint32_t color; + unsigned int sr; + unsigned int sg; + unsigned int sb; + unsigned int a; + unsigned int dr; + unsigned int dg; + unsigned int db; + + color = *srcptr++; + + a = color >> 24; + + if (a == 0) + { + /* Skip transparent source pixels. */ + dstptr++; + continue; + } + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + if (a == 255) + { + /* Opaque pixel shortcut. */ + dr = sr; + dg = sg; + db = sb; + } + else + { + /* General pixel color blending. */ + color = *dstptr; + + dr = (color >> 16) & 0xFF; + dr = (dr * (255 - a) + sr * a) / 255; + dg = (color >> 8) & 0xFF; + dg = (dg * (255 - a) + sg * a) / 255; + db = (color >> 0) & 0xFF; + db = (db * (255 - a) + sb * a) / 255; + } + + color = (a << 24) | (dr << 16) | (dg << 8) | db; + + *dstptr++ = color; + } + + srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); + dstptr = (grub_uint32_t *) (((grub_uint8_t *) dstptr) + dstrowskip); + } +} + +/* Optimized blending blitter for RGBA8888 to BGR888. */ +void +grub_video_fbblit_blend_BGR888_RGBA8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + grub_uint32_t *srcptr; + grub_uint8_t *dstptr; + unsigned int srcrowskip; + unsigned int dstrowskip; + int i; + int j; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; + dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + srcptr = (grub_uint32_t *) get_data_ptr (src, offset_x, offset_y); + dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + grub_uint32_t color; + unsigned int sr; + unsigned int sg; + unsigned int sb; + unsigned int a; + unsigned int dr; + unsigned int dg; + unsigned int db; + + color = *srcptr++; + + a = color >> 24; + + if (a == 0) + { + /* Skip transparent source pixels. */ + dstptr += 3; + continue; + } + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + if (a == 255) + { + /* Opaque pixel shortcut. */ + dr = sr; + dg = sg; + db = sb; + } + else + { + /* General pixel color blending. */ + color = *dstptr; + + db = dstptr[0]; + db = (db * (255 - a) + sb * a) / 255; + dg = dstptr[1]; + dg = (dg * (255 - a) + sg * a) / 255; + dr = dstptr[2]; + dr = (dr * (255 - a) + sr * a) / 255; + } + + *dstptr++ = db; + *dstptr++ = dg; + *dstptr++ = dr; + } + + srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); + dstptr += dstrowskip; + } +} + +/* Optimized blending blitter for RGBA888 to RGBA8888. */ +void +grub_video_fbblit_blend_RGBA8888_RGBA8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + grub_uint32_t color; + int i; + int j; + grub_uint32_t *srcptr; + grub_uint32_t *dstptr; + unsigned int sr; + unsigned int sg; + unsigned int sb; + unsigned int a; + unsigned int dr; + unsigned int dg; + unsigned int db; + + for (j = 0; j < height; j++) + { + srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + { + color = *srcptr++; + + a = color >> 24; + + if (a == 0) + { + dstptr++; + continue; + } + + if (a == 255) + { + *dstptr++ = color; + continue; + } + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + color = *dstptr; + + dr = (color >> 0) & 0xFF; + dg = (color >> 8) & 0xFF; + db = (color >> 16) & 0xFF; + + dr = (dr * (255 - a) + sr * a) / 255; + dg = (dg * (255 - a) + sg * a) / 255; + db = (db * (255 - a) + sb * a) / 255; + + color = (a << 24) | (db << 16) | (dg << 8) | dr; + + *dstptr++ = color; + } + } +} + +/* Optimized blending blitter for RGBA8888 to RGB888. */ +void +grub_video_fbblit_blend_RGB888_RGBA8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + grub_uint32_t color; + int i; + int j; + grub_uint32_t *srcptr; + grub_uint8_t *dstptr; + unsigned int sr; + unsigned int sg; + unsigned int sb; + unsigned int a; + unsigned int dr; + unsigned int dg; + unsigned int db; + + for (j = 0; j < height; j++) + { + srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + { + color = *srcptr++; + + a = color >> 24; + + if (a == 0) + { + dstptr += 3; + continue; + } + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + if (a == 255) + { + *dstptr++ = sr; + *dstptr++ = sg; + *dstptr++ = sb; + + continue; + } + + dr = dstptr[0]; + dg = dstptr[1]; + db = dstptr[2]; + + dr = (dr * (255 - a) + sr * a) / 255; + dg = (dg * (255 - a) + sg * a) / 255; + db = (db * (255 - a) + sb * a) / 255; + + *dstptr++ = dr; + *dstptr++ = dg; + *dstptr++ = db; + } + } +} + +/* Optimized blending blitter for RGBA8888 to indexed color. */ +void +grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst, + struct grub_video_fbblit_info *src, + int x, int y, + int width, int height, + int offset_x, int offset_y) +{ + grub_uint32_t color; + int i; + int j; + grub_uint32_t *srcptr; + grub_uint8_t *dstptr; + unsigned int sr; + unsigned int sg; + unsigned int sb; + unsigned int a; + unsigned char dr; + unsigned char dg; + unsigned char db; + unsigned char da; + + for (j = 0; j < height; j++) + { + srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); + dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); + + for (i = 0; i < width; i++) + { + color = *srcptr++; + + a = color >> 24; + + if (a == 0) + { + dstptr++; + continue; + } + + sr = (color >> 0) & 0xFF; + sg = (color >> 8) & 0xFF; + sb = (color >> 16) & 0xFF; + + if (a == 255) + { + color = grub_video_fb_map_rgb(sr, sg, sb); + *dstptr++ = color & 0xFF; + continue; + } + + grub_video_fb_unmap_color_int (dst, *dstptr, &dr, &dg, &db, &da); + + dr = (dr * (255 - a) + sr * a) / 255; + dg = (dg * (255 - a) + sg * a) / 255; + db = (db * (255 - a) + sb * a) / 255; + + color = grub_video_fb_map_rgb(dr, dg, db); + + *dstptr++ = color & 0xFF; + } + } +} diff --git a/video/fb/fbfill.c b/video/fb/fbfill.c new file mode 100644 index 0000000..a4ca7c2 --- /dev/null +++ b/video/fb/fbfill.c @@ -0,0 +1,177 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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, see . + */ + +/* 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 + +/* Generic filler that works for every supported mode. */ +void +grub_video_fbfill (struct grub_video_fbblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height) +{ + int i; + int j; + + for (j = 0; j < height; j++) + for (i = 0; i < width; i++) + set_pixel (dst, x + i, y + j, color); +} + +/* Optimized filler for direct color 32 bit modes. It is assumed that color + is already mapped to destination format. */ +void +grub_video_fbfill_direct32 (struct grub_video_fbblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height) +{ + int i; + int j; + grub_uint32_t *dstptr; + grub_size_t rowskip; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + /* Get the start address. */ + dstptr = (grub_uint32_t *) grub_video_fb_get_video_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + *dstptr++ = color; + + /* Advance the dest pointer to the right location on the next line. */ + dstptr = (grub_uint32_t *) (((char *) dstptr) + rowskip); + } +} + +/* Optimized filler for direct color 24 bit modes. It is assumed that color + is already mapped to destination format. */ +void +grub_video_fbfill_direct24 (struct grub_video_fbblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height) +{ + int i; + int j; + grub_size_t rowskip; + grub_uint8_t *dstptr; + grub_uint8_t fill0 = (grub_uint8_t)((color >> 0) & 0xFF); + grub_uint8_t fill1 = (grub_uint8_t)((color >> 8) & 0xFF); + grub_uint8_t fill2 = (grub_uint8_t)((color >> 16) & 0xFF); + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + /* Get the start address. */ + dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + *dstptr++ = fill0; + *dstptr++ = fill1; + *dstptr++ = fill2; + } + + /* Advance the dest pointer to the right location on the next line. */ + dstptr += rowskip; + } +} + +/* Optimized filler for direct color 16 bit modes. It is assumed that color + is already mapped to destination format. */ +void +grub_video_fbfill_direct16 (struct grub_video_fbblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height) +{ + int i; + int j; + grub_size_t rowskip; + grub_uint8_t *dstptr; + grub_uint8_t fill0 = (grub_uint8_t)((color >> 0) & 0xFF); + grub_uint8_t fill1 = (grub_uint8_t)((color >> 8) & 0xFF); + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + /* Get the start address. */ + dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + *dstptr++ = fill0; + *dstptr++ = fill1; + } + + /* Advance the dest pointer to the right location on the next line. */ + dstptr += rowskip; + } +} + +/* Optimized filler for index color. It is assumed that color + is already mapped to destination format. */ +void +grub_video_fbfill_direct8 (struct grub_video_fbblit_info *dst, + grub_video_color_t color, int x, int y, + int width, int height) +{ + int i; + int j; + grub_size_t rowskip; + grub_uint8_t *dstptr; + grub_uint8_t fill = (grub_uint8_t)color & 0xFF; + + /* Calculate the number of bytes to advance from the end of one line + to the beginning of the next line. */ + rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; + + /* Get the start address. */ + dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + *dstptr++ = fill; + + /* Advance the dest pointer to the right location on the next line. */ + dstptr += rowskip; + } +} diff --git a/video/fb/fbutil.c b/video/fb/fbutil.c new file mode 100644 index 0000000..09cbb12 --- /dev/null +++ b/video/fb/fbutil.c @@ -0,0 +1,177 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007,2009 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 3 of the License, or + * (at your option) any later version. + * + * GRUB 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, see . + */ + +#include +#include +#include + +grub_uint8_t * +get_data_ptr (struct grub_video_fbblit_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; + + case 1: + /* For 1-bit bitmaps, addressing needs to be done at the bit level + and it doesn't make sense, in general, to ask for a pointer + to a particular pixel's data. */ + break; + } + + return ptr; +} + +grub_video_color_t +get_pixel (struct grub_video_fbblit_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; + + case 1: + if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) + { + int bit_index = y * source->mode_info->width + x; + grub_uint8_t *ptr = (grub_uint8_t *)source->data + + bit_index / 8; + int bit_pos = 7 - bit_index % 8; + color = (*ptr >> bit_pos) & 0x01; + } + break; + + default: + break; + } + + return color; +} + +void +set_pixel (struct grub_video_fbblit_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; + + case 1: + if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) + { + int bit_index = y * source->mode_info->width + x; + grub_uint8_t *ptr = (grub_uint8_t *)source->data + + bit_index / 8; + int bit_pos = 7 - bit_index % 8; + *ptr = (*ptr & ~(1 << bit_pos)) | ((color & 0x01) << bit_pos); + } + break; + + default: + break; + } +} diff --git a/video/fb/video_fb.c b/video/fb/video_fb.c new file mode 100644 index 0000000..98f80c3 --- /dev/null +++ b/video/fb/video_fb.c @@ -0,0 +1,1100 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009 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 3 of the License, or + * (at your option) any later version. + * + * GRUB 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct grub_video_fbrender_target *render_target; +struct grub_video_palette_data *palette; +static unsigned int palette_size; + +/* Specify "standard" VGA palette, some video cards may + need this and this will also be used when using RGB modes. */ +struct grub_video_palette_data grub_video_fbstd_colors[16] = + { + // {R, G, B, A} + {0x00, 0x00, 0x00, 0xFF}, // 0 = black + {0x00, 0x00, 0xA8, 0xFF}, // 1 = blue + {0x00, 0xA8, 0x00, 0xFF}, // 2 = green + {0x00, 0xA8, 0xA8, 0xFF}, // 3 = cyan + {0xA8, 0x00, 0x00, 0xFF}, // 4 = red + {0xA8, 0x00, 0xA8, 0xFF}, // 5 = magenta + {0xA8, 0x54, 0x00, 0xFF}, // 6 = brown + {0xA8, 0xA8, 0xA8, 0xFF}, // 7 = light gray + + {0x54, 0x54, 0x54, 0xFF}, // 8 = dark gray + {0x54, 0x54, 0xFE, 0xFF}, // 9 = bright blue + {0x54, 0xFE, 0x54, 0xFF}, // 10 = bright green + {0x54, 0xFE, 0xFE, 0xFF}, // 11 = bright cyan + {0xFE, 0x54, 0x54, 0xFF}, // 12 = bright red + {0xFE, 0x54, 0xFE, 0xFF}, // 13 = bright magenta + {0xFE, 0xFE, 0x54, 0xFF}, // 14 = yellow + {0xFE, 0xFE, 0xFE, 0xFF} // 15 = white + }; + +grub_err_t +grub_video_fb_init (void) +{ + grub_free (palette); + render_target = 0; + palette = 0; + palette_size = 0; + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_fini (void) +{ + grub_free (palette); + render_target = 0; + palette = 0; + palette_size = 0; + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_get_info (struct grub_video_mode_info *mode_info) +{ + /* Copy mode info from active render target. */ + grub_memcpy (mode_info, &render_target->mode_info, + sizeof (struct grub_video_mode_info)); + + return GRUB_ERR_NONE; +} + + +grub_uint8_t * +grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source, + grub_uint32_t x, grub_uint32_t 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_err_t +grub_video_fb_get_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data) +{ + unsigned int i; + + /* Assume that we know everything from index color palette. */ + for (i = 0; (i < count) && ((i + start) < palette_size); i++) + palette_data[i] = palette[start + i]; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_set_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data) +{ + unsigned i; + if (start + count > palette_size) + { + palette_size = start + count; + palette = grub_realloc (palette, sizeof (palette[0]) * palette_size); + if (!palette) + { + grub_video_fb_fini (); + return grub_errno; + } + } + for (i = 0; (i < count) && ((i + start) < palette_size); i++) + palette[start + i] = palette_data[i]; + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_set_viewport (unsigned int x, unsigned int y, + unsigned int width, unsigned int height) +{ + render_target->viewport.x = x; + render_target->viewport.y = y; + render_target->viewport.width = width; + render_target->viewport.height = height; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_get_viewport (unsigned int *x, unsigned int *y, + unsigned int *width, unsigned int *height) +{ + if (x) *x = render_target->viewport.x; + if (y) *y = render_target->viewport.y; + if (width) *width = render_target->viewport.width; + if (height) *height = render_target->viewport.height; + + return GRUB_ERR_NONE; +} + +/* Maps color name to target optimized color format. */ +grub_video_color_t +grub_video_fb_map_color (grub_uint32_t color_name) +{ + /* TODO: implement color theme mapping code. */ + + if (color_name < palette_size) + { + if ((render_target->mode_info.mode_type + & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) + return color_name; + else + { + grub_video_color_t color; + + color = grub_video_fb_map_rgb (palette[color_name].r, + palette[color_name].g, + palette[color_name].b); + + return color; + } + } + + return 0; +} + +/* Maps RGB to target optimized color format. */ +grub_video_color_t +grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green, + grub_uint8_t blue) +{ + if ((render_target->mode_info.mode_type + & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) + { + int minindex = 0; + int delta = 0; + int tmp; + int val; + unsigned i; + + /* Find best matching color. */ + for (i = 0; i < palette_size; i++) + { + val = palette[i].r - red; + tmp = val * val; + val = palette[i].g - green; + tmp += val * val; + val = palette[i].b - blue; + tmp += val * val; + + if (i == 0) + delta = tmp; + + if (tmp < delta) + { + delta = tmp; + minindex = i; + if (tmp == 0) + break; + } + } + + return minindex; + } + else if ((render_target->mode_info.mode_type + & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0) + { + if (red == render_target->mode_info.fg_red + && green == render_target->mode_info.fg_green + && blue == render_target->mode_info.fg_blue) + return 1; + else + return 0; + } + else + { + grub_uint32_t value; + grub_uint8_t alpha = 255; /* Opaque color. */ + + red >>= 8 - render_target->mode_info.red_mask_size; + green >>= 8 - render_target->mode_info.green_mask_size; + blue >>= 8 - render_target->mode_info.blue_mask_size; + alpha >>= 8 - render_target->mode_info.reserved_mask_size; + + value = red << render_target->mode_info.red_field_pos; + value |= green << render_target->mode_info.green_field_pos; + value |= blue << render_target->mode_info.blue_field_pos; + value |= alpha << render_target->mode_info.reserved_field_pos; + + return value; + } + +} + +/* Maps RGBA to target optimized color format. */ +grub_video_color_t +grub_video_fb_map_rgba (grub_uint8_t red, grub_uint8_t green, + grub_uint8_t blue, grub_uint8_t alpha) +{ + if ((render_target->mode_info.mode_type + & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) + /* No alpha available in index color modes, just use + same value as in only RGB modes. */ + return grub_video_fb_map_rgb (red, green, blue); + else if ((render_target->mode_info.mode_type + & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0) + { + if (red == render_target->mode_info.fg_red + && green == render_target->mode_info.fg_green + && blue == render_target->mode_info.fg_blue + && alpha == render_target->mode_info.fg_alpha) + return 1; + else + return 0; + } + else + { + grub_uint32_t value; + + red >>= 8 - render_target->mode_info.red_mask_size; + green >>= 8 - render_target->mode_info.green_mask_size; + blue >>= 8 - render_target->mode_info.blue_mask_size; + alpha >>= 8 - render_target->mode_info.reserved_mask_size; + + value = red << render_target->mode_info.red_field_pos; + value |= green << render_target->mode_info.green_field_pos; + value |= blue << render_target->mode_info.blue_field_pos; + value |= alpha << render_target->mode_info.reserved_field_pos; + + return value; + } +} + +/* Splits target optimized format to components. */ +grub_err_t +grub_video_fb_unmap_color (grub_video_color_t color, + grub_uint8_t *red, grub_uint8_t *green, + grub_uint8_t *blue, grub_uint8_t *alpha) +{ + struct grub_video_fbblit_info target_info; + + target_info.mode_info = &render_target->mode_info; + target_info.data = render_target->data; + + grub_video_fb_unmap_color_int (&target_info, color, red, green, blue, alpha); + + return GRUB_ERR_NONE; +} + +/* Splits color in source format to components. */ +void +grub_video_fb_unmap_color_int (struct grub_video_fbblit_info * source, + grub_video_color_t color, + grub_uint8_t *red, grub_uint8_t *green, + grub_uint8_t *blue, grub_uint8_t *alpha) +{ + 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 an out-of-bounds color, return transparent black. */ + if (color > 255) + { + *red = 0; + *green = 0; + *blue = 0; + *alpha = 0; + return; + } + + *red = palette[color].r; + *green = palette[color].g; + *blue = palette[color].b; + *alpha = palette[color].a; + return; + } + else if ((mode_info->mode_type + & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0) + { + if (color & 1) + { + *red = mode_info->fg_red; + *green = mode_info->fg_green; + *blue = mode_info->fg_blue; + *alpha = mode_info->fg_alpha; + } + else + { + *red = mode_info->bg_red; + *green = mode_info->bg_green; + *blue = mode_info->bg_blue; + *alpha = mode_info->bg_alpha; + } + } + else + { + grub_uint32_t tmp; + + /* Get red component. */ + 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 >> 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 >> 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) + { + 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. */ + tmp = 255; + + *alpha = tmp & 0xFF; + } +} + +grub_err_t +grub_video_fb_fill_rect (grub_video_color_t color, int x, int y, + unsigned int width, unsigned int height) +{ + struct grub_video_fbblit_info target; + + /* 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 (x < 0) + { + width += x; + x = 0; + } + if (y < 0) + { + height += 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; + + /* Add viewport offset. */ + x += render_target->viewport.x; + y += render_target->viewport.y; + + /* Use fbblit_info to encapsulate rendering. */ + target.mode_info = &render_target->mode_info; + target.data = render_target->data; + + /* Try to figure out more optimized version. Note that color is already + mapped to target format so we can make assumptions based on that. */ + if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + { + grub_video_fbfill_direct32 (&target, color, x, y, + width, height); + return GRUB_ERR_NONE; + } + else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) + { + grub_video_fbfill_direct32 (&target, color, x, y, + width, height); + return GRUB_ERR_NONE; + } + else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) + { + grub_video_fbfill_direct24 (&target, color, x, y, + width, height); + return GRUB_ERR_NONE; + } + else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_565) + { + grub_video_fbfill_direct16 (&target, color, x, y, + width, height); + return GRUB_ERR_NONE; + } + else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_565) + { + grub_video_fbfill_direct16 (&target, color, x, y, + width, height); + return GRUB_ERR_NONE; + } + else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + grub_video_fbfill_direct8 (&target, color, x, y, + width, height); + return GRUB_ERR_NONE; + } + + /* No optimized version found, use default (slow) filler. */ + grub_video_fbfill (&target, color, x, y, width, height); + + return GRUB_ERR_NONE; +} + +/* NOTE: This function assumes that given coordinates are within bounds of + handled data. */ +static void +common_blitter (struct grub_video_fbblit_info *target, + struct grub_video_fbblit_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_RGBA_8888) + { + if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) + { + grub_video_fbblit_replace_directN (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + { + grub_video_fbblit_replace_BGRX8888_RGBX8888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888) + { + grub_video_fbblit_replace_BGR888_RGBX8888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) + { + grub_video_fbblit_replace_RGB888_RGBX8888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + grub_video_fbblit_replace_index_RGBX8888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + } + else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) + { + if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + { + grub_video_fbblit_replace_BGRX8888_RGB888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) + { + grub_video_fbblit_replace_RGBX8888_RGB888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888) + { + grub_video_fbblit_replace_BGR888_RGB888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) + { + grub_video_fbblit_replace_directN (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + grub_video_fbblit_replace_index_RGB888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + } + else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + { + if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + { + grub_video_fbblit_replace_directN (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + } + else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + grub_video_fbblit_replace_directN (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + } + + /* No optimized replace operator found, use default (slow) blitter. */ + grub_video_fbblit_replace (target, source, x, y, width, height, + offset_x, offset_y); + } + else + { + /* Try to figure out more optimized blend operator. */ + if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) + { + if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + { + grub_video_fbblit_blend_BGRA8888_RGBA8888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) + { + grub_video_fbblit_blend_RGBA8888_RGBA8888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888) + { + grub_video_fbblit_blend_BGR888_RGBA8888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) + { + grub_video_fbblit_blend_RGB888_RGBA8888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + grub_video_fbblit_blend_index_RGBA8888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + } + else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) + { + /* Note: There is really no alpha information here, so blend is + changed to replace. */ + + if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) + { + grub_video_fbblit_replace_BGRX8888_RGB888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) + { + grub_video_fbblit_replace_RGBX8888_RGB888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888) + { + grub_video_fbblit_replace_BGR888_RGB888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) + { + grub_video_fbblit_replace_directN (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) + { + grub_video_fbblit_replace_index_RGB888 (target, source, + x, y, width, height, + offset_x, offset_y); + return; + } + } + + /* No optimized blend operation found, use default (slow) blitter. */ + grub_video_fbblit_blend (target, source, x, y, width, height, + offset_x, offset_y); + } +} + +grub_err_t +grub_video_fb_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) +{ + struct grub_video_fbblit_info source; + struct grub_video_fbblit_info target; + + /* 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)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)bitmap->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; + } + + /* 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 fbblit_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; +} + +grub_err_t +grub_video_fb_blit_render_target (struct grub_video_fbrender_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_fbblit_info source_info; + struct grub_video_fbblit_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; + } + + /* 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) > source->mode_info.width) + width = source->mode_info.width - offset_x; + if ((offset_y + height) > source->mode_info.height) + height = source->mode_info.height - offset_y; + + /* Limit drawing to source render target dimensions. */ + if (width > source->mode_info.width) + width = source->mode_info.width; + + if (height > source->mode_info.height) + height = source->mode_info.height; + + /* Add viewport offset. */ + x += render_target->viewport.x; + y += render_target->viewport.y; + + /* Use fbblit_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; + + /* Do actual blitting. */ + common_blitter (&target_info, &source_info, oper, x, y, width, height, + offset_x, offset_y); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_scroll (grub_video_color_t color, int dx, int dy) +{ + int width; + int height; + int src_x; + int src_y; + int dst_x; + int dst_y; + + /* 1. Check if we have something to do. */ + if ((dx == 0) && (dy == 0)) + return GRUB_ERR_NONE; + + width = render_target->viewport.width - grub_abs (dx); + height = render_target->viewport.height - grub_abs (dy); + + if (dx < 0) + { + src_x = render_target->viewport.x - dx; + dst_x = render_target->viewport.x; + } + else + { + src_x = render_target->viewport.x; + dst_x = render_target->viewport.x + dx; + } + + if (dy < 0) + { + src_y = render_target->viewport.y - dy; + dst_y = render_target->viewport.y; + } + else + { + src_y = render_target->viewport.y; + dst_y = render_target->viewport.y + dy; + } + + /* 2. Check if there is need to copy data. */ + if ((grub_abs (dx) < render_target->viewport.width) + && (grub_abs (dy) < render_target->viewport.height)) + { + /* 3. Move data in render target. */ + struct grub_video_fbblit_info target; + grub_uint8_t *src; + grub_uint8_t *dst; + int j; + + target.mode_info = &render_target->mode_info; + target.data = render_target->data; + + /* Check vertical direction of the move. */ + if (dy <= 0) + /* 3a. Move data upwards. */ + for (j = 0; j < height; j++) + { + dst = grub_video_fb_get_video_ptr (&target, dst_x, dst_y + j); + src = grub_video_fb_get_video_ptr (&target, src_x, src_y + j); + grub_memmove (dst, src, + width * target.mode_info->bytes_per_pixel); + } + else + /* 3b. Move data downwards. */ + for (j = (height - 1); j >= 0; j--) + { + dst = grub_video_fb_get_video_ptr (&target, dst_x, dst_y + j); + src = grub_video_fb_get_video_ptr (&target, src_x, src_y + j); + grub_memmove (dst, src, + width * target.mode_info->bytes_per_pixel); + } + } + + /* 4. Fill empty space with specified color. In this implementation + there might be colliding areas but at the moment there is no need + to optimize this. */ + + /* 4a. Fill top & bottom parts. */ + if (dy > 0) + grub_video_fb_fill_rect (color, 0, 0, render_target->viewport.width, dy); + else if (dy < 0) + { + if (render_target->viewport.height < grub_abs (dy)) + dy = -render_target->viewport.height; + + grub_video_fb_fill_rect (color, 0, render_target->viewport.height + dy, + render_target->viewport.width, -dy); + } + + /* 4b. Fill left & right parts. */ + if (dx > 0) + grub_video_fb_fill_rect (color, 0, 0, + dx, render_target->viewport.height); + else if (dx < 0) + { + if (render_target->viewport.width < grub_abs (dx)) + dx = -render_target->viewport.width; + + grub_video_fb_fill_rect (color, render_target->viewport.width + dx, 0, + -dx, render_target->viewport.height); + } + + return GRUB_ERR_NONE; +} + + +grub_err_t +grub_video_fb_create_render_target (struct grub_video_fbrender_target **result, + unsigned int width, unsigned int height, + unsigned int mode_type __attribute__ ((unused))) +{ + struct grub_video_fbrender_target *target; + unsigned int size; + + /* Validate arguments. */ + if ((! result) + || (width == 0) + || (height == 0)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "invalid argument given."); + + /* Allocate memory for render target. */ + target = grub_malloc (sizeof (struct grub_video_fbrender_target)); + if (! target) + return grub_errno; + + /* TODO: Implement other types too. + Currently only 32bit render targets are supported. */ + + /* Mark render target as allocated. */ + target->is_allocated = 1; + + /* Maximize viewport. */ + target->viewport.x = 0; + target->viewport.y = 0; + target->viewport.width = width; + target->viewport.height = height; + + /* Setup render target format. */ + target->mode_info.width = width; + target->mode_info.height = height; + target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB + | GRUB_VIDEO_MODE_TYPE_ALPHA; + target->mode_info.bpp = 32; + target->mode_info.bytes_per_pixel = 4; + target->mode_info.pitch = target->mode_info.bytes_per_pixel * width; + target->mode_info.number_of_colors = palette_size; /* Emulated palette. */ + target->mode_info.red_mask_size = 8; + target->mode_info.red_field_pos = 0; + target->mode_info.green_mask_size = 8; + target->mode_info.green_field_pos = 8; + target->mode_info.blue_mask_size = 8; + target->mode_info.blue_field_pos = 16; + target->mode_info.reserved_mask_size = 8; + target->mode_info.reserved_field_pos = 24; + + target->mode_info.blit_format = grub_video_get_blit_format (&target->mode_info); + + /* Calculate size needed for the data. */ + size = (width * target->mode_info.bytes_per_pixel) * height; + + target->data = grub_malloc (size); + if (! target->data) + { + grub_free (target); + return grub_errno; + } + + /* Clear render target with black and maximum transparency. */ + grub_memset (target->data, 0, size); + + /* TODO: Add render target to render target list. */ + + /* Save result to caller. */ + *result = target; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_delete_render_target (struct grub_video_fbrender_target *target) +{ + /* If there is no target, then just return without error. */ + if (! target) + return GRUB_ERR_NONE; + + /* TODO: Delist render target from render target list. */ + + /* If this is software render target, free it's memory. */ + if (target->is_allocated) + grub_free (target->data); + + /* Free render target. */ + grub_free (target); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *target) +{ + if (! target->data) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "invalid render target given."); + + render_target = target; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **target) +{ + *target = render_target; + + return GRUB_ERR_NONE; +} diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c index ae08402..19cfaf5 100644 --- a/video/i386/pc/vbe.c +++ b/video/i386/pc/vbe.c @@ -16,43 +16,17 @@ * along with GRUB. If not, see . */ +#define grub_video_render_target grub_video_fbrender_target + #include #include #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. */ -static struct grub_vbe_palette_data vga_colors[16] = - { - // {B, G, R, A} - {0x00, 0x00, 0x00, 0x00}, // 0 = black - {0xA8, 0x00, 0x00, 0x00}, // 1 = blue - {0x00, 0xA8, 0x00, 0x00}, // 2 = green - {0xA8, 0xA8, 0x00, 0x00}, // 3 = cyan - {0x00, 0x00, 0xA8, 0x00}, // 4 = red - {0xA8, 0x00, 0xA8, 0x00}, // 5 = magenta - {0x00, 0x54, 0xA8, 0x00}, // 6 = brown - {0xA8, 0xA8, 0xA8, 0x00}, // 7 = light gray - - {0x54, 0x54, 0x54, 0x00}, // 8 = dark gray - {0xFE, 0x54, 0x54, 0x00}, // 9 = bright blue - {0x54, 0xFE, 0x54, 0x00}, // 10 = bright green - {0xFE, 0xFE, 0x54, 0x00}, // 11 = bright cyan - {0x54, 0x54, 0xFE, 0x00}, // 12 = bright red - {0xFE, 0x54, 0xFE, 0x00}, // 13 = bright magenta - {0x54, 0xFE, 0xFE, 0x00}, // 14 = yellow - {0xFE, 0xFE, 0xFE, 0x00} // 15 = white - }; static int vbe_detected = -1; @@ -68,10 +42,8 @@ static struct grub_uint32_t active_mode; grub_uint8_t *ptr; int index_color_mode; - struct grub_video_palette_data palette[256]; } framebuffer; -static struct grub_video_render_target *render_target; static grub_uint32_t initial_mode; static grub_uint32_t mode_in_use = 0x55aa; static grub_uint16_t *mode_list; @@ -239,11 +211,20 @@ grub_vbe_set_video_mode (grub_uint32_t mode, { struct grub_vbe_palette_data *palette = (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + unsigned i; - /* Make sure that the BIOS can reach the palette. */ - grub_memcpy (palette, vga_colors, sizeof (vga_colors)); - status = grub_vbe_bios_set_palette_data (sizeof (vga_colors) - / sizeof (struct grub_vbe_palette_data), + /* Make sure that the BIOS can reach the palette. */ + for (i = 0; i < sizeof (grub_video_fbstd_colors) + / sizeof (grub_video_fbstd_colors[0]); i++) + { + palette[i].red = grub_video_fbstd_colors[i].r; + palette[i].green = grub_video_fbstd_colors[i].g; + palette[i].blue = grub_video_fbstd_colors[i].b; + palette[i].alignment = 0; + } + + status = grub_vbe_bios_set_palette_data (sizeof (grub_video_fbstd_colors) + / sizeof (grub_video_fbstd_colors[0]), 0, palette); @@ -308,43 +289,6 @@ grub_vbe_get_video_mode_info (grub_uint32_t mode, return GRUB_ERR_NONE; } -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_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; -} - static grub_err_t grub_video_vbe_init (void) { @@ -387,9 +331,7 @@ grub_video_vbe_init (void) /* Reset frame buffer and render target variables. */ grub_memset (&framebuffer, 0, sizeof(framebuffer)); - render_target = &framebuffer.render_target; - - return GRUB_ERR_NONE; + return grub_video_fb_init (); } static grub_err_t @@ -409,8 +351,7 @@ grub_video_vbe_fini (void) /* TODO: destroy render targets. */ - /* Return success to caller. */ - return GRUB_ERR_NONE; + return grub_video_fb_fini (); } static grub_err_t @@ -422,7 +363,6 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, struct grub_vbe_mode_info_block best_mode_info; grub_uint32_t best_mode = 0; int depth; - unsigned int i; /* Decode depth from mode_type. If it is zero, then autodetect. */ depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) @@ -512,54 +452,63 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, in order to fasten later operations. */ mode_in_use = best_mode; - /* Reset render target to framebuffer one. */ - render_target = &framebuffer.render_target; - /* Fill mode info details in framebuffer's render target. */ - render_target->mode_info.width = active_mode_info.x_resolution; - render_target->mode_info.height = active_mode_info.y_resolution; + framebuffer.render_target.mode_info.width + = active_mode_info.x_resolution; + framebuffer.render_target.mode_info.height + = active_mode_info.y_resolution; if (framebuffer.index_color_mode) - render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + framebuffer.render_target.mode_info.mode_type + = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; else - render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; - - render_target->mode_info.bpp = active_mode_info.bits_per_pixel; - render_target->mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel; - render_target->mode_info.pitch = framebuffer.bytes_per_scan_line; - render_target->mode_info.number_of_colors = 256; /* TODO: fix me. */ - render_target->mode_info.red_mask_size = active_mode_info.red_mask_size; - render_target->mode_info.red_field_pos = active_mode_info.red_field_position; - render_target->mode_info.green_mask_size = active_mode_info.green_mask_size; - render_target->mode_info.green_field_pos = active_mode_info.green_field_position; - render_target->mode_info.blue_mask_size = active_mode_info.blue_mask_size; - render_target->mode_info.blue_field_pos = active_mode_info.blue_field_position; - render_target->mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size; - render_target->mode_info.reserved_field_pos = active_mode_info.rsvd_field_position; - - render_target->mode_info.blit_format = grub_video_get_blit_format (&render_target->mode_info); + framebuffer.render_target.mode_info.mode_type + = GRUB_VIDEO_MODE_TYPE_RGB; + + framebuffer.render_target.mode_info.bpp = active_mode_info.bits_per_pixel; + framebuffer.render_target.mode_info.bytes_per_pixel + = framebuffer.bytes_per_pixel; + framebuffer.render_target.mode_info.pitch + = framebuffer.bytes_per_scan_line; + framebuffer.render_target.mode_info.number_of_colors + = 256; /* TODO: fix me. */ + framebuffer.render_target.mode_info.red_mask_size + = active_mode_info.red_mask_size; + framebuffer.render_target.mode_info.red_field_pos + = active_mode_info.red_field_position; + framebuffer.render_target.mode_info.green_mask_size + = active_mode_info.green_mask_size; + framebuffer.render_target.mode_info.green_field_pos + = active_mode_info.green_field_position; + framebuffer.render_target.mode_info.blue_mask_size + = active_mode_info.blue_mask_size; + framebuffer.render_target.mode_info.blue_field_pos + = active_mode_info.blue_field_position; + framebuffer.render_target.mode_info.reserved_mask_size + = active_mode_info.rsvd_mask_size; + framebuffer.render_target.mode_info.reserved_field_pos + = active_mode_info.rsvd_field_position; + + framebuffer.render_target.mode_info.blit_format + = grub_video_get_blit_format (&framebuffer.render_target.mode_info); /* Reset viewport to match new mode. */ - render_target->viewport.x = 0; - render_target->viewport.y = 0; - render_target->viewport.width = active_mode_info.x_resolution; - render_target->viewport.height = active_mode_info.y_resolution; + framebuffer.render_target.viewport.x = 0; + framebuffer.render_target.viewport.y = 0; + framebuffer.render_target.viewport.width = active_mode_info.x_resolution; + framebuffer.render_target.viewport.height = active_mode_info.y_resolution; /* Set framebuffer pointer and mark it as non allocated. */ - render_target->is_allocated = 0; - render_target->data = framebuffer.ptr; + framebuffer.render_target.is_allocated = 0; + framebuffer.render_target.data = framebuffer.ptr; /* Copy default palette to initialize emulated palette. */ - for (i = 0; - i < (sizeof (vga_colors) - / sizeof (struct grub_vbe_palette_data)); - i++) - { - framebuffer.palette[i].r = vga_colors[i].red; - framebuffer.palette[i].g = vga_colors[i].green; - framebuffer.palette[i].b = vga_colors[i].blue; - framebuffer.palette[i].a = 0xFF; - } + grub_video_fb_set_palette (0, (sizeof (grub_video_fbstd_colors) + / sizeof (grub_video_fbstd_colors[0])), + grub_video_fbstd_colors); + + /* Reset render target to framebuffer one. */ + grub_video_fb_set_active_render_target (&framebuffer.render_target); return GRUB_ERR_NONE; } @@ -569,21 +518,9 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, } static grub_err_t -grub_video_vbe_get_info (struct grub_video_mode_info *mode_info) -{ - /* Copy mode info from active render target. */ - grub_memcpy (mode_info, &render_target->mode_info, - sizeof (struct grub_video_mode_info)); - - return GRUB_ERR_NONE; -} - -static grub_err_t grub_video_vbe_set_palette (unsigned int start, unsigned int count, struct grub_video_palette_data *palette_data) { - unsigned int i; - if (framebuffer.index_color_mode) { /* TODO: Implement setting indexed color mode palette to hardware. */ @@ -595,28 +532,13 @@ grub_video_vbe_set_palette (unsigned int start, unsigned int count, } /* Then set color to emulated palette. */ - for (i = 0; (i < count) && ((i + start) < 256); i++) - framebuffer.palette[start + i] = palette_data[i]; - - return GRUB_ERR_NONE; -} -static grub_err_t -grub_video_vbe_get_palette (unsigned int start, unsigned int count, - struct grub_video_palette_data *palette_data) -{ - unsigned int i; - - /* Assume that we know everything from index color palette. */ - for (i = 0; (i < count) && ((i + start) < 256); i++) - palette_data[i] = framebuffer.palette[start + i]; - - return GRUB_ERR_NONE; + return grub_video_fb_set_palette (start, count, palette_data); } -static grub_err_t +grub_err_t grub_video_vbe_set_viewport (unsigned int x, unsigned int y, - unsigned int width, unsigned int height) + unsigned int width, unsigned int height) { /* Make sure viewport is withing screen dimensions. If viewport was set to be out of the region, mark its size as zero. */ @@ -637,832 +559,7 @@ grub_video_vbe_set_viewport (unsigned int x, unsigned int y, if (y + height > active_mode_info.y_resolution) height = active_mode_info.y_resolution - y; - - render_target->viewport.x = x; - render_target->viewport.y = y; - render_target->viewport.width = width; - render_target->viewport.height = height; - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_video_vbe_get_viewport (unsigned int *x, unsigned int *y, - unsigned int *width, unsigned int *height) -{ - if (x) *x = render_target->viewport.x; - if (y) *y = render_target->viewport.y; - if (width) *width = render_target->viewport.width; - if (height) *height = render_target->viewport.height; - - return GRUB_ERR_NONE; -} - -/* Maps color name to target optimized color format. */ -static grub_video_color_t -grub_video_vbe_map_color (grub_uint32_t color_name) -{ - /* TODO: implement color theme mapping code. */ - - if (color_name < 256) - { - if ((render_target->mode_info.mode_type - & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) - return color_name; - else - { - grub_video_color_t color; - - color = grub_video_vbe_map_rgb (framebuffer.palette[color_name].r, - framebuffer.palette[color_name].g, - framebuffer.palette[color_name].b); - - return color; - } - } - - return 0; -} - -/* Maps RGB to target optimized color format. */ -grub_video_color_t -grub_video_vbe_map_rgb (grub_uint8_t red, grub_uint8_t green, - grub_uint8_t blue) -{ - if ((render_target->mode_info.mode_type - & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) - { - int minindex = 0; - int delta = 0; - int tmp; - int val; - int i; - - /* Find best matching color. */ - for (i = 0; i < 256; i++) - { - val = framebuffer.palette[i].r - red; - tmp = val * val; - val = framebuffer.palette[i].g - green; - tmp += val * val; - val = framebuffer.palette[i].b - blue; - tmp += val * val; - - if (i == 0) - delta = tmp; - - if (tmp < delta) - { - delta = tmp; - minindex = i; - if (tmp == 0) - break; - } - } - - return minindex; - } - else if ((render_target->mode_info.mode_type - & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0) - { - if (red == render_target->mode_info.fg_red - && green == render_target->mode_info.fg_green - && blue == render_target->mode_info.fg_blue) - return 1; - else - return 0; - } - else - { - grub_uint32_t value; - grub_uint8_t alpha = 255; /* Opaque color. */ - - red >>= 8 - render_target->mode_info.red_mask_size; - green >>= 8 - render_target->mode_info.green_mask_size; - blue >>= 8 - render_target->mode_info.blue_mask_size; - alpha >>= 8 - render_target->mode_info.reserved_mask_size; - - value = red << render_target->mode_info.red_field_pos; - value |= green << render_target->mode_info.green_field_pos; - value |= blue << render_target->mode_info.blue_field_pos; - value |= alpha << render_target->mode_info.reserved_field_pos; - - return value; - } - -} - -/* Maps RGBA to target optimized color format. */ -grub_video_color_t -grub_video_vbe_map_rgba (grub_uint8_t red, grub_uint8_t green, - grub_uint8_t blue, grub_uint8_t alpha) -{ - if ((render_target->mode_info.mode_type - & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) - /* No alpha available in index color modes, just use - same value as in only RGB modes. */ - return grub_video_vbe_map_rgb (red, green, blue); - else if ((render_target->mode_info.mode_type - & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0) - { - if (red == render_target->mode_info.fg_red - && green == render_target->mode_info.fg_green - && blue == render_target->mode_info.fg_blue - && alpha == render_target->mode_info.fg_alpha) - return 1; - else - return 0; - } - else - { - grub_uint32_t value; - - red >>= 8 - render_target->mode_info.red_mask_size; - green >>= 8 - render_target->mode_info.green_mask_size; - blue >>= 8 - render_target->mode_info.blue_mask_size; - alpha >>= 8 - render_target->mode_info.reserved_mask_size; - - value = red << render_target->mode_info.red_field_pos; - value |= green << render_target->mode_info.green_field_pos; - value |= blue << render_target->mode_info.blue_field_pos; - value |= alpha << render_target->mode_info.reserved_field_pos; - - return value; - } -} - -/* Splits target optimized format to components. */ -grub_err_t grub_video_vbe_unmap_color (grub_video_color_t color, - grub_uint8_t *red, grub_uint8_t *green, - grub_uint8_t *blue, grub_uint8_t *alpha) -{ - struct grub_video_i386_vbeblit_info target_info; - - target_info.mode_info = &render_target->mode_info; - target_info.data = render_target->data; - - grub_video_vbe_unmap_color_int (&target_info, color, red, green, blue, alpha); - - return GRUB_ERR_NONE; -} - -/* Splits color in source format to components. */ -void -grub_video_vbe_unmap_color_int (struct grub_video_i386_vbeblit_info * source, - grub_video_color_t color, - grub_uint8_t *red, grub_uint8_t *green, - grub_uint8_t *blue, grub_uint8_t *alpha) -{ - 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 an out-of-bounds color, return transparent black. */ - if (color > 255) - { - *red = 0; - *green = 0; - *blue = 0; - *alpha = 0; - return; - } - - *red = framebuffer.palette[color].r; - *green = framebuffer.palette[color].g; - *blue = framebuffer.palette[color].b; - *alpha = framebuffer.palette[color].a; - return; - } - else if ((mode_info->mode_type - & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0) - { - if (color & 1) - { - *red = mode_info->fg_red; - *green = mode_info->fg_green; - *blue = mode_info->fg_blue; - *alpha = mode_info->fg_alpha; - } - else - { - *red = mode_info->bg_red; - *green = mode_info->bg_green; - *blue = mode_info->bg_blue; - *alpha = mode_info->bg_alpha; - } - } - else - { - grub_uint32_t tmp; - - /* Get red component. */ - 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 >> 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 >> 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) - { - 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. */ - tmp = 255; - - *alpha = tmp & 0xFF; - } -} - -static grub_err_t -grub_video_vbe_fill_rect (grub_video_color_t color, int x, int y, - unsigned int width, unsigned int height) -{ - 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)) - 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 (x < 0) - { - width += x; - x = 0; - } - if (y < 0) - { - height += 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; - - /* Add viewport offset. */ - 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. Note that color is already - mapped to target format so we can make assumptions based on that. */ - if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) - { - grub_video_i386_vbefill_direct32 (&target, color, x, y, - width, height); - return GRUB_ERR_NONE; - } - else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) - { - grub_video_i386_vbefill_direct32 (&target, color, x, y, - width, height); - return GRUB_ERR_NONE; - } - else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { - grub_video_i386_vbefill_direct24 (&target, color, x, y, - width, height); - return GRUB_ERR_NONE; - } - else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_565) - { - grub_video_i386_vbefill_direct16 (&target, color, x, y, - width, height); - return GRUB_ERR_NONE; - } - else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_565) - { - grub_video_i386_vbefill_direct16 (&target, color, x, y, - width, height); - return GRUB_ERR_NONE; - } - else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - grub_video_i386_vbefill_direct8 (&target, color, x, y, - width, height); - return GRUB_ERR_NONE; - } - - /* No optimized version found, use default (slow) filler. */ - grub_video_i386_vbefill (&target, color, x, y, width, height); - - return GRUB_ERR_NONE; -} - -/* NOTE: This function assumes that given coordinates 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_RGBA_8888) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) - { - grub_video_i386_vbeblit_replace_directN (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) - { - grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888) - { - grub_video_i386_vbeblit_replace_BGR888_RGBX8888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { - grub_video_i386_vbeblit_replace_RGB888_RGBX8888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - grub_video_i386_vbeblit_replace_index_RGBX8888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - } - else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) - { - grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) - { - grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888) - { - grub_video_i386_vbeblit_replace_BGR888_RGB888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { - grub_video_i386_vbeblit_replace_directN (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - grub_video_i386_vbeblit_replace_index_RGB888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - } - else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) - { - grub_video_i386_vbeblit_replace_directN (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - } - else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - grub_video_i386_vbeblit_replace_directN (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - } - - /* No optimized replace operator found, use default (slow) blitter. */ - grub_video_i386_vbeblit_replace (target, source, x, y, width, height, - offset_x, offset_y); - } - else - { - /* Try to figure out more optimized blend operator. */ - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) - { - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) - { - grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) - { - grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888) - { - grub_video_i386_vbeblit_blend_BGR888_RGBA8888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { - grub_video_i386_vbeblit_blend_RGB888_RGBA8888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - grub_video_i386_vbeblit_blend_index_RGBA8888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - } - else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { - /* Note: There is really no alpha information here, so blend is - changed to replace. */ - - if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888) - { - grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888) - { - grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888) - { - grub_video_i386_vbeblit_replace_BGR888_RGB888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888) - { - grub_video_i386_vbeblit_replace_directN (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR) - { - grub_video_i386_vbeblit_replace_index_RGB888 (target, source, - x, y, width, height, - offset_x, offset_y); - return; - } - } - - /* No optimized blend operation found, use default (slow) blitter. */ - grub_video_i386_vbeblit_blend (target, source, x, y, width, height, - offset_x, offset_y); - } -} - -static grub_err_t -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) -{ - 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)) - 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)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)bitmap->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; - } - - /* 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; - } - - /* 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) > source->mode_info.width) - width = source->mode_info.width - offset_x; - if ((offset_y + height) > source->mode_info.height) - height = source->mode_info.height - offset_y; - - /* Limit drawing to source render target dimensions. */ - if (width > source->mode_info.width) - width = source->mode_info.width; - - if (height > source->mode_info.height) - height = source->mode_info.height; - - /* Add viewport offset. */ - x += render_target->viewport.x; - y += render_target->viewport.y; - - /* 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; - - /* Do actual blitting. */ - common_blitter (&target_info, &source_info, oper, x, y, width, height, - offset_x, offset_y); - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_video_vbe_scroll (grub_video_color_t color, int dx, int dy) -{ - int width; - int height; - int src_x; - int src_y; - int dst_x; - int dst_y; - - /* 1. Check if we have something to do. */ - if ((dx == 0) && (dy == 0)) - return GRUB_ERR_NONE; - - width = render_target->viewport.width - grub_abs (dx); - height = render_target->viewport.height - grub_abs (dy); - - if (dx < 0) - { - src_x = render_target->viewport.x - dx; - dst_x = render_target->viewport.x; - } - else - { - src_x = render_target->viewport.x; - dst_x = render_target->viewport.x + dx; - } - - if (dy < 0) - { - src_y = render_target->viewport.y - dy; - dst_y = render_target->viewport.y; - } - else - { - src_y = render_target->viewport.y; - dst_y = render_target->viewport.y + dy; - } - - /* 2. Check if there is need to copy data. */ - if ((grub_abs (dx) < render_target->viewport.width) - && (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; - - /* Check vertical direction of the move. */ - if (dy <= 0) - /* 3a. Move data upwards. */ - for (j = 0; j < height; 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 * target.mode_info->bytes_per_pixel); - } - else - /* 3b. Move data downwards. */ - for (j = (height - 1); j >= 0; 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 * target.mode_info->bytes_per_pixel); - } - } - - /* 4. Fill empty space with specified color. In this implementation - there might be colliding areas but at the moment there is no need - to optimize this. */ - - /* 4a. Fill top & bottom parts. */ - if (dy > 0) - grub_video_vbe_fill_rect (color, 0, 0, render_target->viewport.width, dy); - else if (dy < 0) - { - if (render_target->viewport.height < grub_abs (dy)) - dy = -render_target->viewport.height; - - grub_video_vbe_fill_rect (color, 0, render_target->viewport.height + dy, - render_target->viewport.width, -dy); - } - - /* 4b. Fill left & right parts. */ - if (dx > 0) - grub_video_vbe_fill_rect (color, 0, 0, - dx, render_target->viewport.height); - else if (dx < 0) - { - if (render_target->viewport.width < grub_abs (dx)) - dx = -render_target->viewport.width; - - grub_video_vbe_fill_rect (color, render_target->viewport.width + dx, 0, - -dx, render_target->viewport.height); - } - - return GRUB_ERR_NONE; + return grub_video_fb_set_viewport (x, y, width, height); } static grub_err_t @@ -1473,126 +570,16 @@ grub_video_vbe_swap_buffers (void) } static grub_err_t -grub_video_vbe_create_render_target (struct grub_video_render_target **result, - unsigned int width, unsigned int height, - unsigned int mode_type __attribute__ ((unused))) -{ - struct grub_video_render_target *target; - unsigned int size; - - /* Validate arguments. */ - if ((! result) - || (width == 0) - || (height == 0)) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid argument given."); - - /* Allocate memory for render target. */ - target = grub_malloc (sizeof (struct grub_video_render_target)); - if (! target) - return grub_errno; - - /* TODO: Implement other types too. - Currently only 32bit render targets are supported. */ - - /* Mark render target as allocated. */ - target->is_allocated = 1; - - /* Maximize viewport. */ - target->viewport.x = 0; - target->viewport.y = 0; - target->viewport.width = width; - target->viewport.height = height; - - /* Setup render target format. */ - target->mode_info.width = width; - target->mode_info.height = height; - target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB - | GRUB_VIDEO_MODE_TYPE_ALPHA; - target->mode_info.bpp = 32; - target->mode_info.bytes_per_pixel = 4; - target->mode_info.pitch = target->mode_info.bytes_per_pixel * width; - target->mode_info.number_of_colors = 256; /* Emulated palette. */ - target->mode_info.red_mask_size = 8; - target->mode_info.red_field_pos = 0; - target->mode_info.green_mask_size = 8; - target->mode_info.green_field_pos = 8; - target->mode_info.blue_mask_size = 8; - target->mode_info.blue_field_pos = 16; - target->mode_info.reserved_mask_size = 8; - target->mode_info.reserved_field_pos = 24; - - target->mode_info.blit_format = grub_video_get_blit_format (&target->mode_info); - - /* Calculate size needed for the data. */ - size = (width * target->mode_info.bytes_per_pixel) * height; - - target->data = grub_malloc (size); - if (! target->data) - { - grub_free (target); - return grub_errno; - } - - /* Clear render target with black and maximum transparency. */ - grub_memset (target->data, 0, size); - - /* TODO: Add render target to render target list. */ - - /* Save result to caller. */ - *result = target; - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_video_vbe_delete_render_target (struct grub_video_render_target *target) -{ - /* If there is no target, then just return without error. */ - if (! target) - return GRUB_ERR_NONE; - - /* TODO: Delist render target from render target list. */ - - /* If this is software render target, free it's memory. */ - if (target->is_allocated) - grub_free (target->data); - - /* Free render target. */ - grub_free (target); - - return GRUB_ERR_NONE; -} - -static grub_err_t grub_video_vbe_set_active_render_target (struct grub_video_render_target *target) { if (target == GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER) - { - render_target = &framebuffer.render_target; - - return GRUB_ERR_NONE; - } + return grub_video_fb_set_active_render_target (&framebuffer.render_target); if (target == GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "double buffering not implemented yet."); - if (! target->data) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid render target given."); - - render_target = target; - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_video_vbe_get_active_render_target (struct grub_video_render_target **target) -{ - *target = render_target; - - return GRUB_ERR_NONE; + return grub_video_fb_set_active_render_target (target); } static struct grub_video_adapter grub_video_vbe_adapter = @@ -1602,24 +589,24 @@ static struct grub_video_adapter grub_video_vbe_adapter = .init = grub_video_vbe_init, .fini = grub_video_vbe_fini, .setup = grub_video_vbe_setup, - .get_info = grub_video_vbe_get_info, + .get_info = grub_video_fb_get_info, .set_palette = grub_video_vbe_set_palette, - .get_palette = grub_video_vbe_get_palette, - .set_viewport = grub_video_vbe_set_viewport, - .get_viewport = grub_video_vbe_get_viewport, - .map_color = grub_video_vbe_map_color, - .map_rgb = grub_video_vbe_map_rgb, - .map_rgba = grub_video_vbe_map_rgba, - .unmap_color = grub_video_vbe_unmap_color, - .fill_rect = grub_video_vbe_fill_rect, - .blit_bitmap = grub_video_vbe_blit_bitmap, - .blit_render_target = grub_video_vbe_blit_render_target, - .scroll = grub_video_vbe_scroll, + .get_palette = grub_video_fb_get_palette, + .set_viewport = grub_video_fb_set_viewport, + .get_viewport = grub_video_fb_get_viewport, + .map_color = grub_video_fb_map_color, + .map_rgb = grub_video_fb_map_rgb, + .map_rgba = grub_video_fb_map_rgba, + .unmap_color = grub_video_fb_unmap_color, + .fill_rect = grub_video_fb_fill_rect, + .blit_bitmap = grub_video_fb_blit_bitmap, + .blit_render_target = grub_video_fb_blit_render_target, + .scroll = grub_video_fb_scroll, .swap_buffers = grub_video_vbe_swap_buffers, - .create_render_target = grub_video_vbe_create_render_target, - .delete_render_target = grub_video_vbe_delete_render_target, + .create_render_target = grub_video_fb_create_render_target, + .delete_render_target = grub_video_fb_delete_render_target, .set_active_render_target = grub_video_vbe_set_active_render_target, - .get_active_render_target = grub_video_vbe_get_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, .next = 0 }; diff --git a/video/i386/pc/vbeblit.c b/video/i386/pc/vbeblit.c deleted file mode 100644 index 4121bfe..0000000 --- a/video/i386/pc/vbeblit.c +++ /dev/null @@ -1,828 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB 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, see . - */ - -/* 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 - -/* Generic replacing blitter (slow). Works for every supported format. */ -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; - - for (j = 0; j < height; j++) - { - for (i = 0; i < width; i++) - { - src_color = get_pixel (src, i + offset_x, j + offset_y); - - grub_video_vbe_unmap_color_int (src, src_color, &src_red, &src_green, - &src_blue, &src_alpha); - - dst_color = grub_video_vbe_map_rgba (src_red, src_green, - src_blue, src_alpha); - - set_pixel (dst, x + i, y + j, dst_color); - } - } -} - -/* Block copy replacing blitter. Works with modes multiple of 8 bits. */ -void -grub_video_i386_vbeblit_replace_directN (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, int width, int height, - int offset_x, int offset_y) -{ - int j; - grub_uint32_t *srcptr; - grub_uint32_t *dstptr; - int bpp; - - bpp = src->mode_info->bytes_per_pixel; - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j); - - grub_memmove (dstptr, srcptr, width * bpp); - } -} - -/* Optimized replacing blitter for RGBX8888 to BGRX8888. */ -void -grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - int i; - int j; - grub_uint8_t *srcptr; - grub_uint8_t *dstptr; - unsigned int srcrowskip; - unsigned int dstrowskip; - - /* Calculate the number of bytes to advance from the end of one line - to the beginning of the next line. */ - srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; - dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - - srcptr = (grub_uint8_t *) get_data_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); - - for (j = 0; j < height; j++) - { - for (i = 0; i < width; i++) - { - grub_uint8_t r = *srcptr++; - grub_uint8_t g = *srcptr++; - grub_uint8_t b = *srcptr++; - grub_uint8_t a = *srcptr++; - - *dstptr++ = b; - *dstptr++ = g; - *dstptr++ = r; - *dstptr++ = a; - } - - srcptr += srcrowskip; - dstptr += dstrowskip; - } -} - -/* Optimized replacing blitter for RGB888 to BGRX8888. */ -void -grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - int i; - int j; - grub_uint8_t *srcptr; - grub_uint8_t *dstptr; - unsigned int srcrowskip; - unsigned int dstrowskip; - - /* Calculate the number of bytes to advance from the end of one line - to the beginning of the next line. */ - srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; - dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - - srcptr = (grub_uint8_t *) get_data_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); - - for (j = 0; j < height; j++) - { - for (i = 0; i < width; i++) - { - grub_uint8_t r = *srcptr++; - grub_uint8_t g = *srcptr++; - grub_uint8_t b = *srcptr++; - - *dstptr++ = b; - *dstptr++ = g; - *dstptr++ = r; - - /* Set alpha component as opaque. */ - *dstptr++ = 255; - } - - srcptr += srcrowskip; - dstptr += dstrowskip; - } -} - -/* Optimized replacing blitter for RGBX8888 to BGR888. */ -void -grub_video_i386_vbeblit_replace_BGR888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - grub_uint32_t *srcptr; - grub_uint8_t *dstptr; - unsigned int srcrowskip; - unsigned int dstrowskip; - int i; - int j; - - /* Calculate the number of bytes to advance from the end of one line - to the beginning of the next line. */ - srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; - dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - - srcptr = (grub_uint32_t *) get_data_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); - - for (j = 0; j < height; j++) - { - for (i = 0; i < width; i++) - { - grub_uint32_t color; - grub_uint8_t sr; - grub_uint8_t sg; - grub_uint8_t sb; - - color = *srcptr++; - - sr = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sb = (color >> 16) & 0xFF; - - *dstptr++ = sb; - *dstptr++ = sg; - *dstptr++ = sr; - } - - srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); - dstptr += dstrowskip; - } -} - -/* Optimized replacing blitter for RGB888 to BGR888. */ -void -grub_video_i386_vbeblit_replace_BGR888_RGB888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - int i; - int j; - grub_uint8_t *srcptr; - grub_uint8_t *dstptr; - unsigned int srcrowskip; - unsigned int dstrowskip; - - /* Calculate the number of bytes to advance from the end of one line - to the beginning of the next line. */ - srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; - dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - - srcptr = (grub_uint8_t *) get_data_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); - - for (j = 0; j < height; j++) - { - for (i = 0; i < width; i++) - { - grub_uint8_t r = *srcptr++; - grub_uint8_t g = *srcptr++; - grub_uint8_t b = *srcptr++; - - *dstptr++ = b; - *dstptr++ = g; - *dstptr++ = r; - } - - srcptr += srcrowskip; - dstptr += dstrowskip; - } -} - -/* Optimized replacing blitter for RGB888 to RGBX8888. */ -void -grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - grub_uint32_t color; - int i; - int j; - grub_uint8_t *srcptr; - grub_uint32_t *dstptr; - unsigned int sr; - unsigned int sg; - unsigned int sb; - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - { - sr = *srcptr++; - sg = *srcptr++; - sb = *srcptr++; - - /* Set alpha as opaque. */ - color = 0xFF000000 | (sb << 16) | (sg << 8) | sr; - - *dstptr++ = color; - } - } -} - -/* Optimized replacing blitter for RGBX8888 to RGB888. */ -void -grub_video_i386_vbeblit_replace_RGB888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - grub_uint32_t color; - int i; - int j; - grub_uint32_t *srcptr; - grub_uint8_t *dstptr; - unsigned int sr; - unsigned int sg; - unsigned int sb; - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - { - color = *srcptr++; - - sr = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sb = (color >> 16) & 0xFF; - - *dstptr++ = sr; - *dstptr++ = sg; - *dstptr++ = sb; - } - } -} - -/* Optimized replacing blitter for RGBX8888 to indexed color. */ -void -grub_video_i386_vbeblit_replace_index_RGBX8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - grub_uint32_t color; - int i; - int j; - grub_uint32_t *srcptr; - grub_uint8_t *dstptr; - unsigned int sr; - unsigned int sg; - unsigned int sb; - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - { - color = *srcptr++; - - sr = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sb = (color >> 16) & 0xFF; - - color = grub_video_vbe_map_rgb(sr, sg, sb); - *dstptr++ = color & 0xFF; - } - } -} - -/* Optimized replacing blitter for RGB888 to indexed color. */ -void -grub_video_i386_vbeblit_replace_index_RGB888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - grub_uint32_t color; - int i; - int j; - grub_uint8_t *srcptr; - grub_uint8_t *dstptr; - unsigned int sr; - unsigned int sg; - unsigned int sb; - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - { - sr = *srcptr++; - sg = *srcptr++; - sb = *srcptr++; - - color = grub_video_vbe_map_rgb(sr, sg, sb); - - *dstptr++ = color & 0xFF; - } - } -} - -/* Generic blending blitter. Works for every supported format. */ -void -grub_video_i386_vbeblit_blend (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, int width, int height, - int offset_x, int offset_y) -{ - int i; - int j; - - 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_int (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_int (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); - } - } -} - -/* Optimized blending blitter for RGBA8888 to BGRA8888. */ -void -grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - grub_uint32_t *srcptr; - grub_uint32_t *dstptr; - unsigned int srcrowskip; - unsigned int dstrowskip; - int i; - int j; - - /* Calculate the number of bytes to advance from the end of one line - to the beginning of the next line. */ - srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; - dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - - srcptr = (grub_uint32_t *) get_data_ptr (src, offset_x, offset_y); - dstptr = (grub_uint32_t *) get_data_ptr (dst, x, y); - - for (j = 0; j < height; j++) - { - for (i = 0; i < width; i++) - { - grub_uint32_t color; - unsigned int sr; - unsigned int sg; - unsigned int sb; - unsigned int a; - unsigned int dr; - unsigned int dg; - unsigned int db; - - color = *srcptr++; - - a = color >> 24; - - if (a == 0) - { - /* Skip transparent source pixels. */ - dstptr++; - continue; - } - - sr = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sb = (color >> 16) & 0xFF; - - if (a == 255) - { - /* Opaque pixel shortcut. */ - dr = sr; - dg = sg; - db = sb; - } - else - { - /* General pixel color blending. */ - color = *dstptr; - - dr = (color >> 16) & 0xFF; - dr = (dr * (255 - a) + sr * a) / 255; - dg = (color >> 8) & 0xFF; - dg = (dg * (255 - a) + sg * a) / 255; - db = (color >> 0) & 0xFF; - db = (db * (255 - a) + sb * a) / 255; - } - - color = (a << 24) | (dr << 16) | (dg << 8) | db; - - *dstptr++ = color; - } - - srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); - dstptr = (grub_uint32_t *) (((grub_uint8_t *) dstptr) + dstrowskip); - } -} - -/* Optimized blending blitter for RGBA8888 to BGR888. */ -void -grub_video_i386_vbeblit_blend_BGR888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - grub_uint32_t *srcptr; - grub_uint8_t *dstptr; - unsigned int srcrowskip; - unsigned int dstrowskip; - int i; - int j; - - /* Calculate the number of bytes to advance from the end of one line - to the beginning of the next line. */ - srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; - dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - - srcptr = (grub_uint32_t *) get_data_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y); - - for (j = 0; j < height; j++) - { - for (i = 0; i < width; i++) - { - grub_uint32_t color; - unsigned int sr; - unsigned int sg; - unsigned int sb; - unsigned int a; - unsigned int dr; - unsigned int dg; - unsigned int db; - - color = *srcptr++; - - a = color >> 24; - - if (a == 0) - { - /* Skip transparent source pixels. */ - dstptr += 3; - continue; - } - - sr = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sb = (color >> 16) & 0xFF; - - if (a == 255) - { - /* Opaque pixel shortcut. */ - dr = sr; - dg = sg; - db = sb; - } - else - { - /* General pixel color blending. */ - color = *dstptr; - - db = dstptr[0]; - db = (db * (255 - a) + sb * a) / 255; - dg = dstptr[1]; - dg = (dg * (255 - a) + sg * a) / 255; - dr = dstptr[2]; - dr = (dr * (255 - a) + sr * a) / 255; - } - - *dstptr++ = db; - *dstptr++ = dg; - *dstptr++ = dr; - } - - srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); - dstptr += dstrowskip; - } -} - -/* Optimized blending blitter for RGBA888 to RGBA8888. */ -void -grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - grub_uint32_t color; - int i; - int j; - grub_uint32_t *srcptr; - grub_uint32_t *dstptr; - unsigned int sr; - unsigned int sg; - unsigned int sb; - unsigned int a; - unsigned int dr; - unsigned int dg; - unsigned int db; - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - { - color = *srcptr++; - - a = color >> 24; - - if (a == 0) - { - dstptr++; - continue; - } - - if (a == 255) - { - *dstptr++ = color; - continue; - } - - sr = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sb = (color >> 16) & 0xFF; - - color = *dstptr; - - dr = (color >> 0) & 0xFF; - dg = (color >> 8) & 0xFF; - db = (color >> 16) & 0xFF; - - dr = (dr * (255 - a) + sr * a) / 255; - dg = (dg * (255 - a) + sg * a) / 255; - db = (db * (255 - a) + sb * a) / 255; - - color = (a << 24) | (db << 16) | (dg << 8) | dr; - - *dstptr++ = color; - } - } -} - -/* Optimized blending blitter for RGBA8888 to RGB888. */ -void -grub_video_i386_vbeblit_blend_RGB888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - grub_uint32_t color; - int i; - int j; - grub_uint32_t *srcptr; - grub_uint8_t *dstptr; - unsigned int sr; - unsigned int sg; - unsigned int sb; - unsigned int a; - unsigned int dr; - unsigned int dg; - unsigned int db; - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - { - color = *srcptr++; - - a = color >> 24; - - if (a == 0) - { - dstptr += 3; - continue; - } - - sr = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sb = (color >> 16) & 0xFF; - - if (a == 255) - { - *dstptr++ = sr; - *dstptr++ = sg; - *dstptr++ = sb; - - continue; - } - - dr = dstptr[0]; - dg = dstptr[1]; - db = dstptr[2]; - - dr = (dr * (255 - a) + sr * a) / 255; - dg = (dg * (255 - a) + sg * a) / 255; - db = (db * (255 - a) + sb * a) / 255; - - *dstptr++ = dr; - *dstptr++ = dg; - *dstptr++ = db; - } - } -} - -/* Optimized blending blitter for RGBA8888 to indexed color. */ -void -grub_video_i386_vbeblit_blend_index_RGBA8888 (struct grub_video_i386_vbeblit_info *dst, - struct grub_video_i386_vbeblit_info *src, - int x, int y, - int width, int height, - int offset_x, int offset_y) -{ - grub_uint32_t color; - int i; - int j; - grub_uint32_t *srcptr; - grub_uint8_t *dstptr; - unsigned int sr; - unsigned int sg; - unsigned int sb; - unsigned int a; - unsigned char dr; - unsigned char dg; - unsigned char db; - unsigned char da; - - for (j = 0; j < height; j++) - { - srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j); - - for (i = 0; i < width; i++) - { - color = *srcptr++; - - a = color >> 24; - - if (a == 0) - { - dstptr++; - continue; - } - - sr = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sb = (color >> 16) & 0xFF; - - if (a == 255) - { - color = grub_video_vbe_map_rgb(sr, sg, sb); - *dstptr++ = color & 0xFF; - continue; - } - - grub_video_vbe_unmap_color_int (dst, *dstptr, &dr, &dg, &db, &da); - - dr = (dr * (255 - a) + sr * a) / 255; - dg = (dg * (255 - a) + sg * a) / 255; - db = (db * (255 - a) + sb * a) / 255; - - color = grub_video_vbe_map_rgb(dr, dg, db); - - *dstptr++ = color & 0xFF; - } - } -} diff --git a/video/i386/pc/vbefill.c b/video/i386/pc/vbefill.c deleted file mode 100644 index 3a98a71..0000000 --- a/video/i386/pc/vbefill.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB 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, see . - */ - -/* 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 - -/* Generic filler that works for every supported mode. */ -void -grub_video_i386_vbefill (struct grub_video_i386_vbeblit_info *dst, - grub_video_color_t color, int x, int y, - int width, int height) -{ - int i; - int j; - - for (j = 0; j < height; j++) - for (i = 0; i < width; i++) - set_pixel (dst, x+i, y+j, color); -} - -/* Optimized filler for direct color 32 bit modes. It is assumed that color - is already mapped to destination format. */ -void -grub_video_i386_vbefill_direct32 (struct grub_video_i386_vbeblit_info *dst, - grub_video_color_t color, int x, int y, - int width, int height) -{ - int i; - int j; - grub_uint32_t *dstptr; - grub_size_t rowskip; - - /* Calculate the number of bytes to advance from the end of one line - to the beginning of the next line. */ - rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - - /* Get the start address. */ - dstptr = (grub_uint32_t *) grub_video_vbe_get_video_ptr (dst, x, y); - - for (j = 0; j < height; j++) - { - for (i = 0; i < width; i++) - *dstptr++ = color; - - /* Advance the dest pointer to the right location on the next line. */ - dstptr = (grub_uint32_t *) (((char *) dstptr) + rowskip); - } -} - -/* Optimized filler for direct color 24 bit modes. It is assumed that color - is already mapped to destination format. */ -void -grub_video_i386_vbefill_direct24 (struct grub_video_i386_vbeblit_info *dst, - grub_video_color_t color, int x, int y, - int width, int height) -{ - int i; - int j; - grub_size_t rowskip; - grub_uint8_t *dstptr; - grub_uint8_t fill0 = (grub_uint8_t)((color >> 0) & 0xFF); - grub_uint8_t fill1 = (grub_uint8_t)((color >> 8) & 0xFF); - grub_uint8_t fill2 = (grub_uint8_t)((color >> 16) & 0xFF); - - /* Calculate the number of bytes to advance from the end of one line - to the beginning of the next line. */ - rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - - /* Get the start address. */ - dstptr = (grub_uint8_t *) grub_video_vbe_get_video_ptr (dst, x, y); - - for (j = 0; j < height; j++) - { - for (i = 0; i < width; i++) - { - *dstptr++ = fill0; - *dstptr++ = fill1; - *dstptr++ = fill2; - } - - /* Advance the dest pointer to the right location on the next line. */ - dstptr += rowskip; - } -} - -/* Optimized filler for direct color 16 bit modes. It is assumed that color - is already mapped to destination format. */ -void -grub_video_i386_vbefill_direct16 (struct grub_video_i386_vbeblit_info *dst, - grub_video_color_t color, int x, int y, - int width, int height) -{ - int i; - int j; - grub_size_t rowskip; - grub_uint8_t *dstptr; - grub_uint8_t fill0 = (grub_uint8_t)((color >> 0) & 0xFF); - grub_uint8_t fill1 = (grub_uint8_t)((color >> 8) & 0xFF); - - /* Calculate the number of bytes to advance from the end of one line - to the beginning of the next line. */ - rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - - /* Get the start address. */ - dstptr = (grub_uint8_t *) grub_video_vbe_get_video_ptr (dst, x, y); - - for (j = 0; j < height; j++) - { - for (i = 0; i < width; i++) - { - *dstptr++ = fill0; - *dstptr++ = fill1; - } - - /* Advance the dest pointer to the right location on the next line. */ - dstptr += rowskip; - } -} - -/* Optimized filler for index color. It is assumed that color - is already mapped to destination format. */ -void -grub_video_i386_vbefill_direct8 (struct grub_video_i386_vbeblit_info *dst, - grub_video_color_t color, int x, int y, - int width, int height) -{ - int i; - int j; - grub_size_t rowskip; - grub_uint8_t *dstptr; - grub_uint8_t fill = (grub_uint8_t)color & 0xFF; - - /* Calculate the number of bytes to advance from the end of one line - to the beginning of the next line. */ - rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - - /* Get the start address. */ - dstptr = (grub_uint8_t *) grub_video_vbe_get_video_ptr (dst, x, y); - - for (j = 0; j < height; j++) - { - for (i = 0; i < width; i++) - *dstptr++ = fill; - - /* Advance the dest pointer to the right location on the next line. */ - dstptr += rowskip; - } -} diff --git a/video/i386/pc/vbeutil.c b/video/i386/pc/vbeutil.c deleted file mode 100644 index 1040dc9..0000000 --- a/video/i386/pc/vbeutil.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2009 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 3 of the License, or - * (at your option) any later version. - * - * GRUB 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, see . - */ - -#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; - - case 1: - /* For 1-bit bitmaps, addressing needs to be done at the bit level - and it doesn't make sense, in general, to ask for a pointer - to a particular pixel's data. */ - 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; - - case 1: - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) - { - int bit_index = y * source->mode_info->width + x; - grub_uint8_t *ptr = (grub_uint8_t *)source->data - + bit_index / 8; - int bit_pos = 7 - bit_index % 8; - color = (*ptr >> bit_pos) & 0x01; - } - 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; - - case 1: - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) - { - int bit_index = y * source->mode_info->width + x; - grub_uint8_t *ptr = (grub_uint8_t *)source->data - + bit_index / 8; - int bit_pos = 7 - bit_index % 8; - *ptr = (*ptr & ~(1 << bit_pos)) | ((color & 0x01) << bit_pos); - } - break; - - default: - break; - } -} diff --git a/video/video.c b/video/video.c index c22947b..8271d79 100644 --- a/video/video.c +++ b/video/video.c @@ -654,6 +654,8 @@ grub_video_set_mode (char *modestring, if (err != GRUB_ERR_NONE) { p->fini (); + grub_dprintf ("video", "Failed to setup mode %dx%d (%x) on %s\n", + width, height, flags, p->name); grub_errno = GRUB_ERR_NONE; continue; } @@ -662,6 +664,8 @@ grub_video_set_mode (char *modestring, if (err != GRUB_ERR_NONE) { p->fini (); + grub_dprintf ("video", "Failed to get info: %dx%d (%x) on %s\n", + width, height, flags, p->name); grub_errno = GRUB_ERR_NONE; continue; }