2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 Please note following when reading the code below:
23 - In this driver we assume that every memory can be accessed by same memory
24 bus. If there are different address spaces do not use this code as a base
27 - Every function in this code assumes that bounds checking has been done in
28 previous phase and they are opted out in here. */
30 #include <grub/machine/vbe.h>
31 #include <grub/machine/vbeblit.h>
32 #include <grub/machine/vbeutil.h>
33 #include <grub/misc.h>
34 #include <grub/types.h>
35 #include <grub/video.h>
37 /* Generic replacing blitter (slow). Works for every supported format. */
39 grub_video_i386_vbeblit_replace (struct grub_video_i386_vbeblit_info
*dst
,
40 struct grub_video_i386_vbeblit_info
*src
,
41 int x
, int y
, int width
, int height
,
42 int offset_x
, int offset_y
)
47 grub_uint8_t src_green
;
48 grub_uint8_t src_blue
;
49 grub_uint8_t src_alpha
;
50 grub_video_color_t src_color
;
51 grub_video_color_t dst_color
;
53 for (j
= 0; j
< height
; j
++)
55 for (i
= 0; i
< width
; i
++)
57 src_color
= get_pixel (src
, i
+ offset_x
, j
+ offset_y
);
59 grub_video_vbe_unmap_color_int (src
, src_color
, &src_red
, &src_green
,
60 &src_blue
, &src_alpha
);
62 dst_color
= grub_video_vbe_map_rgba (src_red
, src_green
,
65 set_pixel (dst
, x
+ i
, y
+ j
, dst_color
);
70 /* Block copy replacing blitter. Works with modes multiple of 8 bits. */
72 grub_video_i386_vbeblit_replace_directN (struct grub_video_i386_vbeblit_info
*dst
,
73 struct grub_video_i386_vbeblit_info
*src
,
74 int x
, int y
, int width
, int height
,
75 int offset_x
, int offset_y
)
78 grub_uint32_t
*srcptr
;
79 grub_uint32_t
*dstptr
;
82 bpp
= src
->mode_info
->bytes_per_pixel
;
84 for (j
= 0; j
< height
; j
++)
86 srcptr
= (grub_uint32_t
*)get_data_ptr (src
, offset_x
, j
+ offset_y
);
87 dstptr
= (grub_uint32_t
*)get_data_ptr (dst
, x
, y
+ j
);
89 grub_memmove (dstptr
, srcptr
, width
* bpp
);
93 /* Optimized replacing blitter for RGBX8888 to BGRX8888. */
95 grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888 (struct grub_video_i386_vbeblit_info
*dst
,
96 struct grub_video_i386_vbeblit_info
*src
,
98 int width
, int height
,
99 int offset_x
, int offset_y
)
103 grub_uint8_t
*srcptr
;
104 grub_uint8_t
*dstptr
;
105 unsigned int srcrowskip
;
106 unsigned int dstrowskip
;
108 /* Calculate the number of bytes to advance from the end of one line
109 to the beginning of the next line. */
110 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
111 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
113 srcptr
= (grub_uint8_t
*) get_data_ptr (src
, offset_x
, offset_y
);
114 dstptr
= (grub_uint8_t
*) get_data_ptr (dst
, x
, y
);
116 for (j
= 0; j
< height
; j
++)
118 for (i
= 0; i
< width
; i
++)
120 grub_uint8_t r
= *srcptr
++;
121 grub_uint8_t g
= *srcptr
++;
122 grub_uint8_t b
= *srcptr
++;
123 grub_uint8_t a
= *srcptr
++;
131 srcptr
+= srcrowskip
;
132 dstptr
+= dstrowskip
;
136 /* Optimized replacing blitter for RGB888 to BGRX8888. */
138 grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (struct grub_video_i386_vbeblit_info
*dst
,
139 struct grub_video_i386_vbeblit_info
*src
,
141 int width
, int height
,
142 int offset_x
, int offset_y
)
146 grub_uint8_t
*srcptr
;
147 grub_uint8_t
*dstptr
;
148 unsigned int srcrowskip
;
149 unsigned int dstrowskip
;
151 /* Calculate the number of bytes to advance from the end of one line
152 to the beginning of the next line. */
153 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
154 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
156 srcptr
= (grub_uint8_t
*) get_data_ptr (src
, offset_x
, offset_y
);
157 dstptr
= (grub_uint8_t
*) get_data_ptr (dst
, x
, y
);
159 for (j
= 0; j
< height
; j
++)
161 for (i
= 0; i
< width
; i
++)
163 grub_uint8_t r
= *srcptr
++;
164 grub_uint8_t g
= *srcptr
++;
165 grub_uint8_t b
= *srcptr
++;
171 /* Set alpha component as opaque. */
175 srcptr
+= srcrowskip
;
176 dstptr
+= dstrowskip
;
180 /* Optimized replacing blitter for RGBX8888 to BGR888. */
182 grub_video_i386_vbeblit_replace_BGR888_RGBX8888 (struct grub_video_i386_vbeblit_info
*dst
,
183 struct grub_video_i386_vbeblit_info
*src
,
185 int width
, int height
,
186 int offset_x
, int offset_y
)
188 grub_uint32_t
*srcptr
;
189 grub_uint8_t
*dstptr
;
190 unsigned int srcrowskip
;
191 unsigned int dstrowskip
;
195 /* Calculate the number of bytes to advance from the end of one line
196 to the beginning of the next line. */
197 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
198 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
200 srcptr
= (grub_uint32_t
*) get_data_ptr (src
, offset_x
, offset_y
);
201 dstptr
= (grub_uint8_t
*) get_data_ptr (dst
, x
, y
);
203 for (j
= 0; j
< height
; j
++)
205 for (i
= 0; i
< width
; i
++)
214 sr
= (color
>> 0) & 0xFF;
215 sg
= (color
>> 8) & 0xFF;
216 sb
= (color
>> 16) & 0xFF;
223 srcptr
= (grub_uint32_t
*) (((grub_uint8_t
*) srcptr
) + srcrowskip
);
224 dstptr
+= dstrowskip
;
228 /* Optimized replacing blitter for RGB888 to BGR888. */
230 grub_video_i386_vbeblit_replace_BGR888_RGB888 (struct grub_video_i386_vbeblit_info
*dst
,
231 struct grub_video_i386_vbeblit_info
*src
,
233 int width
, int height
,
234 int offset_x
, int offset_y
)
238 grub_uint8_t
*srcptr
;
239 grub_uint8_t
*dstptr
;
240 unsigned int srcrowskip
;
241 unsigned int dstrowskip
;
243 /* Calculate the number of bytes to advance from the end of one line
244 to the beginning of the next line. */
245 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
246 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
248 srcptr
= (grub_uint8_t
*) get_data_ptr (src
, offset_x
, offset_y
);
249 dstptr
= (grub_uint8_t
*) get_data_ptr (dst
, x
, y
);
251 for (j
= 0; j
< height
; j
++)
253 for (i
= 0; i
< width
; i
++)
255 grub_uint8_t r
= *srcptr
++;
256 grub_uint8_t g
= *srcptr
++;
257 grub_uint8_t b
= *srcptr
++;
264 srcptr
+= srcrowskip
;
265 dstptr
+= dstrowskip
;
269 /* Optimized replacing blitter for RGB888 to RGBX8888. */
271 grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (struct grub_video_i386_vbeblit_info
*dst
,
272 struct grub_video_i386_vbeblit_info
*src
,
274 int width
, int height
,
275 int offset_x
, int offset_y
)
280 grub_uint8_t
*srcptr
;
281 grub_uint32_t
*dstptr
;
286 for (j
= 0; j
< height
; j
++)
288 srcptr
= (grub_uint8_t
*)get_data_ptr (src
, offset_x
, j
+ offset_y
);
289 dstptr
= (grub_uint32_t
*)get_data_ptr (dst
, x
, y
+ j
);
291 for (i
= 0; i
< width
; i
++)
297 /* Set alpha as opaque. */
298 color
= 0xFF000000 | (sb
<< 16) | (sg
<< 8) | sr
;
305 /* Optimized replacing blitter for RGBX8888 to RGB888. */
307 grub_video_i386_vbeblit_replace_RGB888_RGBX8888 (struct grub_video_i386_vbeblit_info
*dst
,
308 struct grub_video_i386_vbeblit_info
*src
,
310 int width
, int height
,
311 int offset_x
, int offset_y
)
316 grub_uint32_t
*srcptr
;
317 grub_uint8_t
*dstptr
;
322 for (j
= 0; j
< height
; j
++)
324 srcptr
= (grub_uint32_t
*)get_data_ptr (src
, offset_x
, j
+ offset_y
);
325 dstptr
= (grub_uint8_t
*)get_data_ptr (dst
, x
, y
+ j
);
327 for (i
= 0; i
< width
; i
++)
331 sr
= (color
>> 0) & 0xFF;
332 sg
= (color
>> 8) & 0xFF;
333 sb
= (color
>> 16) & 0xFF;
342 /* Optimized replacing blitter for RGBX8888 to indexed color. */
344 grub_video_i386_vbeblit_replace_index_RGBX8888 (struct grub_video_i386_vbeblit_info
*dst
,
345 struct grub_video_i386_vbeblit_info
*src
,
347 int width
, int height
,
348 int offset_x
, int offset_y
)
353 grub_uint32_t
*srcptr
;
354 grub_uint8_t
*dstptr
;
359 for (j
= 0; j
< height
; j
++)
361 srcptr
= (grub_uint32_t
*)get_data_ptr (src
, offset_x
, j
+ offset_y
);
362 dstptr
= (grub_uint8_t
*)get_data_ptr (dst
, x
, y
+ j
);
364 for (i
= 0; i
< width
; i
++)
368 sr
= (color
>> 0) & 0xFF;
369 sg
= (color
>> 8) & 0xFF;
370 sb
= (color
>> 16) & 0xFF;
372 color
= grub_video_vbe_map_rgb(sr
, sg
, sb
);
373 *dstptr
++ = color
& 0xFF;
378 /* Optimized replacing blitter for RGB888 to indexed color. */
380 grub_video_i386_vbeblit_replace_index_RGB888 (struct grub_video_i386_vbeblit_info
*dst
,
381 struct grub_video_i386_vbeblit_info
*src
,
383 int width
, int height
,
384 int offset_x
, int offset_y
)
389 grub_uint8_t
*srcptr
;
390 grub_uint8_t
*dstptr
;
395 for (j
= 0; j
< height
; j
++)
397 srcptr
= (grub_uint8_t
*)get_data_ptr (src
, offset_x
, j
+ offset_y
);
398 dstptr
= (grub_uint8_t
*)get_data_ptr (dst
, x
, y
+ j
);
400 for (i
= 0; i
< width
; i
++)
406 color
= grub_video_vbe_map_rgb(sr
, sg
, sb
);
408 *dstptr
++ = color
& 0xFF;
413 /* Generic blending blitter. Works for every supported format. */
415 grub_video_i386_vbeblit_blend (struct grub_video_i386_vbeblit_info
*dst
,
416 struct grub_video_i386_vbeblit_info
*src
,
417 int x
, int y
, int width
, int height
,
418 int offset_x
, int offset_y
)
423 for (j
= 0; j
< height
; j
++)
425 for (i
= 0; i
< width
; i
++)
427 grub_uint8_t src_red
;
428 grub_uint8_t src_green
;
429 grub_uint8_t src_blue
;
430 grub_uint8_t src_alpha
;
431 grub_uint8_t dst_red
;
432 grub_uint8_t dst_green
;
433 grub_uint8_t dst_blue
;
434 grub_uint8_t dst_alpha
;
435 grub_video_color_t src_color
;
436 grub_video_color_t dst_color
;
438 src_color
= get_pixel (src
, i
+ offset_x
, j
+ offset_y
);
439 grub_video_vbe_unmap_color_int (src
, src_color
, &src_red
, &src_green
,
440 &src_blue
, &src_alpha
);
445 if (src_alpha
== 255)
447 dst_color
= grub_video_vbe_map_rgba (src_red
, src_green
,
448 src_blue
, src_alpha
);
449 set_pixel (dst
, x
+ i
, y
+ j
, dst_color
);
453 dst_color
= get_pixel (dst
, x
+ i
, y
+ j
);
455 grub_video_vbe_unmap_color_int (dst
, dst_color
, &dst_red
,
456 &dst_green
, &dst_blue
, &dst_alpha
);
458 dst_red
= (((src_red
* src_alpha
)
459 + (dst_red
* (255 - src_alpha
))) / 255);
460 dst_green
= (((src_green
* src_alpha
)
461 + (dst_green
* (255 - src_alpha
))) / 255);
462 dst_blue
= (((src_blue
* src_alpha
)
463 + (dst_blue
* (255 - src_alpha
))) / 255);
465 dst_alpha
= src_alpha
;
466 dst_color
= grub_video_vbe_map_rgba (dst_red
, dst_green
, dst_blue
,
469 set_pixel (dst
, x
+ i
, y
+ j
, dst_color
);
474 /* Optimized blending blitter for RGBA8888 to BGRA8888. */
476 grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888 (struct grub_video_i386_vbeblit_info
*dst
,
477 struct grub_video_i386_vbeblit_info
*src
,
479 int width
, int height
,
480 int offset_x
, int offset_y
)
482 grub_uint32_t
*srcptr
;
483 grub_uint32_t
*dstptr
;
484 unsigned int srcrowskip
;
485 unsigned int dstrowskip
;
489 /* Calculate the number of bytes to advance from the end of one line
490 to the beginning of the next line. */
491 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
492 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
494 srcptr
= (grub_uint32_t
*) get_data_ptr (src
, offset_x
, offset_y
);
495 dstptr
= (grub_uint32_t
*) get_data_ptr (dst
, x
, y
);
497 for (j
= 0; j
< height
; j
++)
499 for (i
= 0; i
< width
; i
++)
516 /* Skip transparent source pixels. */
521 sr
= (color
>> 0) & 0xFF;
522 sg
= (color
>> 8) & 0xFF;
523 sb
= (color
>> 16) & 0xFF;
527 /* Opaque pixel shortcut. */
534 /* General pixel color blending. */
537 dr
= (color
>> 16) & 0xFF;
538 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
539 dg
= (color
>> 8) & 0xFF;
540 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
541 db
= (color
>> 0) & 0xFF;
542 db
= (db
* (255 - a
) + sb
* a
) / 255;
545 color
= (a
<< 24) | (dr
<< 16) | (dg
<< 8) | db
;
550 srcptr
= (grub_uint32_t
*) (((grub_uint8_t
*) srcptr
) + srcrowskip
);
551 dstptr
= (grub_uint32_t
*) (((grub_uint8_t
*) dstptr
) + dstrowskip
);
555 /* Optimized blending blitter for RGBA8888 to BGR888. */
557 grub_video_i386_vbeblit_blend_BGR888_RGBA8888 (struct grub_video_i386_vbeblit_info
*dst
,
558 struct grub_video_i386_vbeblit_info
*src
,
560 int width
, int height
,
561 int offset_x
, int offset_y
)
563 grub_uint32_t
*srcptr
;
564 grub_uint8_t
*dstptr
;
565 unsigned int srcrowskip
;
566 unsigned int dstrowskip
;
570 /* Calculate the number of bytes to advance from the end of one line
571 to the beginning of the next line. */
572 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
573 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
575 srcptr
= (grub_uint32_t
*) get_data_ptr (src
, offset_x
, offset_y
);
576 dstptr
= (grub_uint8_t
*) get_data_ptr (dst
, x
, y
);
578 for (j
= 0; j
< height
; j
++)
580 for (i
= 0; i
< width
; i
++)
597 /* Skip transparent source pixels. */
602 sr
= (color
>> 0) & 0xFF;
603 sg
= (color
>> 8) & 0xFF;
604 sb
= (color
>> 16) & 0xFF;
608 /* Opaque pixel shortcut. */
615 /* General pixel color blending. */
619 db
= (db
* (255 - a
) + sb
* a
) / 255;
621 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
623 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
631 srcptr
= (grub_uint32_t
*) (((grub_uint8_t
*) srcptr
) + srcrowskip
);
632 dstptr
+= dstrowskip
;
636 /* Optimized blending blitter for RGBA888 to RGBA8888. */
638 grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888 (struct grub_video_i386_vbeblit_info
*dst
,
639 struct grub_video_i386_vbeblit_info
*src
,
641 int width
, int height
,
642 int offset_x
, int offset_y
)
647 grub_uint32_t
*srcptr
;
648 grub_uint32_t
*dstptr
;
657 for (j
= 0; j
< height
; j
++)
659 srcptr
= (grub_uint32_t
*)get_data_ptr (src
, offset_x
, j
+ offset_y
);
660 dstptr
= (grub_uint32_t
*)get_data_ptr (dst
, x
, y
+ j
);
662 for (i
= 0; i
< width
; i
++)
680 sr
= (color
>> 0) & 0xFF;
681 sg
= (color
>> 8) & 0xFF;
682 sb
= (color
>> 16) & 0xFF;
686 dr
= (color
>> 0) & 0xFF;
687 dg
= (color
>> 8) & 0xFF;
688 db
= (color
>> 16) & 0xFF;
690 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
691 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
692 db
= (db
* (255 - a
) + sb
* a
) / 255;
694 color
= (a
<< 24) | (db
<< 16) | (dg
<< 8) | dr
;
701 /* Optimized blending blitter for RGBA8888 to RGB888. */
703 grub_video_i386_vbeblit_blend_RGB888_RGBA8888 (struct grub_video_i386_vbeblit_info
*dst
,
704 struct grub_video_i386_vbeblit_info
*src
,
706 int width
, int height
,
707 int offset_x
, int offset_y
)
712 grub_uint32_t
*srcptr
;
713 grub_uint8_t
*dstptr
;
722 for (j
= 0; j
< height
; j
++)
724 srcptr
= (grub_uint32_t
*)get_data_ptr (src
, offset_x
, j
+ offset_y
);
725 dstptr
= (grub_uint8_t
*)get_data_ptr (dst
, x
, y
+ j
);
727 for (i
= 0; i
< width
; i
++)
739 sr
= (color
>> 0) & 0xFF;
740 sg
= (color
>> 8) & 0xFF;
741 sb
= (color
>> 16) & 0xFF;
756 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
757 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
758 db
= (db
* (255 - a
) + sb
* a
) / 255;
767 /* Optimized blending blitter for RGBA8888 to indexed color. */
769 grub_video_i386_vbeblit_blend_index_RGBA8888 (struct grub_video_i386_vbeblit_info
*dst
,
770 struct grub_video_i386_vbeblit_info
*src
,
772 int width
, int height
,
773 int offset_x
, int offset_y
)
778 grub_uint32_t
*srcptr
;
779 grub_uint8_t
*dstptr
;
789 for (j
= 0; j
< height
; j
++)
791 srcptr
= (grub_uint32_t
*)get_data_ptr (src
, offset_x
, j
+ offset_y
);
792 dstptr
= (grub_uint8_t
*)get_data_ptr (dst
, x
, y
+ j
);
794 for (i
= 0; i
< width
; i
++)
806 sr
= (color
>> 0) & 0xFF;
807 sg
= (color
>> 8) & 0xFF;
808 sb
= (color
>> 16) & 0xFF;
812 color
= grub_video_vbe_map_rgb(sr
, sg
, sb
);
813 *dstptr
++ = color
& 0xFF;
817 grub_video_vbe_unmap_color_int (dst
, *dstptr
, &dr
, &dg
, &db
, &da
);
819 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
820 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
821 db
= (db
* (255 - a
) + sb
* a
) / 255;
823 color
= grub_video_vbe_map_rgb(dr
, dg
, db
);
825 *dstptr
++ = color
& 0xFF;