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/video_fb.h>
31 #include <grub/fbblit.h>
32 #include <grub/fbutil.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_fbblit_replace (struct grub_video_fbblit_info
*dst
,
40 struct grub_video_fbblit_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_fb_unmap_color_int (src
, src_color
, &src_red
, &src_green
,
60 &src_blue
, &src_alpha
);
62 dst_color
= grub_video_fb_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_fbblit_replace_directN (struct grub_video_fbblit_info
*dst
,
73 struct grub_video_fbblit_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
;
83 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
84 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
86 for (j
= 0; j
< height
; j
++)
88 grub_memmove (dstptr
, srcptr
, width
* bpp
);
89 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, src
->mode_info
->pitch
);
90 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dst
->mode_info
->pitch
);
94 /* Optimized replacing blitter for 1-bit to 32bit. */
96 grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info
*dst
,
97 struct grub_video_fbblit_info
*src
,
99 int width
, int height
,
100 int offset_x
, int offset_y
)
104 grub_uint8_t
*srcptr
;
105 grub_uint32_t
*dstptr
;
106 grub_uint8_t srcmask
;
107 unsigned int dstrowskip
;
108 unsigned int srcrowskipbyte
, srcrowskipbit
;
109 grub_uint32_t fgcolor
, bgcolor
;
112 /* Calculate the number of bytes to advance from the end of one line
113 to the beginning of the next line. */
114 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
115 srcrowskipbyte
= (src
->mode_info
->width
- width
) >> 3;
116 srcrowskipbit
= (src
->mode_info
->width
- width
) & 7;
118 bit_index
= offset_y
* src
->mode_info
->width
+ offset_x
;
119 srcptr
= (grub_uint8_t
*) src
->data
+ (bit_index
>> 3);
120 srcmask
= 1 << (~bit_index
& 7);
121 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
123 fgcolor
= grub_video_fb_map_rgba (src
->mode_info
->fg_red
,
124 src
->mode_info
->fg_green
,
125 src
->mode_info
->fg_blue
,
126 src
->mode_info
->fg_alpha
);
128 bgcolor
= grub_video_fb_map_rgba (src
->mode_info
->bg_red
,
129 src
->mode_info
->bg_green
,
130 src
->mode_info
->bg_blue
,
131 src
->mode_info
->bg_alpha
);
133 for (j
= 0; j
< height
; j
++)
135 for (i
= 0; i
< width
; i
++)
137 if (*srcptr
& srcmask
)
151 srcptr
+= srcrowskipbyte
;
152 if (srcmask
>> srcrowskipbit
)
153 srcmask
>>= srcrowskipbit
;
157 srcmask
<<= 8 - srcrowskipbit
;
159 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
164 #ifdef GRUB_HAVE_UNALIGNED_ACCESS
165 /* Optimized replacing blitter for 1-bit to 24-bit. */
167 grub_video_fbblit_replace_24bit_1bit (struct grub_video_fbblit_info
*dst
,
168 struct grub_video_fbblit_info
*src
,
170 int width
, int height
,
171 int offset_x
, int offset_y
)
175 grub_uint8_t
*srcptr
;
176 grub_uint8_t
*dstptr
;
177 grub_uint8_t srcmask
;
178 unsigned int dstrowskip
;
179 unsigned int srcrowskipbyte
, srcrowskipbit
;
180 grub_uint32_t fgcolor
, bgcolor
;
183 /* Calculate the number of bytes to advance from the end of one line
184 to the beginning of the next line. */
185 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
186 srcrowskipbyte
= (src
->mode_info
->width
- width
) >> 3;
187 srcrowskipbit
= (src
->mode_info
->width
- width
) & 7;
189 bit_index
= offset_y
* src
->mode_info
->width
+ offset_x
;
190 srcptr
= (grub_uint8_t
*) src
->data
+ (bit_index
>> 3);
191 srcmask
= 1 << (~bit_index
& 7);
192 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
194 fgcolor
= grub_video_fb_map_rgba (src
->mode_info
->fg_red
,
195 src
->mode_info
->fg_green
,
196 src
->mode_info
->fg_blue
,
197 src
->mode_info
->fg_alpha
);
199 bgcolor
= grub_video_fb_map_rgba (src
->mode_info
->bg_red
,
200 src
->mode_info
->bg_green
,
201 src
->mode_info
->bg_blue
,
202 src
->mode_info
->bg_alpha
);
204 for (j
= 0; j
< height
; j
++)
206 for (i
= 0; i
< width
- 1; i
++)
208 if (*srcptr
& srcmask
)
209 *(grub_uint32_t
*) dstptr
= fgcolor
;
211 *(grub_uint32_t
*) dstptr
= bgcolor
;
222 if (*srcptr
& srcmask
)
224 *dstptr
++ = fgcolor
& 0xff;
225 *dstptr
++ = (fgcolor
& 0xff00) >> 8;
226 *dstptr
++ = (fgcolor
& 0xff0000) >> 16;
230 *dstptr
++ = bgcolor
& 0xff;
231 *dstptr
++ = (bgcolor
& 0xff00) >> 8;
232 *dstptr
++ = (bgcolor
& 0xff0000) >> 16;
241 srcptr
+= srcrowskipbyte
;
242 if (srcmask
>> srcrowskipbit
)
243 srcmask
>>= srcrowskipbit
;
247 srcmask
<<= 8 - srcrowskipbit
;
249 dstptr
+= dstrowskip
;
254 /* Optimized replacing blitter for 1-bit to 16-bit. */
256 grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info
*dst
,
257 struct grub_video_fbblit_info
*src
,
259 int width
, int height
,
260 int offset_x
, int offset_y
)
264 grub_uint8_t
*srcptr
;
265 grub_uint16_t
*dstptr
;
266 grub_uint8_t srcmask
;
267 unsigned int dstrowskip
;
268 unsigned int srcrowskipbyte
, srcrowskipbit
;
269 grub_uint16_t fgcolor
, bgcolor
;
272 /* Calculate the number of bytes to advance from the end of one line
273 to the beginning of the next line. */
274 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
275 srcrowskipbyte
= (src
->mode_info
->width
- width
) >> 3;
276 srcrowskipbit
= (src
->mode_info
->width
- width
) & 7;
278 bit_index
= offset_y
* src
->mode_info
->width
+ offset_x
;
279 srcptr
= (grub_uint8_t
*) src
->data
+ (bit_index
>> 3);
280 srcmask
= 1 << (~bit_index
& 7);
281 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
283 fgcolor
= grub_video_fb_map_rgba (src
->mode_info
->fg_red
,
284 src
->mode_info
->fg_green
,
285 src
->mode_info
->fg_blue
,
286 src
->mode_info
->fg_alpha
);
288 bgcolor
= grub_video_fb_map_rgba (src
->mode_info
->bg_red
,
289 src
->mode_info
->bg_green
,
290 src
->mode_info
->bg_blue
,
291 src
->mode_info
->bg_alpha
);
293 for (j
= 0; j
< height
; j
++)
295 for (i
= 0; i
< width
; i
++)
297 if (*srcptr
& srcmask
)
311 srcptr
+= srcrowskipbyte
;
312 if (srcmask
>> srcrowskipbit
)
313 srcmask
>>= srcrowskipbit
;
317 srcmask
<<= 8 - srcrowskipbit
;
319 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
323 /* Optimized replacing blitter for 1-bit to 8-bit. */
325 grub_video_fbblit_replace_8bit_1bit (struct grub_video_fbblit_info
*dst
,
326 struct grub_video_fbblit_info
*src
,
328 int width
, int height
,
329 int offset_x
, int offset_y
)
333 grub_uint8_t
*srcptr
;
334 grub_uint8_t
*dstptr
;
335 grub_uint8_t srcmask
;
336 unsigned int dstrowskip
;
337 unsigned int srcrowskipbyte
, srcrowskipbit
;
338 grub_uint8_t fgcolor
, bgcolor
;
341 /* Calculate the number of bytes to advance from the end of one line
342 to the beginning of the next line. */
343 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
344 srcrowskipbyte
= (src
->mode_info
->width
- width
) >> 3;
345 srcrowskipbit
= (src
->mode_info
->width
- width
) & 7;
347 bit_index
= offset_y
* src
->mode_info
->width
+ offset_x
;
348 srcptr
= (grub_uint8_t
*) src
->data
+ (bit_index
>> 3);
349 srcmask
= 1 << (~bit_index
& 7);
350 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
352 fgcolor
= grub_video_fb_map_rgba (src
->mode_info
->fg_red
,
353 src
->mode_info
->fg_green
,
354 src
->mode_info
->fg_blue
,
355 src
->mode_info
->fg_alpha
);
357 bgcolor
= grub_video_fb_map_rgba (src
->mode_info
->bg_red
,
358 src
->mode_info
->bg_green
,
359 src
->mode_info
->bg_blue
,
360 src
->mode_info
->bg_alpha
);
362 for (j
= 0; j
< height
; j
++)
364 for (i
= 0; i
< width
; i
++)
366 if (*srcptr
& srcmask
)
380 srcptr
+= srcrowskipbyte
;
381 if (srcmask
>> srcrowskipbit
)
382 srcmask
>>= srcrowskipbit
;
386 srcmask
<<= 8 - srcrowskipbit
;
388 dstptr
+= dstrowskip
;
392 /* Optimized replacing blitter for RGBX8888 to BGRX8888. */
394 grub_video_fbblit_replace_BGRX8888_RGBX8888 (struct grub_video_fbblit_info
*dst
,
395 struct grub_video_fbblit_info
*src
,
397 int width
, int height
,
398 int offset_x
, int offset_y
)
402 grub_uint8_t
*srcptr
;
403 grub_uint8_t
*dstptr
;
404 unsigned int srcrowskip
;
405 unsigned int dstrowskip
;
407 /* Calculate the number of bytes to advance from the end of one line
408 to the beginning of the next line. */
409 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
410 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
412 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
413 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
415 for (j
= 0; j
< height
; j
++)
417 for (i
= 0; i
< width
; i
++)
419 #ifdef GRUB_CPU_WORDS_BIGENDIAN
420 grub_uint8_t a
= *srcptr
++;
422 grub_uint8_t r
= *srcptr
++;
423 grub_uint8_t g
= *srcptr
++;
424 grub_uint8_t b
= *srcptr
++;
425 #ifndef GRUB_CPU_WORDS_BIGENDIAN
426 grub_uint8_t a
= *srcptr
++;
429 #ifdef GRUB_CPU_WORDS_BIGENDIAN
435 #ifndef GRUB_CPU_WORDS_BIGENDIAN
440 srcptr
+= srcrowskip
;
441 dstptr
+= dstrowskip
;
445 /* Optimized replacing blitter for RGB888 to BGRX8888. */
447 grub_video_fbblit_replace_BGRX8888_RGB888 (struct grub_video_fbblit_info
*dst
,
448 struct grub_video_fbblit_info
*src
,
450 int width
, int height
,
451 int offset_x
, int offset_y
)
455 grub_uint8_t
*srcptr
;
456 grub_uint8_t
*dstptr
;
457 unsigned int srcrowskip
;
458 unsigned int dstrowskip
;
460 /* Calculate the number of bytes to advance from the end of one line
461 to the beginning of the next line. */
462 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
463 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
465 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
466 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
468 for (j
= 0; j
< height
; j
++)
470 for (i
= 0; i
< width
; i
++)
472 grub_uint8_t r
= *srcptr
++;
473 grub_uint8_t g
= *srcptr
++;
474 grub_uint8_t b
= *srcptr
++;
476 #ifdef GRUB_CPU_WORDS_BIGENDIAN
477 /* Set alpha component as opaque. */
485 #ifndef GRUB_CPU_WORDS_BIGENDIAN
486 /* Set alpha component as opaque. */
491 srcptr
+= srcrowskip
;
492 dstptr
+= dstrowskip
;
496 /* Optimized replacing blitter for RGBX8888 to BGR888. */
498 grub_video_fbblit_replace_BGR888_RGBX8888 (struct grub_video_fbblit_info
*dst
,
499 struct grub_video_fbblit_info
*src
,
501 int width
, int height
,
502 int offset_x
, int offset_y
)
504 grub_uint32_t
*srcptr
;
505 grub_uint8_t
*dstptr
;
506 unsigned int srcrowskip
;
507 unsigned int dstrowskip
;
511 /* Calculate the number of bytes to advance from the end of one line
512 to the beginning of the next line. */
513 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
514 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
516 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
517 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
519 for (j
= 0; j
< height
; j
++)
521 for (i
= 0; i
< width
; i
++)
530 sr
= (color
>> 0) & 0xFF;
531 sg
= (color
>> 8) & 0xFF;
532 sb
= (color
>> 16) & 0xFF;
534 #ifdef GRUB_CPU_WORDS_BIGENDIAN
545 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
546 dstptr
+= dstrowskip
;
550 /* Optimized replacing blitter for RGB888 to BGR888. */
552 grub_video_fbblit_replace_BGR888_RGB888 (struct grub_video_fbblit_info
*dst
,
553 struct grub_video_fbblit_info
*src
,
555 int width
, int height
,
556 int offset_x
, int offset_y
)
560 grub_uint8_t
*srcptr
;
561 grub_uint8_t
*dstptr
;
562 unsigned int srcrowskip
;
563 unsigned int dstrowskip
;
565 /* Calculate the number of bytes to advance from the end of one line
566 to the beginning of the next line. */
567 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
568 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
570 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
571 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
573 for (j
= 0; j
< height
; j
++)
575 for (i
= 0; i
< width
; i
++)
577 grub_uint8_t r
= *srcptr
++;
578 grub_uint8_t g
= *srcptr
++;
579 grub_uint8_t b
= *srcptr
++;
586 srcptr
+= srcrowskip
;
587 dstptr
+= dstrowskip
;
591 /* Optimized replacing blitter for RGB888 to RGBX8888. */
593 grub_video_fbblit_replace_RGBX8888_RGB888 (struct grub_video_fbblit_info
*dst
,
594 struct grub_video_fbblit_info
*src
,
596 int width
, int height
,
597 int offset_x
, int offset_y
)
602 grub_uint8_t
*srcptr
;
603 grub_uint32_t
*dstptr
;
607 grub_size_t srcrowskip
;
608 grub_size_t dstrowskip
;
610 srcrowskip
= src
->mode_info
->pitch
- 3 * width
;
611 dstrowskip
= dst
->mode_info
->pitch
- 4 * width
;
612 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
613 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
615 for (j
= 0; j
< height
; j
++)
617 for (i
= 0; i
< width
; i
++)
619 #ifdef GRUB_CPU_WORDS_BIGENDIAN
628 /* Set alpha as opaque. */
629 color
= 0xFF000000 | (sb
<< 16) | (sg
<< 8) | sr
;
633 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
634 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
638 /* Optimized replacing blitter for RGBX8888 to RGB888. */
640 grub_video_fbblit_replace_RGB888_RGBX8888 (struct grub_video_fbblit_info
*dst
,
641 struct grub_video_fbblit_info
*src
,
643 int width
, int height
,
644 int offset_x
, int offset_y
)
649 grub_uint32_t
*srcptr
;
650 grub_uint8_t
*dstptr
;
654 grub_size_t srcrowskip
;
655 grub_size_t dstrowskip
;
657 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
658 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
659 srcrowskip
= src
->mode_info
->pitch
- 4 * width
;
660 dstrowskip
= dst
->mode_info
->pitch
- 3 * width
;
662 for (j
= 0; j
< height
; j
++)
664 for (i
= 0; i
< width
; i
++)
668 sr
= (color
>> 0) & 0xFF;
669 sg
= (color
>> 8) & 0xFF;
670 sb
= (color
>> 16) & 0xFF;
672 #ifndef GRUB_CPU_WORDS_BIGENDIAN
682 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
683 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
687 /* Optimized replacing blitter for RGBX8888 to indexed color. */
689 grub_video_fbblit_replace_index_RGBX8888 (struct grub_video_fbblit_info
*dst
,
690 struct grub_video_fbblit_info
*src
,
692 int width
, int height
,
693 int offset_x
, int offset_y
)
698 grub_uint32_t
*srcptr
;
699 grub_uint8_t
*dstptr
;
703 grub_size_t srcrowskip
;
704 grub_size_t dstrowskip
;
706 srcrowskip
= src
->mode_info
->pitch
- 4 * width
;
707 dstrowskip
= dst
->mode_info
->pitch
- width
;
709 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
710 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
712 for (j
= 0; j
< height
; j
++)
714 for (i
= 0; i
< width
; i
++)
718 #ifdef GRUB_CPU_WORDS_BIGENDIAN
719 sb
= (color
>> 0) & 0xFF;
720 sg
= (color
>> 8) & 0xFF;
721 sr
= (color
>> 16) & 0xFF;
723 sr
= (color
>> 0) & 0xFF;
724 sg
= (color
>> 8) & 0xFF;
725 sb
= (color
>> 16) & 0xFF;
728 color
= grub_video_fb_map_rgb(sr
, sg
, sb
);
729 *dstptr
++ = color
& 0xFF;
731 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
732 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
736 /* Optimized replacing blitter for RGB888 to indexed color. */
738 grub_video_fbblit_replace_index_RGB888 (struct grub_video_fbblit_info
*dst
,
739 struct grub_video_fbblit_info
*src
,
741 int width
, int height
,
742 int offset_x
, int offset_y
)
747 grub_uint8_t
*srcptr
;
748 grub_uint8_t
*dstptr
;
752 grub_size_t srcrowskip
;
753 grub_size_t dstrowskip
;
755 srcrowskip
= src
->mode_info
->pitch
- 3 * width
;
756 dstrowskip
= dst
->mode_info
->pitch
- width
;
758 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
759 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
761 for (j
= 0; j
< height
; j
++)
763 for (i
= 0; i
< width
; i
++)
765 #ifndef GRUB_CPU_WORDS_BIGENDIAN
775 color
= grub_video_fb_map_rgb(sr
, sg
, sb
);
777 *dstptr
++ = color
& 0xFF;
779 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
780 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
784 /* Generic blending blitter. Works for every supported format. */
786 grub_video_fbblit_blend (struct grub_video_fbblit_info
*dst
,
787 struct grub_video_fbblit_info
*src
,
788 int x
, int y
, int width
, int height
,
789 int offset_x
, int offset_y
)
794 for (j
= 0; j
< height
; j
++)
796 for (i
= 0; i
< width
; i
++)
798 grub_uint8_t src_red
;
799 grub_uint8_t src_green
;
800 grub_uint8_t src_blue
;
801 grub_uint8_t src_alpha
;
802 grub_uint8_t dst_red
;
803 grub_uint8_t dst_green
;
804 grub_uint8_t dst_blue
;
805 grub_uint8_t dst_alpha
;
806 grub_video_color_t src_color
;
807 grub_video_color_t dst_color
;
809 src_color
= get_pixel (src
, i
+ offset_x
, j
+ offset_y
);
810 grub_video_fb_unmap_color_int (src
, src_color
, &src_red
, &src_green
,
811 &src_blue
, &src_alpha
);
816 if (src_alpha
== 255)
818 dst_color
= grub_video_fb_map_rgba (src_red
, src_green
,
819 src_blue
, src_alpha
);
820 set_pixel (dst
, x
+ i
, y
+ j
, dst_color
);
824 dst_color
= get_pixel (dst
, x
+ i
, y
+ j
);
826 grub_video_fb_unmap_color_int (dst
, dst_color
, &dst_red
,
827 &dst_green
, &dst_blue
, &dst_alpha
);
829 dst_red
= (((src_red
* src_alpha
)
830 + (dst_red
* (255 - src_alpha
))) / 255);
831 dst_green
= (((src_green
* src_alpha
)
832 + (dst_green
* (255 - src_alpha
))) / 255);
833 dst_blue
= (((src_blue
* src_alpha
)
834 + (dst_blue
* (255 - src_alpha
))) / 255);
836 dst_alpha
= src_alpha
;
837 dst_color
= grub_video_fb_map_rgba (dst_red
, dst_green
, dst_blue
,
840 set_pixel (dst
, x
+ i
, y
+ j
, dst_color
);
845 /* Optimized blending blitter for RGBA8888 to BGRA8888. */
847 grub_video_fbblit_blend_BGRA8888_RGBA8888 (struct grub_video_fbblit_info
*dst
,
848 struct grub_video_fbblit_info
*src
,
850 int width
, int height
,
851 int offset_x
, int offset_y
)
853 grub_uint32_t
*srcptr
;
854 grub_uint32_t
*dstptr
;
855 unsigned int srcrowskip
;
856 unsigned int dstrowskip
;
860 /* Calculate the number of bytes to advance from the end of one line
861 to the beginning of the next line. */
862 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
863 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
865 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
866 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
868 for (j
= 0; j
< height
; j
++)
870 for (i
= 0; i
< width
; i
++)
887 /* Skip transparent source pixels. */
892 sr
= (color
>> 0) & 0xFF;
893 sg
= (color
>> 8) & 0xFF;
894 sb
= (color
>> 16) & 0xFF;
898 /* Opaque pixel shortcut. */
905 /* General pixel color blending. */
908 dr
= (color
>> 16) & 0xFF;
909 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
910 dg
= (color
>> 8) & 0xFF;
911 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
912 db
= (color
>> 0) & 0xFF;
913 db
= (db
* (255 - a
) + sb
* a
) / 255;
916 color
= (a
<< 24) | (dr
<< 16) | (dg
<< 8) | db
;
921 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
922 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
926 /* Optimized blending blitter for RGBA8888 to BGR888. */
928 grub_video_fbblit_blend_BGR888_RGBA8888 (struct grub_video_fbblit_info
*dst
,
929 struct grub_video_fbblit_info
*src
,
931 int width
, int height
,
932 int offset_x
, int offset_y
)
934 grub_uint32_t
*srcptr
;
935 grub_uint8_t
*dstptr
;
936 unsigned int srcrowskip
;
937 unsigned int dstrowskip
;
941 /* Calculate the number of bytes to advance from the end of one line
942 to the beginning of the next line. */
943 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
944 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
946 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
947 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
949 for (j
= 0; j
< height
; j
++)
951 for (i
= 0; i
< width
; i
++)
968 /* Skip transparent source pixels. */
973 sr
= (color
>> 0) & 0xFF;
974 sg
= (color
>> 8) & 0xFF;
975 sb
= (color
>> 16) & 0xFF;
979 /* Opaque pixel shortcut. */
986 /* General pixel color blending. */
989 #ifndef GRUB_CPU_WORDS_BIGENDIAN
999 db
= (db
* (255 - a
) + sb
* a
) / 255;
1000 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
1001 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
1004 #ifndef GRUB_CPU_WORDS_BIGENDIAN
1015 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
1016 dstptr
+= dstrowskip
;
1020 /* Optimized blending blitter for RGBA888 to RGBA8888. */
1022 grub_video_fbblit_blend_RGBA8888_RGBA8888 (struct grub_video_fbblit_info
*dst
,
1023 struct grub_video_fbblit_info
*src
,
1025 int width
, int height
,
1026 int offset_x
, int offset_y
)
1028 grub_uint32_t color
;
1031 grub_uint32_t
*srcptr
;
1032 grub_uint32_t
*dstptr
;
1040 grub_size_t srcrowskip
;
1041 grub_size_t dstrowskip
;
1043 srcrowskip
= src
->mode_info
->pitch
- 4 * width
;
1044 dstrowskip
= dst
->mode_info
->pitch
- 4 * width
;
1046 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
1047 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
1049 for (j
= 0; j
< height
; j
++)
1051 for (i
= 0; i
< width
; i
++)
1069 sr
= (color
>> 0) & 0xFF;
1070 sg
= (color
>> 8) & 0xFF;
1071 sb
= (color
>> 16) & 0xFF;
1075 dr
= (color
>> 0) & 0xFF;
1076 dg
= (color
>> 8) & 0xFF;
1077 db
= (color
>> 16) & 0xFF;
1079 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
1080 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
1081 db
= (db
* (255 - a
) + sb
* a
) / 255;
1083 color
= (a
<< 24) | (db
<< 16) | (dg
<< 8) | dr
;
1087 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
1088 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
1092 /* Optimized blending blitter for RGBA8888 to RGB888. */
1094 grub_video_fbblit_blend_RGB888_RGBA8888 (struct grub_video_fbblit_info
*dst
,
1095 struct grub_video_fbblit_info
*src
,
1097 int width
, int height
,
1098 int offset_x
, int offset_y
)
1100 grub_uint32_t color
;
1103 grub_uint32_t
*srcptr
;
1104 grub_uint8_t
*dstptr
;
1112 grub_size_t srcrowskip
;
1113 grub_size_t dstrowskip
;
1115 srcrowskip
= src
->mode_info
->pitch
- 4 * width
;
1116 dstrowskip
= dst
->mode_info
->pitch
- 3 * width
;
1118 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
1119 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
1121 for (j
= 0; j
< height
; j
++)
1123 for (i
= 0; i
< width
; i
++)
1135 sr
= (color
>> 0) & 0xFF;
1136 sg
= (color
>> 8) & 0xFF;
1137 sb
= (color
>> 16) & 0xFF;
1141 #ifndef GRUB_CPU_WORDS_BIGENDIAN
1154 #ifndef GRUB_CPU_WORDS_BIGENDIAN
1164 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
1165 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
1166 db
= (db
* (255 - a
) + sb
* a
) / 255;
1168 #ifndef GRUB_CPU_WORDS_BIGENDIAN
1178 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
1179 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
1183 /* Optimized blending blitter for RGBA8888 to indexed color. */
1185 grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info
*dst
,
1186 struct grub_video_fbblit_info
*src
,
1188 int width
, int height
,
1189 int offset_x
, int offset_y
)
1191 grub_uint32_t color
;
1194 grub_uint32_t
*srcptr
;
1195 grub_uint8_t
*dstptr
;
1204 grub_size_t srcrowskip
;
1205 grub_size_t dstrowskip
;
1207 srcrowskip
= src
->mode_info
->pitch
- 4 * width
;
1208 dstrowskip
= dst
->mode_info
->pitch
- width
;
1210 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
1211 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
1213 for (j
= 0; j
< height
; j
++)
1215 for (i
= 0; i
< width
; i
++)
1227 sr
= (color
>> 0) & 0xFF;
1228 sg
= (color
>> 8) & 0xFF;
1229 sb
= (color
>> 16) & 0xFF;
1233 color
= grub_video_fb_map_rgb(sr
, sg
, sb
);
1234 *dstptr
++ = color
& 0xFF;
1238 grub_video_fb_unmap_color_int (dst
, *dstptr
, &dr
, &dg
, &db
, &da
);
1240 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
1241 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
1242 db
= (db
* (255 - a
) + sb
* a
) / 255;
1244 color
= grub_video_fb_map_rgb(dr
, dg
, db
);
1246 *dstptr
++ = color
& 0xFF;
1248 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
1249 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
1253 /* Optimized blending blitter for 1-bit to XXXA8888. */
1255 grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info
*dst
,
1256 struct grub_video_fbblit_info
*src
,
1258 int width
, int height
,
1259 int offset_x
, int offset_y
)
1263 grub_uint8_t
*srcptr
;
1264 grub_uint32_t
*dstptr
;
1265 grub_uint8_t srcmask
;
1266 unsigned int dstrowskip
;
1267 unsigned int srcrowskipbyte
, srcrowskipbit
;
1268 grub_uint32_t fgcolor
, bgcolor
;
1271 /* Calculate the number of bytes to advance from the end of one line
1272 to the beginning of the next line. */
1273 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
1274 srcrowskipbyte
= (src
->mode_info
->width
- width
) >> 3;
1275 srcrowskipbit
= (src
->mode_info
->width
- width
) & 7;
1277 bit_index
= offset_y
* src
->mode_info
->width
+ offset_x
;
1278 srcptr
= (grub_uint8_t
*) src
->data
+ (bit_index
>> 3);
1279 srcmask
= 1 << (~bit_index
& 7);
1280 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
1282 fgcolor
= grub_video_fb_map_rgba (src
->mode_info
->fg_red
,
1283 src
->mode_info
->fg_green
,
1284 src
->mode_info
->fg_blue
,
1285 src
->mode_info
->fg_alpha
);
1287 bgcolor
= grub_video_fb_map_rgba (src
->mode_info
->bg_red
,
1288 src
->mode_info
->bg_green
,
1289 src
->mode_info
->bg_blue
,
1290 src
->mode_info
->bg_alpha
);
1292 for (j
= 0; j
< height
; j
++)
1294 for (i
= 0; i
< width
; i
++)
1296 grub_uint32_t color
;
1299 if (*srcptr
& srcmask
)
1302 a
= src
->mode_info
->fg_alpha
;
1307 a
= src
->mode_info
->bg_alpha
;
1314 grub_uint8_t s1
= (color
>> 0) & 0xFF;
1315 grub_uint8_t s2
= (color
>> 8) & 0xFF;
1316 grub_uint8_t s3
= (color
>> 16) & 0xFF;
1318 grub_uint8_t d1
= (*dstptr
>> 0) & 0xFF;
1319 grub_uint8_t d2
= (*dstptr
>> 8) & 0xFF;
1320 grub_uint8_t d3
= (*dstptr
>> 16) & 0xFF;
1322 d1
= (d1
* (255 - a
) + s1
* a
) / 255;
1323 d2
= (d2
* (255 - a
) + s2
* a
) / 255;
1324 d3
= (d3
* (255 - a
) + s3
* a
) / 255;
1326 *dstptr
= (a
<< 24) | (d3
<< 16) | (d2
<< 8) | d1
;
1339 srcptr
+= srcrowskipbyte
;
1340 if (srcmask
>> srcrowskipbit
)
1341 srcmask
>>= srcrowskipbit
;
1345 srcmask
<<= 8 - srcrowskipbit
;
1347 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
1351 /* Optimized blending blitter for 1-bit to XXX888. */
1352 #ifdef GRUB_HAVE_UNALIGNED_ACCESS
1354 grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info
*dst
,
1355 struct grub_video_fbblit_info
*src
,
1357 int width
, int height
,
1358 int offset_x
, int offset_y
)
1362 grub_uint8_t
*srcptr
;
1363 grub_uint8_t
*dstptr
;
1364 grub_uint8_t srcmask
;
1365 unsigned int dstrowskip
;
1366 unsigned int srcrowskipbyte
, srcrowskipbit
;
1367 grub_uint32_t fgcolor
, bgcolor
;
1370 /* Calculate the number of bytes to advance from the end of one line
1371 to the beginning of the next line. */
1372 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
1373 srcrowskipbyte
= (src
->mode_info
->width
- width
) >> 3;
1374 srcrowskipbit
= (src
->mode_info
->width
- width
) & 7;
1376 bit_index
= offset_y
* src
->mode_info
->width
+ offset_x
;
1377 srcptr
= (grub_uint8_t
*) src
->data
+ (bit_index
>> 3);
1378 srcmask
= 1 << (~bit_index
& 7);
1379 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
1381 fgcolor
= grub_video_fb_map_rgba (src
->mode_info
->fg_red
,
1382 src
->mode_info
->fg_green
,
1383 src
->mode_info
->fg_blue
,
1384 src
->mode_info
->fg_alpha
);
1386 bgcolor
= grub_video_fb_map_rgba (src
->mode_info
->bg_red
,
1387 src
->mode_info
->bg_green
,
1388 src
->mode_info
->bg_blue
,
1389 src
->mode_info
->bg_alpha
);
1391 for (j
= 0; j
< height
; j
++)
1393 for (i
= 0; i
< width
; i
++)
1395 grub_uint32_t color
;
1397 if (*srcptr
& srcmask
)
1400 a
= src
->mode_info
->fg_alpha
;
1405 a
= src
->mode_info
->bg_alpha
;
1410 #ifndef GRUB_CPU_WORDS_BIGENDIAN
1411 ((grub_uint8_t
*) dstptr
)[0] = color
& 0xff;
1412 ((grub_uint8_t
*) dstptr
)[1] = (color
& 0xff00) >> 8;
1413 ((grub_uint8_t
*) dstptr
)[2] = (color
& 0xff0000) >> 16;
1415 ((grub_uint8_t
*) dstptr
)[2] = color
& 0xff;
1416 ((grub_uint8_t
*) dstptr
)[1] = (color
& 0xff00) >> 8;
1417 ((grub_uint8_t
*) dstptr
)[0] = (color
& 0xff0000) >> 16;
1422 grub_uint8_t s1
= (color
>> 0) & 0xFF;
1423 grub_uint8_t s2
= (color
>> 8) & 0xFF;
1424 grub_uint8_t s3
= (color
>> 16) & 0xFF;
1426 grub_uint8_t d1
= (*(grub_uint32_t
*) dstptr
>> 0) & 0xFF;
1427 grub_uint8_t d2
= (*(grub_uint32_t
*) dstptr
>> 8) & 0xFF;
1428 grub_uint8_t d3
= (*(grub_uint32_t
*) dstptr
>> 16) & 0xFF;
1430 ((grub_uint8_t
*) dstptr
)[0] = (d1
* (255 - a
) + s1
* a
) / 255;
1431 ((grub_uint8_t
*) dstptr
)[1] = (d2
* (255 - a
) + s2
* a
) / 255;
1432 ((grub_uint8_t
*) dstptr
)[2] = (d3
* (255 - a
) + s3
* a
) / 255;
1445 srcptr
+= srcrowskipbyte
;
1446 if (srcmask
>> srcrowskipbit
)
1447 srcmask
>>= srcrowskipbit
;
1451 srcmask
<<= 8 - srcrowskipbit
;
1453 dstptr
+= dstrowskip
;
1458 /* Optimized blending blitter for 1-bit to XXX888. */
1460 grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info
*dst
,
1461 struct grub_video_fbblit_info
*src
,
1463 int width
, int height
,
1464 int offset_x
, int offset_y
)
1468 grub_uint8_t
*srcptr
;
1469 grub_uint16_t
*dstptr
;
1470 grub_uint8_t srcmask
;
1471 unsigned int dstrowskip
;
1472 unsigned int srcrowskipbyte
, srcrowskipbit
;
1473 grub_uint16_t fgcolor
, bgcolor
;
1476 /* Calculate the number of bytes to advance from the end of one line
1477 to the beginning of the next line. */
1478 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
1479 srcrowskipbyte
= (src
->mode_info
->width
- width
) >> 3;
1480 srcrowskipbit
= (src
->mode_info
->width
- width
) & 7;
1482 bit_index
= offset_y
* src
->mode_info
->width
+ offset_x
;
1483 srcptr
= (grub_uint8_t
*) src
->data
+ (bit_index
>> 3);
1484 srcmask
= 1 << (~bit_index
& 7);
1485 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
1487 fgcolor
= grub_video_fb_map_rgba (src
->mode_info
->fg_red
,
1488 src
->mode_info
->fg_green
,
1489 src
->mode_info
->fg_blue
,
1490 src
->mode_info
->fg_alpha
);
1492 bgcolor
= grub_video_fb_map_rgba (src
->mode_info
->bg_red
,
1493 src
->mode_info
->bg_green
,
1494 src
->mode_info
->bg_blue
,
1495 src
->mode_info
->bg_alpha
);
1497 for (j
= 0; j
< height
; j
++)
1499 for (i
= 0; i
< width
; i
++)
1501 grub_uint32_t color
;
1503 if (*srcptr
& srcmask
)
1506 a
= src
->mode_info
->fg_alpha
;
1511 a
= src
->mode_info
->bg_alpha
;
1518 grub_uint8_t s1
= (color
>> 0) & 0x1F;
1519 grub_uint8_t s2
= (color
>> 5) & 0x3F;
1520 grub_uint8_t s3
= (color
>> 11) & 0x1F;
1522 grub_uint8_t d1
= (*dstptr
>> 0) & 0x1F;
1523 grub_uint8_t d2
= (*dstptr
>> 5) & 0x3F;
1524 grub_uint8_t d3
= (*dstptr
>> 11) & 0x1F;
1526 d1
= (d1
* (255 - a
) + s1
* a
) / 255;
1527 d2
= (d2
* (255 - a
) + s2
* a
) / 255;
1528 d3
= (d3
* (255 - a
) + s3
* a
) / 255;
1530 *dstptr
= (d1
& 0x1f) | ((d2
& 0x3f) << 5) | ((d3
& 0x1f) << 11);
1543 srcptr
+= srcrowskipbyte
;
1544 if (srcmask
>> srcrowskipbit
)
1545 srcmask
>>= srcrowskipbit
;
1549 srcmask
<<= 8 - srcrowskipbit
;
1551 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);