Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / video / fb / fbblit.c
blob4d262d7103997bd8bd1d48e805a41ae511b5eec3
1 /*
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/>.
19 /* SPECIAL NOTES!
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
25 code for other archs.
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. */
38 void
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)
44 int i;
45 int j;
46 grub_uint8_t src_red;
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,
63 src_blue, src_alpha);
65 set_pixel (dst, x + i, y + j, dst_color);
70 /* Block copy replacing blitter. Works with modes multiple of 8 bits. */
71 void
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)
77 int j;
78 grub_uint32_t *srcptr;
79 grub_uint32_t *dstptr;
80 int bpp;
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. */
95 void
96 grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst,
97 struct grub_video_fbblit_info *src,
98 int x, int y,
99 int width, int height,
100 int offset_x, int offset_y)
102 int i;
103 int j;
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;
110 int bit_index;
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)
138 *dstptr = fgcolor;
139 else
140 *dstptr = bgcolor;
141 srcmask >>= 1;
142 if (!srcmask)
144 srcptr++;
145 srcmask = 0x80;
148 dstptr++;
151 srcptr += srcrowskipbyte;
152 if (srcmask >> srcrowskipbit)
153 srcmask >>= srcrowskipbit;
154 else
156 srcptr++;
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. */
166 void
167 grub_video_fbblit_replace_24bit_1bit (struct grub_video_fbblit_info *dst,
168 struct grub_video_fbblit_info *src,
169 int x, int y,
170 int width, int height,
171 int offset_x, int offset_y)
173 int i;
174 int j;
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;
181 int bit_index;
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;
210 else
211 *(grub_uint32_t *) dstptr = bgcolor;
212 srcmask >>= 1;
213 if (!srcmask)
215 srcptr++;
216 srcmask = 0x80;
219 dstptr += 3;
222 if (*srcptr & srcmask)
224 *dstptr++ = fgcolor & 0xff;
225 *dstptr++ = (fgcolor & 0xff00) >> 8;
226 *dstptr++ = (fgcolor & 0xff0000) >> 16;
228 else
230 *dstptr++ = bgcolor & 0xff;
231 *dstptr++ = (bgcolor & 0xff00) >> 8;
232 *dstptr++ = (bgcolor & 0xff0000) >> 16;
234 srcmask >>= 1;
235 if (!srcmask)
237 srcptr++;
238 srcmask = 0x80;
241 srcptr += srcrowskipbyte;
242 if (srcmask >> srcrowskipbit)
243 srcmask >>= srcrowskipbit;
244 else
246 srcptr++;
247 srcmask <<= 8 - srcrowskipbit;
249 dstptr += dstrowskip;
252 #endif
254 /* Optimized replacing blitter for 1-bit to 16-bit. */
255 void
256 grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst,
257 struct grub_video_fbblit_info *src,
258 int x, int y,
259 int width, int height,
260 int offset_x, int offset_y)
262 int i;
263 int j;
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;
270 int bit_index;
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)
298 *dstptr = fgcolor;
299 else
300 *dstptr = bgcolor;
301 srcmask >>= 1;
302 if (!srcmask)
304 srcptr++;
305 srcmask = 0x80;
308 dstptr++;
311 srcptr += srcrowskipbyte;
312 if (srcmask >> srcrowskipbit)
313 srcmask >>= srcrowskipbit;
314 else
316 srcptr++;
317 srcmask <<= 8 - srcrowskipbit;
319 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
323 /* Optimized replacing blitter for 1-bit to 8-bit. */
324 void
325 grub_video_fbblit_replace_8bit_1bit (struct grub_video_fbblit_info *dst,
326 struct grub_video_fbblit_info *src,
327 int x, int y,
328 int width, int height,
329 int offset_x, int offset_y)
331 int i;
332 int j;
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;
339 int bit_index;
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)
367 *dstptr = fgcolor;
368 else
369 *dstptr = bgcolor;
370 srcmask >>= 1;
371 if (!srcmask)
373 srcptr++;
374 srcmask = 0x80;
377 dstptr++;
380 srcptr += srcrowskipbyte;
381 if (srcmask >> srcrowskipbit)
382 srcmask >>= srcrowskipbit;
383 else
385 srcptr++;
386 srcmask <<= 8 - srcrowskipbit;
388 dstptr += dstrowskip;
392 /* Optimized replacing blitter for RGBX8888 to BGRX8888. */
393 void
394 grub_video_fbblit_replace_BGRX8888_RGBX8888 (struct grub_video_fbblit_info *dst,
395 struct grub_video_fbblit_info *src,
396 int x, int y,
397 int width, int height,
398 int offset_x, int offset_y)
400 int i;
401 int j;
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++;
424 *dstptr++ = b;
425 *dstptr++ = g;
426 *dstptr++ = r;
427 *dstptr++ = a;
430 srcptr += srcrowskip;
431 dstptr += dstrowskip;
435 /* Optimized replacing blitter for RGB888 to BGRX8888. */
436 void
437 grub_video_fbblit_replace_BGRX8888_RGB888 (struct grub_video_fbblit_info *dst,
438 struct grub_video_fbblit_info *src,
439 int x, int y,
440 int width, int height,
441 int offset_x, int offset_y)
443 int i;
444 int j;
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++;
466 *dstptr++ = b;
467 *dstptr++ = g;
468 *dstptr++ = r;
470 /* Set alpha component as opaque. */
471 *dstptr++ = 255;
474 srcptr += srcrowskip;
475 dstptr += dstrowskip;
479 /* Optimized replacing blitter for RGBX8888 to BGR888. */
480 void
481 grub_video_fbblit_replace_BGR888_RGBX8888 (struct grub_video_fbblit_info *dst,
482 struct grub_video_fbblit_info *src,
483 int x, int y,
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;
491 int i;
492 int j;
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++)
506 grub_uint32_t color;
507 grub_uint8_t sr;
508 grub_uint8_t sg;
509 grub_uint8_t sb;
511 color = *srcptr++;
513 sr = (color >> 0) & 0xFF;
514 sg = (color >> 8) & 0xFF;
515 sb = (color >> 16) & 0xFF;
517 *dstptr++ = sb;
518 *dstptr++ = sg;
519 *dstptr++ = sr;
522 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
523 dstptr += dstrowskip;
527 /* Optimized replacing blitter for RGB888 to BGR888. */
528 void
529 grub_video_fbblit_replace_BGR888_RGB888 (struct grub_video_fbblit_info *dst,
530 struct grub_video_fbblit_info *src,
531 int x, int y,
532 int width, int height,
533 int offset_x, int offset_y)
535 int i;
536 int j;
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++;
558 *dstptr++ = b;
559 *dstptr++ = g;
560 *dstptr++ = r;
563 srcptr += srcrowskip;
564 dstptr += dstrowskip;
568 /* Optimized replacing blitter for RGB888 to RGBX8888. */
569 void
570 grub_video_fbblit_replace_RGBX8888_RGB888 (struct grub_video_fbblit_info *dst,
571 struct grub_video_fbblit_info *src,
572 int x, int y,
573 int width, int height,
574 int offset_x, int offset_y)
576 grub_uint32_t color;
577 int i;
578 int j;
579 grub_uint8_t *srcptr;
580 grub_uint32_t *dstptr;
581 unsigned int sr;
582 unsigned int sg;
583 unsigned int sb;
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++)
596 sr = *srcptr++;
597 sg = *srcptr++;
598 sb = *srcptr++;
600 /* Set alpha as opaque. */
601 color = 0xFF000000 | (sb << 16) | (sg << 8) | sr;
603 *dstptr++ = color;
605 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
606 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
610 /* Optimized replacing blitter for RGBX8888 to RGB888. */
611 void
612 grub_video_fbblit_replace_RGB888_RGBX8888 (struct grub_video_fbblit_info *dst,
613 struct grub_video_fbblit_info *src,
614 int x, int y,
615 int width, int height,
616 int offset_x, int offset_y)
618 grub_uint32_t color;
619 int i;
620 int j;
621 grub_uint32_t *srcptr;
622 grub_uint8_t *dstptr;
623 unsigned int sr;
624 unsigned int sg;
625 unsigned int sb;
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++)
638 color = *srcptr++;
640 sr = (color >> 0) & 0xFF;
641 sg = (color >> 8) & 0xFF;
642 sb = (color >> 16) & 0xFF;
644 *dstptr++ = sr;
645 *dstptr++ = sg;
646 *dstptr++ = sb;
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. */
654 void
655 grub_video_fbblit_replace_index_RGBX8888 (struct grub_video_fbblit_info *dst,
656 struct grub_video_fbblit_info *src,
657 int x, int y,
658 int width, int height,
659 int offset_x, int offset_y)
661 grub_uint32_t color;
662 int i;
663 int j;
664 grub_uint32_t *srcptr;
665 grub_uint8_t *dstptr;
666 unsigned int sr;
667 unsigned int sg;
668 unsigned int sb;
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++)
682 color = *srcptr++;
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. */
697 void
698 grub_video_fbblit_replace_index_RGB888 (struct grub_video_fbblit_info *dst,
699 struct grub_video_fbblit_info *src,
700 int x, int y,
701 int width, int height,
702 int offset_x, int offset_y)
704 grub_uint32_t color;
705 int i;
706 int j;
707 grub_uint8_t *srcptr;
708 grub_uint8_t *dstptr;
709 unsigned int sr;
710 unsigned int sg;
711 unsigned int sb;
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++)
725 sr = *srcptr++;
726 sg = *srcptr++;
727 sb = *srcptr++;
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. */
739 void
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)
745 int i;
746 int j;
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);
767 if (src_alpha == 0)
768 continue;
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);
775 continue;
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,
792 dst_alpha);
794 set_pixel (dst, x + i, y + j, dst_color);
799 /* Optimized blending blitter for RGBA8888 to BGRA8888. */
800 void
801 grub_video_fbblit_blend_BGRA8888_RGBA8888 (struct grub_video_fbblit_info *dst,
802 struct grub_video_fbblit_info *src,
803 int x, int y,
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;
811 int i;
812 int j;
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++)
826 grub_uint32_t color;
827 unsigned int sr;
828 unsigned int sg;
829 unsigned int sb;
830 unsigned int a;
831 unsigned int dr;
832 unsigned int dg;
833 unsigned int db;
835 color = *srcptr++;
837 a = color >> 24;
839 if (a == 0)
841 /* Skip transparent source pixels. */
842 dstptr++;
843 continue;
846 sr = (color >> 0) & 0xFF;
847 sg = (color >> 8) & 0xFF;
848 sb = (color >> 16) & 0xFF;
850 if (a == 255)
852 /* Opaque pixel shortcut. */
853 dr = sr;
854 dg = sg;
855 db = sb;
857 else
859 /* General pixel color blending. */
860 color = *dstptr;
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;
872 *dstptr++ = color;
875 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
876 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
880 /* Optimized blending blitter for RGBA8888 to BGR888. */
881 void
882 grub_video_fbblit_blend_BGR888_RGBA8888 (struct grub_video_fbblit_info *dst,
883 struct grub_video_fbblit_info *src,
884 int x, int y,
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;
892 int i;
893 int j;
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++)
907 grub_uint32_t color;
908 unsigned int sr;
909 unsigned int sg;
910 unsigned int sb;
911 unsigned int a;
912 unsigned int dr;
913 unsigned int dg;
914 unsigned int db;
916 color = *srcptr++;
918 a = color >> 24;
920 if (a == 0)
922 /* Skip transparent source pixels. */
923 dstptr += 3;
924 continue;
927 sr = (color >> 0) & 0xFF;
928 sg = (color >> 8) & 0xFF;
929 sb = (color >> 16) & 0xFF;
931 if (a == 255)
933 /* Opaque pixel shortcut. */
934 dr = sr;
935 dg = sg;
936 db = sb;
938 else
940 /* General pixel color blending. */
941 color = *dstptr;
943 db = dstptr[0];
944 db = (db * (255 - a) + sb * a) / 255;
945 dg = dstptr[1];
946 dg = (dg * (255 - a) + sg * a) / 255;
947 dr = dstptr[2];
948 dr = (dr * (255 - a) + sr * a) / 255;
951 *dstptr++ = db;
952 *dstptr++ = dg;
953 *dstptr++ = dr;
956 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
957 dstptr += dstrowskip;
961 /* Optimized blending blitter for RGBA888 to RGBA8888. */
962 void
963 grub_video_fbblit_blend_RGBA8888_RGBA8888 (struct grub_video_fbblit_info *dst,
964 struct grub_video_fbblit_info *src,
965 int x, int y,
966 int width, int height,
967 int offset_x, int offset_y)
969 grub_uint32_t color;
970 int i;
971 int j;
972 grub_uint32_t *srcptr;
973 grub_uint32_t *dstptr;
974 unsigned int sr;
975 unsigned int sg;
976 unsigned int sb;
977 unsigned int a;
978 unsigned int dr;
979 unsigned int dg;
980 unsigned int db;
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++)
994 color = *srcptr++;
996 a = color >> 24;
998 if (a == 0)
1000 dstptr++;
1001 continue;
1004 if (a == 255)
1006 *dstptr++ = color;
1007 continue;
1010 sr = (color >> 0) & 0xFF;
1011 sg = (color >> 8) & 0xFF;
1012 sb = (color >> 16) & 0xFF;
1014 color = *dstptr;
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;
1026 *dstptr++ = color;
1028 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
1029 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
1033 /* Optimized blending blitter for RGBA8888 to RGB888. */
1034 void
1035 grub_video_fbblit_blend_RGB888_RGBA8888 (struct grub_video_fbblit_info *dst,
1036 struct grub_video_fbblit_info *src,
1037 int x, int y,
1038 int width, int height,
1039 int offset_x, int offset_y)
1041 grub_uint32_t color;
1042 int i;
1043 int j;
1044 grub_uint32_t *srcptr;
1045 grub_uint8_t *dstptr;
1046 unsigned int sr;
1047 unsigned int sg;
1048 unsigned int sb;
1049 unsigned int a;
1050 unsigned int dr;
1051 unsigned int dg;
1052 unsigned int db;
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++)
1066 color = *srcptr++;
1068 a = color >> 24;
1070 if (a == 0)
1072 dstptr += 3;
1073 continue;
1076 sr = (color >> 0) & 0xFF;
1077 sg = (color >> 8) & 0xFF;
1078 sb = (color >> 16) & 0xFF;
1080 if (a == 255)
1082 *dstptr++ = sr;
1083 *dstptr++ = sg;
1084 *dstptr++ = sb;
1086 continue;
1089 dr = dstptr[0];
1090 dg = dstptr[1];
1091 db = dstptr[2];
1093 dr = (dr * (255 - a) + sr * a) / 255;
1094 dg = (dg * (255 - a) + sg * a) / 255;
1095 db = (db * (255 - a) + sb * a) / 255;
1097 *dstptr++ = dr;
1098 *dstptr++ = dg;
1099 *dstptr++ = db;
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. */
1107 void
1108 grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst,
1109 struct grub_video_fbblit_info *src,
1110 int x, int y,
1111 int width, int height,
1112 int offset_x, int offset_y)
1114 grub_uint32_t color;
1115 int i;
1116 int j;
1117 grub_uint32_t *srcptr;
1118 grub_uint8_t *dstptr;
1119 unsigned int sr;
1120 unsigned int sg;
1121 unsigned int sb;
1122 unsigned int a;
1123 unsigned char dr;
1124 unsigned char dg;
1125 unsigned char db;
1126 unsigned char da;
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++)
1140 color = *srcptr++;
1142 a = color >> 24;
1144 if (a == 0)
1146 dstptr++;
1147 continue;
1150 sr = (color >> 0) & 0xFF;
1151 sg = (color >> 8) & 0xFF;
1152 sb = (color >> 16) & 0xFF;
1154 if (a == 255)
1156 color = grub_video_fb_map_rgb(sr, sg, sb);
1157 *dstptr++ = color & 0xFF;
1158 continue;
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. */
1177 void
1178 grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst,
1179 struct grub_video_fbblit_info *src,
1180 int x, int y,
1181 int width, int height,
1182 int offset_x, int offset_y)
1184 int i;
1185 int j;
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;
1192 int bit_index;
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;
1220 grub_uint8_t a;
1222 if (*srcptr & srcmask)
1224 color = fgcolor;
1225 a = src->mode_info->fg_alpha;
1227 else
1229 color = bgcolor;
1230 a = src->mode_info->bg_alpha;
1233 if (a == 255)
1234 *dstptr = color;
1235 else if (a != 0)
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;
1252 srcmask >>= 1;
1253 if (!srcmask)
1255 srcptr++;
1256 srcmask = 0x80;
1259 dstptr++;
1262 srcptr += srcrowskipbyte;
1263 if (srcmask >> srcrowskipbit)
1264 srcmask >>= srcrowskipbit;
1265 else
1267 srcptr++;
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
1276 void
1277 grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst,
1278 struct grub_video_fbblit_info *src,
1279 int x, int y,
1280 int width, int height,
1281 int offset_x, int offset_y)
1283 int i;
1284 int j;
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;
1291 int bit_index;
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;
1319 grub_uint8_t a;
1320 if (*srcptr & srcmask)
1322 color = fgcolor;
1323 a = src->mode_info->fg_alpha;
1325 else
1327 color = bgcolor;
1328 a = src->mode_info->bg_alpha;
1331 if (a == 255)
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;
1337 else if (a != 0)
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;
1352 srcmask >>= 1;
1353 if (!srcmask)
1355 srcptr++;
1356 srcmask = 0x80;
1359 dstptr += 3;
1362 srcptr += srcrowskipbyte;
1363 if (srcmask >> srcrowskipbit)
1364 srcmask >>= srcrowskipbit;
1365 else
1367 srcptr++;
1368 srcmask <<= 8 - srcrowskipbit;
1370 dstptr += dstrowskip;
1373 #endif
1375 /* Optimized blending blitter for 1-bit to XXX888. */
1376 void
1377 grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst,
1378 struct grub_video_fbblit_info *src,
1379 int x, int y,
1380 int width, int height,
1381 int offset_x, int offset_y)
1383 int i;
1384 int j;
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;
1391 int bit_index;
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;
1419 grub_uint8_t a;
1420 if (*srcptr & srcmask)
1422 color = fgcolor;
1423 a = src->mode_info->fg_alpha;
1425 else
1427 color = bgcolor;
1428 a = src->mode_info->bg_alpha;
1431 if (a == 255)
1432 *dstptr = color;
1433 else if (a != 0)
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);
1450 srcmask >>= 1;
1451 if (!srcmask)
1453 srcptr++;
1454 srcmask = 0x80;
1457 dstptr++;
1460 srcptr += srcrowskipbyte;
1461 if (srcmask >> srcrowskipbit)
1462 srcmask >>= srcrowskipbit;
1463 else
1465 srcptr++;
1466 srcmask <<= 8 - srcrowskipbit;
1468 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);