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 grub_uint8_t r
= *srcptr
++;
420 grub_uint8_t g
= *srcptr
++;
421 grub_uint8_t b
= *srcptr
++;
422 grub_uint8_t a
= *srcptr
++;
430 srcptr
+= srcrowskip
;
431 dstptr
+= dstrowskip
;
435 /* Optimized replacing blitter for RGB888 to BGRX8888. */
437 grub_video_fbblit_replace_BGRX8888_RGB888 (struct grub_video_fbblit_info
*dst
,
438 struct grub_video_fbblit_info
*src
,
440 int width
, int height
,
441 int offset_x
, int offset_y
)
445 grub_uint8_t
*srcptr
;
446 grub_uint8_t
*dstptr
;
447 unsigned int srcrowskip
;
448 unsigned int dstrowskip
;
450 /* Calculate the number of bytes to advance from the end of one line
451 to the beginning of the next line. */
452 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
453 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
455 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
456 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
458 for (j
= 0; j
< height
; j
++)
460 for (i
= 0; i
< width
; i
++)
462 grub_uint8_t r
= *srcptr
++;
463 grub_uint8_t g
= *srcptr
++;
464 grub_uint8_t b
= *srcptr
++;
470 /* Set alpha component as opaque. */
474 srcptr
+= srcrowskip
;
475 dstptr
+= dstrowskip
;
479 /* Optimized replacing blitter for RGBX8888 to BGR888. */
481 grub_video_fbblit_replace_BGR888_RGBX8888 (struct grub_video_fbblit_info
*dst
,
482 struct grub_video_fbblit_info
*src
,
484 int width
, int height
,
485 int offset_x
, int offset_y
)
487 grub_uint32_t
*srcptr
;
488 grub_uint8_t
*dstptr
;
489 unsigned int srcrowskip
;
490 unsigned int dstrowskip
;
494 /* Calculate the number of bytes to advance from the end of one line
495 to the beginning of the next line. */
496 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
497 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
499 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
500 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
502 for (j
= 0; j
< height
; j
++)
504 for (i
= 0; i
< width
; i
++)
513 sr
= (color
>> 0) & 0xFF;
514 sg
= (color
>> 8) & 0xFF;
515 sb
= (color
>> 16) & 0xFF;
522 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
523 dstptr
+= dstrowskip
;
527 /* Optimized replacing blitter for RGB888 to BGR888. */
529 grub_video_fbblit_replace_BGR888_RGB888 (struct grub_video_fbblit_info
*dst
,
530 struct grub_video_fbblit_info
*src
,
532 int width
, int height
,
533 int offset_x
, int offset_y
)
537 grub_uint8_t
*srcptr
;
538 grub_uint8_t
*dstptr
;
539 unsigned int srcrowskip
;
540 unsigned int dstrowskip
;
542 /* Calculate the number of bytes to advance from the end of one line
543 to the beginning of the next line. */
544 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
545 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
547 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
548 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
550 for (j
= 0; j
< height
; j
++)
552 for (i
= 0; i
< width
; i
++)
554 grub_uint8_t r
= *srcptr
++;
555 grub_uint8_t g
= *srcptr
++;
556 grub_uint8_t b
= *srcptr
++;
563 srcptr
+= srcrowskip
;
564 dstptr
+= dstrowskip
;
568 /* Optimized replacing blitter for RGB888 to RGBX8888. */
570 grub_video_fbblit_replace_RGBX8888_RGB888 (struct grub_video_fbblit_info
*dst
,
571 struct grub_video_fbblit_info
*src
,
573 int width
, int height
,
574 int offset_x
, int offset_y
)
579 grub_uint8_t
*srcptr
;
580 grub_uint32_t
*dstptr
;
584 grub_size_t srcrowskip
;
585 grub_size_t dstrowskip
;
587 srcrowskip
= src
->mode_info
->pitch
- 3 * width
;
588 dstrowskip
= dst
->mode_info
->pitch
- 4 * width
;
589 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
590 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
592 for (j
= 0; j
< height
; j
++)
594 for (i
= 0; i
< width
; i
++)
600 /* Set alpha as opaque. */
601 color
= 0xFF000000 | (sb
<< 16) | (sg
<< 8) | sr
;
605 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
606 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
610 /* Optimized replacing blitter for RGBX8888 to RGB888. */
612 grub_video_fbblit_replace_RGB888_RGBX8888 (struct grub_video_fbblit_info
*dst
,
613 struct grub_video_fbblit_info
*src
,
615 int width
, int height
,
616 int offset_x
, int offset_y
)
621 grub_uint32_t
*srcptr
;
622 grub_uint8_t
*dstptr
;
626 grub_size_t srcrowskip
;
627 grub_size_t dstrowskip
;
629 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
630 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
631 srcrowskip
= src
->mode_info
->pitch
- 4 * width
;
632 dstrowskip
= dst
->mode_info
->pitch
- 3 * width
;
634 for (j
= 0; j
< height
; j
++)
636 for (i
= 0; i
< width
; i
++)
640 sr
= (color
>> 0) & 0xFF;
641 sg
= (color
>> 8) & 0xFF;
642 sb
= (color
>> 16) & 0xFF;
648 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
649 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
653 /* Optimized replacing blitter for RGBX8888 to indexed color. */
655 grub_video_fbblit_replace_index_RGBX8888 (struct grub_video_fbblit_info
*dst
,
656 struct grub_video_fbblit_info
*src
,
658 int width
, int height
,
659 int offset_x
, int offset_y
)
664 grub_uint32_t
*srcptr
;
665 grub_uint8_t
*dstptr
;
669 grub_size_t srcrowskip
;
670 grub_size_t dstrowskip
;
672 srcrowskip
= src
->mode_info
->pitch
- 4 * width
;
673 dstrowskip
= dst
->mode_info
->pitch
- width
;
675 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
676 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
678 for (j
= 0; j
< height
; j
++)
680 for (i
= 0; i
< width
; i
++)
684 sr
= (color
>> 0) & 0xFF;
685 sg
= (color
>> 8) & 0xFF;
686 sb
= (color
>> 16) & 0xFF;
688 color
= grub_video_fb_map_rgb(sr
, sg
, sb
);
689 *dstptr
++ = color
& 0xFF;
691 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
692 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
696 /* Optimized replacing blitter for RGB888 to indexed color. */
698 grub_video_fbblit_replace_index_RGB888 (struct grub_video_fbblit_info
*dst
,
699 struct grub_video_fbblit_info
*src
,
701 int width
, int height
,
702 int offset_x
, int offset_y
)
707 grub_uint8_t
*srcptr
;
708 grub_uint8_t
*dstptr
;
712 grub_size_t srcrowskip
;
713 grub_size_t dstrowskip
;
715 srcrowskip
= src
->mode_info
->pitch
- 3 * width
;
716 dstrowskip
= dst
->mode_info
->pitch
- width
;
718 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
719 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
721 for (j
= 0; j
< height
; j
++)
723 for (i
= 0; i
< width
; i
++)
729 color
= grub_video_fb_map_rgb(sr
, sg
, sb
);
731 *dstptr
++ = color
& 0xFF;
733 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
734 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
738 /* Generic blending blitter. Works for every supported format. */
740 grub_video_fbblit_blend (struct grub_video_fbblit_info
*dst
,
741 struct grub_video_fbblit_info
*src
,
742 int x
, int y
, int width
, int height
,
743 int offset_x
, int offset_y
)
748 for (j
= 0; j
< height
; j
++)
750 for (i
= 0; i
< width
; i
++)
752 grub_uint8_t src_red
;
753 grub_uint8_t src_green
;
754 grub_uint8_t src_blue
;
755 grub_uint8_t src_alpha
;
756 grub_uint8_t dst_red
;
757 grub_uint8_t dst_green
;
758 grub_uint8_t dst_blue
;
759 grub_uint8_t dst_alpha
;
760 grub_video_color_t src_color
;
761 grub_video_color_t dst_color
;
763 src_color
= get_pixel (src
, i
+ offset_x
, j
+ offset_y
);
764 grub_video_fb_unmap_color_int (src
, src_color
, &src_red
, &src_green
,
765 &src_blue
, &src_alpha
);
770 if (src_alpha
== 255)
772 dst_color
= grub_video_fb_map_rgba (src_red
, src_green
,
773 src_blue
, src_alpha
);
774 set_pixel (dst
, x
+ i
, y
+ j
, dst_color
);
778 dst_color
= get_pixel (dst
, x
+ i
, y
+ j
);
780 grub_video_fb_unmap_color_int (dst
, dst_color
, &dst_red
,
781 &dst_green
, &dst_blue
, &dst_alpha
);
783 dst_red
= (((src_red
* src_alpha
)
784 + (dst_red
* (255 - src_alpha
))) / 255);
785 dst_green
= (((src_green
* src_alpha
)
786 + (dst_green
* (255 - src_alpha
))) / 255);
787 dst_blue
= (((src_blue
* src_alpha
)
788 + (dst_blue
* (255 - src_alpha
))) / 255);
790 dst_alpha
= src_alpha
;
791 dst_color
= grub_video_fb_map_rgba (dst_red
, dst_green
, dst_blue
,
794 set_pixel (dst
, x
+ i
, y
+ j
, dst_color
);
799 /* Optimized blending blitter for RGBA8888 to BGRA8888. */
801 grub_video_fbblit_blend_BGRA8888_RGBA8888 (struct grub_video_fbblit_info
*dst
,
802 struct grub_video_fbblit_info
*src
,
804 int width
, int height
,
805 int offset_x
, int offset_y
)
807 grub_uint32_t
*srcptr
;
808 grub_uint32_t
*dstptr
;
809 unsigned int srcrowskip
;
810 unsigned int dstrowskip
;
814 /* Calculate the number of bytes to advance from the end of one line
815 to the beginning of the next line. */
816 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
817 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
819 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
820 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
822 for (j
= 0; j
< height
; j
++)
824 for (i
= 0; i
< width
; i
++)
841 /* Skip transparent source pixels. */
846 sr
= (color
>> 0) & 0xFF;
847 sg
= (color
>> 8) & 0xFF;
848 sb
= (color
>> 16) & 0xFF;
852 /* Opaque pixel shortcut. */
859 /* General pixel color blending. */
862 dr
= (color
>> 16) & 0xFF;
863 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
864 dg
= (color
>> 8) & 0xFF;
865 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
866 db
= (color
>> 0) & 0xFF;
867 db
= (db
* (255 - a
) + sb
* a
) / 255;
870 color
= (a
<< 24) | (dr
<< 16) | (dg
<< 8) | db
;
875 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
876 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
880 /* Optimized blending blitter for RGBA8888 to BGR888. */
882 grub_video_fbblit_blend_BGR888_RGBA8888 (struct grub_video_fbblit_info
*dst
,
883 struct grub_video_fbblit_info
*src
,
885 int width
, int height
,
886 int offset_x
, int offset_y
)
888 grub_uint32_t
*srcptr
;
889 grub_uint8_t
*dstptr
;
890 unsigned int srcrowskip
;
891 unsigned int dstrowskip
;
895 /* Calculate the number of bytes to advance from the end of one line
896 to the beginning of the next line. */
897 srcrowskip
= src
->mode_info
->pitch
- src
->mode_info
->bytes_per_pixel
* width
;
898 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
900 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
901 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
903 for (j
= 0; j
< height
; j
++)
905 for (i
= 0; i
< width
; i
++)
922 /* Skip transparent source pixels. */
927 sr
= (color
>> 0) & 0xFF;
928 sg
= (color
>> 8) & 0xFF;
929 sb
= (color
>> 16) & 0xFF;
933 /* Opaque pixel shortcut. */
940 /* General pixel color blending. */
944 db
= (db
* (255 - a
) + sb
* a
) / 255;
946 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
948 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
956 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
957 dstptr
+= dstrowskip
;
961 /* Optimized blending blitter for RGBA888 to RGBA8888. */
963 grub_video_fbblit_blend_RGBA8888_RGBA8888 (struct grub_video_fbblit_info
*dst
,
964 struct grub_video_fbblit_info
*src
,
966 int width
, int height
,
967 int offset_x
, int offset_y
)
972 grub_uint32_t
*srcptr
;
973 grub_uint32_t
*dstptr
;
981 grub_size_t srcrowskip
;
982 grub_size_t dstrowskip
;
984 srcrowskip
= src
->mode_info
->pitch
- 4 * width
;
985 dstrowskip
= dst
->mode_info
->pitch
- 4 * width
;
987 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
988 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
990 for (j
= 0; j
< height
; j
++)
992 for (i
= 0; i
< width
; i
++)
1010 sr
= (color
>> 0) & 0xFF;
1011 sg
= (color
>> 8) & 0xFF;
1012 sb
= (color
>> 16) & 0xFF;
1016 dr
= (color
>> 0) & 0xFF;
1017 dg
= (color
>> 8) & 0xFF;
1018 db
= (color
>> 16) & 0xFF;
1020 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
1021 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
1022 db
= (db
* (255 - a
) + sb
* a
) / 255;
1024 color
= (a
<< 24) | (db
<< 16) | (dg
<< 8) | dr
;
1028 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
1029 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
1033 /* Optimized blending blitter for RGBA8888 to RGB888. */
1035 grub_video_fbblit_blend_RGB888_RGBA8888 (struct grub_video_fbblit_info
*dst
,
1036 struct grub_video_fbblit_info
*src
,
1038 int width
, int height
,
1039 int offset_x
, int offset_y
)
1041 grub_uint32_t color
;
1044 grub_uint32_t
*srcptr
;
1045 grub_uint8_t
*dstptr
;
1053 grub_size_t srcrowskip
;
1054 grub_size_t dstrowskip
;
1056 srcrowskip
= src
->mode_info
->pitch
- 4 * width
;
1057 dstrowskip
= dst
->mode_info
->pitch
- 3 * width
;
1059 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
1060 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
1062 for (j
= 0; j
< height
; j
++)
1064 for (i
= 0; i
< width
; i
++)
1076 sr
= (color
>> 0) & 0xFF;
1077 sg
= (color
>> 8) & 0xFF;
1078 sb
= (color
>> 16) & 0xFF;
1093 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
1094 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
1095 db
= (db
* (255 - a
) + sb
* a
) / 255;
1101 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
1102 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
1106 /* Optimized blending blitter for RGBA8888 to indexed color. */
1108 grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info
*dst
,
1109 struct grub_video_fbblit_info
*src
,
1111 int width
, int height
,
1112 int offset_x
, int offset_y
)
1114 grub_uint32_t color
;
1117 grub_uint32_t
*srcptr
;
1118 grub_uint8_t
*dstptr
;
1127 grub_size_t srcrowskip
;
1128 grub_size_t dstrowskip
;
1130 srcrowskip
= src
->mode_info
->pitch
- 4 * width
;
1131 dstrowskip
= dst
->mode_info
->pitch
- width
;
1133 srcptr
= grub_video_fb_get_video_ptr (src
, offset_x
, offset_y
);
1134 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
1136 for (j
= 0; j
< height
; j
++)
1138 for (i
= 0; i
< width
; i
++)
1150 sr
= (color
>> 0) & 0xFF;
1151 sg
= (color
>> 8) & 0xFF;
1152 sb
= (color
>> 16) & 0xFF;
1156 color
= grub_video_fb_map_rgb(sr
, sg
, sb
);
1157 *dstptr
++ = color
& 0xFF;
1161 grub_video_fb_unmap_color_int (dst
, *dstptr
, &dr
, &dg
, &db
, &da
);
1163 dr
= (dr
* (255 - a
) + sr
* a
) / 255;
1164 dg
= (dg
* (255 - a
) + sg
* a
) / 255;
1165 db
= (db
* (255 - a
) + sb
* a
) / 255;
1167 color
= grub_video_fb_map_rgb(dr
, dg
, db
);
1169 *dstptr
++ = color
& 0xFF;
1171 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr
, srcrowskip
);
1172 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
1176 /* Optimized blending blitter for 1-bit to XXXA8888. */
1178 grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info
*dst
,
1179 struct grub_video_fbblit_info
*src
,
1181 int width
, int height
,
1182 int offset_x
, int offset_y
)
1186 grub_uint8_t
*srcptr
;
1187 grub_uint32_t
*dstptr
;
1188 grub_uint8_t srcmask
;
1189 unsigned int dstrowskip
;
1190 unsigned int srcrowskipbyte
, srcrowskipbit
;
1191 grub_uint32_t fgcolor
, bgcolor
;
1194 /* Calculate the number of bytes to advance from the end of one line
1195 to the beginning of the next line. */
1196 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
1197 srcrowskipbyte
= (src
->mode_info
->width
- width
) >> 3;
1198 srcrowskipbit
= (src
->mode_info
->width
- width
) & 7;
1200 bit_index
= offset_y
* src
->mode_info
->width
+ offset_x
;
1201 srcptr
= (grub_uint8_t
*) src
->data
+ (bit_index
>> 3);
1202 srcmask
= 1 << (~bit_index
& 7);
1203 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
1205 fgcolor
= grub_video_fb_map_rgba (src
->mode_info
->fg_red
,
1206 src
->mode_info
->fg_green
,
1207 src
->mode_info
->fg_blue
,
1208 src
->mode_info
->fg_alpha
);
1210 bgcolor
= grub_video_fb_map_rgba (src
->mode_info
->bg_red
,
1211 src
->mode_info
->bg_green
,
1212 src
->mode_info
->bg_blue
,
1213 src
->mode_info
->bg_alpha
);
1215 for (j
= 0; j
< height
; j
++)
1217 for (i
= 0; i
< width
; i
++)
1219 grub_uint32_t color
;
1222 if (*srcptr
& srcmask
)
1225 a
= src
->mode_info
->fg_alpha
;
1230 a
= src
->mode_info
->bg_alpha
;
1237 grub_uint8_t s1
= (color
>> 0) & 0xFF;
1238 grub_uint8_t s2
= (color
>> 8) & 0xFF;
1239 grub_uint8_t s3
= (color
>> 16) & 0xFF;
1241 grub_uint8_t d1
= (*dstptr
>> 0) & 0xFF;
1242 grub_uint8_t d2
= (*dstptr
>> 8) & 0xFF;
1243 grub_uint8_t d3
= (*dstptr
>> 16) & 0xFF;
1245 d1
= (d1
* (255 - a
) + s1
* a
) / 255;
1246 d2
= (d2
* (255 - a
) + s2
* a
) / 255;
1247 d3
= (d3
* (255 - a
) + s3
* a
) / 255;
1249 *dstptr
= (a
<< 24) | (d3
<< 16) | (d2
<< 8) | d1
;
1262 srcptr
+= srcrowskipbyte
;
1263 if (srcmask
>> srcrowskipbit
)
1264 srcmask
>>= srcrowskipbit
;
1268 srcmask
<<= 8 - srcrowskipbit
;
1270 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);
1274 /* Optimized blending blitter for 1-bit to XXX888. */
1275 #ifdef GRUB_HAVE_UNALIGNED_ACCESS
1277 grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info
*dst
,
1278 struct grub_video_fbblit_info
*src
,
1280 int width
, int height
,
1281 int offset_x
, int offset_y
)
1285 grub_uint8_t
*srcptr
;
1286 grub_uint8_t
*dstptr
;
1287 grub_uint8_t srcmask
;
1288 unsigned int dstrowskip
;
1289 unsigned int srcrowskipbyte
, srcrowskipbit
;
1290 grub_uint32_t fgcolor
, bgcolor
;
1293 /* Calculate the number of bytes to advance from the end of one line
1294 to the beginning of the next line. */
1295 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
1296 srcrowskipbyte
= (src
->mode_info
->width
- width
) >> 3;
1297 srcrowskipbit
= (src
->mode_info
->width
- width
) & 7;
1299 bit_index
= offset_y
* src
->mode_info
->width
+ offset_x
;
1300 srcptr
= (grub_uint8_t
*) src
->data
+ (bit_index
>> 3);
1301 srcmask
= 1 << (~bit_index
& 7);
1302 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
1304 fgcolor
= grub_video_fb_map_rgba (src
->mode_info
->fg_red
,
1305 src
->mode_info
->fg_green
,
1306 src
->mode_info
->fg_blue
,
1307 src
->mode_info
->fg_alpha
);
1309 bgcolor
= grub_video_fb_map_rgba (src
->mode_info
->bg_red
,
1310 src
->mode_info
->bg_green
,
1311 src
->mode_info
->bg_blue
,
1312 src
->mode_info
->bg_alpha
);
1314 for (j
= 0; j
< height
; j
++)
1316 for (i
= 0; i
< width
; i
++)
1318 grub_uint32_t color
;
1320 if (*srcptr
& srcmask
)
1323 a
= src
->mode_info
->fg_alpha
;
1328 a
= src
->mode_info
->bg_alpha
;
1333 ((grub_uint8_t
*) dstptr
)[0] = color
& 0xff;
1334 ((grub_uint8_t
*) dstptr
)[1] = (color
& 0xff00) >> 8;
1335 ((grub_uint8_t
*) dstptr
)[2] = (color
& 0xff0000) >> 16;
1339 grub_uint8_t s1
= (color
>> 0) & 0xFF;
1340 grub_uint8_t s2
= (color
>> 8) & 0xFF;
1341 grub_uint8_t s3
= (color
>> 16) & 0xFF;
1343 grub_uint8_t d1
= (*(grub_uint32_t
*) dstptr
>> 0) & 0xFF;
1344 grub_uint8_t d2
= (*(grub_uint32_t
*) dstptr
>> 8) & 0xFF;
1345 grub_uint8_t d3
= (*(grub_uint32_t
*) dstptr
>> 16) & 0xFF;
1347 ((grub_uint8_t
*) dstptr
)[0] = (d1
* (255 - a
) + s1
* a
) / 255;
1348 ((grub_uint8_t
*) dstptr
)[1] = (d2
* (255 - a
) + s2
* a
) / 255;
1349 ((grub_uint8_t
*) dstptr
)[2] = (d3
* (255 - a
) + s3
* a
) / 255;
1362 srcptr
+= srcrowskipbyte
;
1363 if (srcmask
>> srcrowskipbit
)
1364 srcmask
>>= srcrowskipbit
;
1368 srcmask
<<= 8 - srcrowskipbit
;
1370 dstptr
+= dstrowskip
;
1375 /* Optimized blending blitter for 1-bit to XXX888. */
1377 grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info
*dst
,
1378 struct grub_video_fbblit_info
*src
,
1380 int width
, int height
,
1381 int offset_x
, int offset_y
)
1385 grub_uint8_t
*srcptr
;
1386 grub_uint16_t
*dstptr
;
1387 grub_uint8_t srcmask
;
1388 unsigned int dstrowskip
;
1389 unsigned int srcrowskipbyte
, srcrowskipbit
;
1390 grub_uint16_t fgcolor
, bgcolor
;
1393 /* Calculate the number of bytes to advance from the end of one line
1394 to the beginning of the next line. */
1395 dstrowskip
= dst
->mode_info
->pitch
- dst
->mode_info
->bytes_per_pixel
* width
;
1396 srcrowskipbyte
= (src
->mode_info
->width
- width
) >> 3;
1397 srcrowskipbit
= (src
->mode_info
->width
- width
) & 7;
1399 bit_index
= offset_y
* src
->mode_info
->width
+ offset_x
;
1400 srcptr
= (grub_uint8_t
*) src
->data
+ (bit_index
>> 3);
1401 srcmask
= 1 << (~bit_index
& 7);
1402 dstptr
= grub_video_fb_get_video_ptr (dst
, x
, y
);
1404 fgcolor
= grub_video_fb_map_rgba (src
->mode_info
->fg_red
,
1405 src
->mode_info
->fg_green
,
1406 src
->mode_info
->fg_blue
,
1407 src
->mode_info
->fg_alpha
);
1409 bgcolor
= grub_video_fb_map_rgba (src
->mode_info
->bg_red
,
1410 src
->mode_info
->bg_green
,
1411 src
->mode_info
->bg_blue
,
1412 src
->mode_info
->bg_alpha
);
1414 for (j
= 0; j
< height
; j
++)
1416 for (i
= 0; i
< width
; i
++)
1418 grub_uint32_t color
;
1420 if (*srcptr
& srcmask
)
1423 a
= src
->mode_info
->fg_alpha
;
1428 a
= src
->mode_info
->bg_alpha
;
1435 grub_uint8_t s1
= (color
>> 0) & 0x1F;
1436 grub_uint8_t s2
= (color
>> 5) & 0x3F;
1437 grub_uint8_t s3
= (color
>> 11) & 0x1F;
1439 grub_uint8_t d1
= (*dstptr
>> 0) & 0x1F;
1440 grub_uint8_t d2
= (*dstptr
>> 5) & 0x3F;
1441 grub_uint8_t d3
= (*dstptr
>> 11) & 0x1F;
1443 d1
= (d1
* (255 - a
) + s1
* a
) / 255;
1444 d2
= (d2
* (255 - a
) + s2
* a
) / 255;
1445 d3
= (d3
* (255 - a
) + s3
* a
) / 255;
1447 *dstptr
= (d1
& 0x1f) | ((d2
& 0x3f) << 5) | ((d3
& 0x1f) << 11);
1460 srcptr
+= srcrowskipbyte
;
1461 if (srcmask
>> srcrowskipbit
)
1462 srcmask
>>= srcrowskipbit
;
1466 srcmask
<<= 8 - srcrowskipbit
;
1468 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr
, dstrowskip
);