]> git.proxmox.com Git - grub2.git/blob - grub-core/video/fb/fbblit.c
* grub-core/video/fb/fbblit.c (grub_video_fbblit_blend_BGR888_RGBA8888):
[grub2.git] / grub-core / video / fb / fbblit.c
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc.
4 *
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.
9 *
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.
14 *
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/>.
17 */
18
19 /* SPECIAL NOTES!
20
21 Please note following when reading the code below:
22
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.
26
27 - Every function in this code assumes that bounds checking has been done in
28 previous phase and they are opted out in here. */
29
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>
36
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)
43 {
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;
52
53 for (j = 0; j < height; j++)
54 {
55 for (i = 0; i < width; i++)
56 {
57 src_color = get_pixel (src, i + offset_x, j + offset_y);
58
59 grub_video_fb_unmap_color_int (src, src_color, &src_red, &src_green,
60 &src_blue, &src_alpha);
61
62 dst_color = grub_video_fb_map_rgba (src_red, src_green,
63 src_blue, src_alpha);
64
65 set_pixel (dst, x + i, y + j, dst_color);
66 }
67 }
68 }
69
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)
76 {
77 int j;
78 grub_uint32_t *srcptr;
79 grub_uint32_t *dstptr;
80 int bpp;
81
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);
85
86 for (j = 0; j < height; j++)
87 {
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);
91 }
92 }
93
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)
101 {
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;
111
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;
117
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);
122
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);
127
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);
132
133 for (j = 0; j < height; j++)
134 {
135 for (i = 0; i < width; i++)
136 {
137 if (*srcptr & srcmask)
138 *dstptr = fgcolor;
139 else
140 *dstptr = bgcolor;
141 srcmask >>= 1;
142 if (!srcmask)
143 {
144 srcptr++;
145 srcmask = 0x80;
146 }
147
148 dstptr++;
149 }
150
151 srcptr += srcrowskipbyte;
152 if (srcmask >> srcrowskipbit)
153 srcmask >>= srcrowskipbit;
154 else
155 {
156 srcptr++;
157 srcmask <<= 8 - srcrowskipbit;
158 }
159 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
160 }
161 }
162
163
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)
172 {
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;
182
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;
188
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);
193
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);
198
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);
203
204 for (j = 0; j < height; j++)
205 {
206 for (i = 0; i < width - 1; i++)
207 {
208 if (*srcptr & srcmask)
209 *(grub_uint32_t *) dstptr = fgcolor;
210 else
211 *(grub_uint32_t *) dstptr = bgcolor;
212 srcmask >>= 1;
213 if (!srcmask)
214 {
215 srcptr++;
216 srcmask = 0x80;
217 }
218
219 dstptr += 3;
220 }
221
222 if (*srcptr & srcmask)
223 {
224 *dstptr++ = fgcolor & 0xff;
225 *dstptr++ = (fgcolor & 0xff00) >> 8;
226 *dstptr++ = (fgcolor & 0xff0000) >> 16;
227 }
228 else
229 {
230 *dstptr++ = bgcolor & 0xff;
231 *dstptr++ = (bgcolor & 0xff00) >> 8;
232 *dstptr++ = (bgcolor & 0xff0000) >> 16;
233 }
234 srcmask >>= 1;
235 if (!srcmask)
236 {
237 srcptr++;
238 srcmask = 0x80;
239 }
240
241 srcptr += srcrowskipbyte;
242 if (srcmask >> srcrowskipbit)
243 srcmask >>= srcrowskipbit;
244 else
245 {
246 srcptr++;
247 srcmask <<= 8 - srcrowskipbit;
248 }
249 dstptr += dstrowskip;
250 }
251 }
252 #endif
253
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)
261 {
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;
271
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;
277
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);
282
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);
287
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);
292
293 for (j = 0; j < height; j++)
294 {
295 for (i = 0; i < width; i++)
296 {
297 if (*srcptr & srcmask)
298 *dstptr = fgcolor;
299 else
300 *dstptr = bgcolor;
301 srcmask >>= 1;
302 if (!srcmask)
303 {
304 srcptr++;
305 srcmask = 0x80;
306 }
307
308 dstptr++;
309 }
310
311 srcptr += srcrowskipbyte;
312 if (srcmask >> srcrowskipbit)
313 srcmask >>= srcrowskipbit;
314 else
315 {
316 srcptr++;
317 srcmask <<= 8 - srcrowskipbit;
318 }
319 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
320 }
321 }
322
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)
330 {
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;
340
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;
346
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);
351
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);
356
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);
361
362 for (j = 0; j < height; j++)
363 {
364 for (i = 0; i < width; i++)
365 {
366 if (*srcptr & srcmask)
367 *dstptr = fgcolor;
368 else
369 *dstptr = bgcolor;
370 srcmask >>= 1;
371 if (!srcmask)
372 {
373 srcptr++;
374 srcmask = 0x80;
375 }
376
377 dstptr++;
378 }
379
380 srcptr += srcrowskipbyte;
381 if (srcmask >> srcrowskipbit)
382 srcmask >>= srcrowskipbit;
383 else
384 {
385 srcptr++;
386 srcmask <<= 8 - srcrowskipbit;
387 }
388 dstptr += dstrowskip;
389 }
390 }
391
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)
399 {
400 int i;
401 int j;
402 grub_uint8_t *srcptr;
403 grub_uint8_t *dstptr;
404 unsigned int srcrowskip;
405 unsigned int dstrowskip;
406
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;
411
412 srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y);
413 dstptr = grub_video_fb_get_video_ptr (dst, x, y);
414
415 for (j = 0; j < height; j++)
416 {
417 for (i = 0; i < width; i++)
418 {
419 #ifdef GRUB_CPU_WORDS_BIGENDIAN
420 grub_uint8_t a = *srcptr++;
421 #endif
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++;
427 #endif
428
429 #ifdef GRUB_CPU_WORDS_BIGENDIAN
430 *dstptr++ = a;
431 #endif
432 *dstptr++ = b;
433 *dstptr++ = g;
434 *dstptr++ = r;
435 #ifndef GRUB_CPU_WORDS_BIGENDIAN
436 *dstptr++ = a;
437 #endif
438 }
439
440 srcptr += srcrowskip;
441 dstptr += dstrowskip;
442 }
443 }
444
445 /* Optimized replacing blitter for RGB888 to BGRX8888. */
446 void
447 grub_video_fbblit_replace_BGRX8888_RGB888 (struct grub_video_fbblit_info *dst,
448 struct grub_video_fbblit_info *src,
449 int x, int y,
450 int width, int height,
451 int offset_x, int offset_y)
452 {
453 int i;
454 int j;
455 grub_uint8_t *srcptr;
456 grub_uint8_t *dstptr;
457 unsigned int srcrowskip;
458 unsigned int dstrowskip;
459
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;
464
465 srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y);
466 dstptr = grub_video_fb_get_video_ptr (dst, x, y);
467
468 for (j = 0; j < height; j++)
469 {
470 for (i = 0; i < width; i++)
471 {
472 grub_uint8_t r = *srcptr++;
473 grub_uint8_t g = *srcptr++;
474 grub_uint8_t b = *srcptr++;
475
476 #ifdef GRUB_CPU_WORDS_BIGENDIAN
477 /* Set alpha component as opaque. */
478 *dstptr++ = 255;
479 #endif
480
481 *dstptr++ = b;
482 *dstptr++ = g;
483 *dstptr++ = r;
484
485 #ifndef GRUB_CPU_WORDS_BIGENDIAN
486 /* Set alpha component as opaque. */
487 *dstptr++ = 255;
488 #endif
489 }
490
491 srcptr += srcrowskip;
492 dstptr += dstrowskip;
493 }
494 }
495
496 /* Optimized replacing blitter for RGBX8888 to BGR888. */
497 void
498 grub_video_fbblit_replace_BGR888_RGBX8888 (struct grub_video_fbblit_info *dst,
499 struct grub_video_fbblit_info *src,
500 int x, int y,
501 int width, int height,
502 int offset_x, int offset_y)
503 {
504 grub_uint32_t *srcptr;
505 grub_uint8_t *dstptr;
506 unsigned int srcrowskip;
507 unsigned int dstrowskip;
508 int i;
509 int j;
510
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;
515
516 srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y);
517 dstptr = grub_video_fb_get_video_ptr (dst, x, y);
518
519 for (j = 0; j < height; j++)
520 {
521 for (i = 0; i < width; i++)
522 {
523 grub_uint32_t color;
524 grub_uint8_t sr;
525 grub_uint8_t sg;
526 grub_uint8_t sb;
527
528 color = *srcptr++;
529
530 sr = (color >> 0) & 0xFF;
531 sg = (color >> 8) & 0xFF;
532 sb = (color >> 16) & 0xFF;
533
534 #ifdef GRUB_CPU_WORDS_BIGENDIAN
535 *dstptr++ = sr;
536 *dstptr++ = sg;
537 *dstptr++ = sb;
538 #else
539 *dstptr++ = sb;
540 *dstptr++ = sg;
541 *dstptr++ = sr;
542 #endif
543 }
544
545 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
546 dstptr += dstrowskip;
547 }
548 }
549
550 /* Optimized replacing blitter for RGB888 to BGR888. */
551 void
552 grub_video_fbblit_replace_BGR888_RGB888 (struct grub_video_fbblit_info *dst,
553 struct grub_video_fbblit_info *src,
554 int x, int y,
555 int width, int height,
556 int offset_x, int offset_y)
557 {
558 int i;
559 int j;
560 grub_uint8_t *srcptr;
561 grub_uint8_t *dstptr;
562 unsigned int srcrowskip;
563 unsigned int dstrowskip;
564
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;
569
570 srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y);
571 dstptr = grub_video_fb_get_video_ptr (dst, x, y);
572
573 for (j = 0; j < height; j++)
574 {
575 for (i = 0; i < width; i++)
576 {
577 grub_uint8_t r = *srcptr++;
578 grub_uint8_t g = *srcptr++;
579 grub_uint8_t b = *srcptr++;
580
581 *dstptr++ = b;
582 *dstptr++ = g;
583 *dstptr++ = r;
584 }
585
586 srcptr += srcrowskip;
587 dstptr += dstrowskip;
588 }
589 }
590
591 /* Optimized replacing blitter for RGB888 to RGBX8888. */
592 void
593 grub_video_fbblit_replace_RGBX8888_RGB888 (struct grub_video_fbblit_info *dst,
594 struct grub_video_fbblit_info *src,
595 int x, int y,
596 int width, int height,
597 int offset_x, int offset_y)
598 {
599 grub_uint32_t color;
600 int i;
601 int j;
602 grub_uint8_t *srcptr;
603 grub_uint32_t *dstptr;
604 unsigned int sr;
605 unsigned int sg;
606 unsigned int sb;
607 grub_size_t srcrowskip;
608 grub_size_t dstrowskip;
609
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);
614
615 for (j = 0; j < height; j++)
616 {
617 for (i = 0; i < width; i++)
618 {
619 #ifdef GRUB_CPU_WORDS_BIGENDIAN
620 sb = *srcptr++;
621 sg = *srcptr++;
622 sr = *srcptr++;
623 #else
624 sr = *srcptr++;
625 sg = *srcptr++;
626 sb = *srcptr++;
627 #endif
628 /* Set alpha as opaque. */
629 color = 0xFF000000 | (sb << 16) | (sg << 8) | sr;
630
631 *dstptr++ = color;
632 }
633 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
634 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
635 }
636 }
637
638 /* Optimized replacing blitter for RGBX8888 to RGB888. */
639 void
640 grub_video_fbblit_replace_RGB888_RGBX8888 (struct grub_video_fbblit_info *dst,
641 struct grub_video_fbblit_info *src,
642 int x, int y,
643 int width, int height,
644 int offset_x, int offset_y)
645 {
646 grub_uint32_t color;
647 int i;
648 int j;
649 grub_uint32_t *srcptr;
650 grub_uint8_t *dstptr;
651 unsigned int sr;
652 unsigned int sg;
653 unsigned int sb;
654 grub_size_t srcrowskip;
655 grub_size_t dstrowskip;
656
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;
661
662 for (j = 0; j < height; j++)
663 {
664 for (i = 0; i < width; i++)
665 {
666 color = *srcptr++;
667
668 sr = (color >> 0) & 0xFF;
669 sg = (color >> 8) & 0xFF;
670 sb = (color >> 16) & 0xFF;
671
672 #ifndef GRUB_CPU_WORDS_BIGENDIAN
673 *dstptr++ = sr;
674 *dstptr++ = sg;
675 *dstptr++ = sb;
676 #else
677 *dstptr++ = sb;
678 *dstptr++ = sg;
679 *dstptr++ = sr;
680 #endif
681 }
682 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
683 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
684 }
685 }
686
687 /* Optimized replacing blitter for RGBX8888 to indexed color. */
688 void
689 grub_video_fbblit_replace_index_RGBX8888 (struct grub_video_fbblit_info *dst,
690 struct grub_video_fbblit_info *src,
691 int x, int y,
692 int width, int height,
693 int offset_x, int offset_y)
694 {
695 grub_uint32_t color;
696 int i;
697 int j;
698 grub_uint32_t *srcptr;
699 grub_uint8_t *dstptr;
700 unsigned int sr;
701 unsigned int sg;
702 unsigned int sb;
703 grub_size_t srcrowskip;
704 grub_size_t dstrowskip;
705
706 srcrowskip = src->mode_info->pitch - 4 * width;
707 dstrowskip = dst->mode_info->pitch - width;
708
709 srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y);
710 dstptr = grub_video_fb_get_video_ptr (dst, x, y);
711
712 for (j = 0; j < height; j++)
713 {
714 for (i = 0; i < width; i++)
715 {
716 color = *srcptr++;
717
718 #ifdef GRUB_CPU_WORDS_BIGENDIAN
719 sb = (color >> 0) & 0xFF;
720 sg = (color >> 8) & 0xFF;
721 sr = (color >> 16) & 0xFF;
722 #else
723 sr = (color >> 0) & 0xFF;
724 sg = (color >> 8) & 0xFF;
725 sb = (color >> 16) & 0xFF;
726 #endif
727
728 color = grub_video_fb_map_rgb(sr, sg, sb);
729 *dstptr++ = color & 0xFF;
730 }
731 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
732 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
733 }
734 }
735
736 /* Optimized replacing blitter for RGB888 to indexed color. */
737 void
738 grub_video_fbblit_replace_index_RGB888 (struct grub_video_fbblit_info *dst,
739 struct grub_video_fbblit_info *src,
740 int x, int y,
741 int width, int height,
742 int offset_x, int offset_y)
743 {
744 grub_uint32_t color;
745 int i;
746 int j;
747 grub_uint8_t *srcptr;
748 grub_uint8_t *dstptr;
749 unsigned int sr;
750 unsigned int sg;
751 unsigned int sb;
752 grub_size_t srcrowskip;
753 grub_size_t dstrowskip;
754
755 srcrowskip = src->mode_info->pitch - 3 * width;
756 dstrowskip = dst->mode_info->pitch - width;
757
758 srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y);
759 dstptr = grub_video_fb_get_video_ptr (dst, x, y);
760
761 for (j = 0; j < height; j++)
762 {
763 for (i = 0; i < width; i++)
764 {
765 #ifndef GRUB_CPU_WORDS_BIGENDIAN
766 sr = *srcptr++;
767 sg = *srcptr++;
768 sb = *srcptr++;
769 #else
770 sb = *srcptr++;
771 sg = *srcptr++;
772 sr = *srcptr++;
773 #endif
774
775 color = grub_video_fb_map_rgb(sr, sg, sb);
776
777 *dstptr++ = color & 0xFF;
778 }
779 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
780 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
781 }
782 }
783
784 /* Generic blending blitter. Works for every supported format. */
785 void
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)
790 {
791 int i;
792 int j;
793
794 for (j = 0; j < height; j++)
795 {
796 for (i = 0; i < width; i++)
797 {
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;
808
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);
812
813 if (src_alpha == 0)
814 continue;
815
816 if (src_alpha == 255)
817 {
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);
821 continue;
822 }
823
824 dst_color = get_pixel (dst, x + i, y + j);
825
826 grub_video_fb_unmap_color_int (dst, dst_color, &dst_red,
827 &dst_green, &dst_blue, &dst_alpha);
828
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);
835
836 dst_alpha = src_alpha;
837 dst_color = grub_video_fb_map_rgba (dst_red, dst_green, dst_blue,
838 dst_alpha);
839
840 set_pixel (dst, x + i, y + j, dst_color);
841 }
842 }
843 }
844
845 /* Optimized blending blitter for RGBA8888 to BGRA8888. */
846 void
847 grub_video_fbblit_blend_BGRA8888_RGBA8888 (struct grub_video_fbblit_info *dst,
848 struct grub_video_fbblit_info *src,
849 int x, int y,
850 int width, int height,
851 int offset_x, int offset_y)
852 {
853 grub_uint32_t *srcptr;
854 grub_uint32_t *dstptr;
855 unsigned int srcrowskip;
856 unsigned int dstrowskip;
857 int i;
858 int j;
859
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;
864
865 srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y);
866 dstptr = grub_video_fb_get_video_ptr (dst, x, y);
867
868 for (j = 0; j < height; j++)
869 {
870 for (i = 0; i < width; i++)
871 {
872 grub_uint32_t color;
873 unsigned int sr;
874 unsigned int sg;
875 unsigned int sb;
876 unsigned int a;
877 unsigned int dr;
878 unsigned int dg;
879 unsigned int db;
880
881 color = *srcptr++;
882
883 a = color >> 24;
884
885 if (a == 0)
886 {
887 /* Skip transparent source pixels. */
888 dstptr++;
889 continue;
890 }
891
892 sr = (color >> 0) & 0xFF;
893 sg = (color >> 8) & 0xFF;
894 sb = (color >> 16) & 0xFF;
895
896 if (a == 255)
897 {
898 /* Opaque pixel shortcut. */
899 dr = sr;
900 dg = sg;
901 db = sb;
902 }
903 else
904 {
905 /* General pixel color blending. */
906 color = *dstptr;
907
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;
914 }
915
916 color = (a << 24) | (dr << 16) | (dg << 8) | db;
917
918 *dstptr++ = color;
919 }
920
921 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
922 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
923 }
924 }
925
926 /* Optimized blending blitter for RGBA8888 to BGR888. */
927 void
928 grub_video_fbblit_blend_BGR888_RGBA8888 (struct grub_video_fbblit_info *dst,
929 struct grub_video_fbblit_info *src,
930 int x, int y,
931 int width, int height,
932 int offset_x, int offset_y)
933 {
934 grub_uint32_t *srcptr;
935 grub_uint8_t *dstptr;
936 unsigned int srcrowskip;
937 unsigned int dstrowskip;
938 int i;
939 int j;
940
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;
945
946 srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y);
947 dstptr = grub_video_fb_get_video_ptr (dst, x, y);
948
949 for (j = 0; j < height; j++)
950 {
951 for (i = 0; i < width; i++)
952 {
953 grub_uint32_t color;
954 unsigned int sr;
955 unsigned int sg;
956 unsigned int sb;
957 unsigned int a;
958 unsigned int dr;
959 unsigned int dg;
960 unsigned int db;
961
962 color = *srcptr++;
963
964 a = color >> 24;
965
966 if (a == 0)
967 {
968 /* Skip transparent source pixels. */
969 dstptr += 3;
970 continue;
971 }
972
973 sr = (color >> 0) & 0xFF;
974 sg = (color >> 8) & 0xFF;
975 sb = (color >> 16) & 0xFF;
976
977 if (a == 255)
978 {
979 /* Opaque pixel shortcut. */
980 dr = sr;
981 dg = sg;
982 db = sb;
983 }
984 else
985 {
986 /* General pixel color blending. */
987 color = *dstptr;
988
989 #ifndef GRUB_CPU_WORDS_BIGENDIAN
990 db = dstptr[0];
991 dg = dstptr[1];
992 dr = dstptr[2];
993 #else
994 dr = dstptr[0];
995 dg = dstptr[1];
996 db = dstptr[2];
997 #endif
998
999 db = (db * (255 - a) + sb * a) / 255;
1000 dg = (dg * (255 - a) + sg * a) / 255;
1001 dr = (dr * (255 - a) + sr * a) / 255;
1002 }
1003
1004 #ifndef GRUB_CPU_WORDS_BIGENDIAN
1005 *dstptr++ = db;
1006 *dstptr++ = dg;
1007 *dstptr++ = dr;
1008 #else
1009 *dstptr++ = dr;
1010 *dstptr++ = dg;
1011 *dstptr++ = db;
1012 #endif
1013 }
1014
1015 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
1016 dstptr += dstrowskip;
1017 }
1018 }
1019
1020 /* Optimized blending blitter for RGBA888 to RGBA8888. */
1021 void
1022 grub_video_fbblit_blend_RGBA8888_RGBA8888 (struct grub_video_fbblit_info *dst,
1023 struct grub_video_fbblit_info *src,
1024 int x, int y,
1025 int width, int height,
1026 int offset_x, int offset_y)
1027 {
1028 grub_uint32_t color;
1029 int i;
1030 int j;
1031 grub_uint32_t *srcptr;
1032 grub_uint32_t *dstptr;
1033 unsigned int sr;
1034 unsigned int sg;
1035 unsigned int sb;
1036 unsigned int a;
1037 unsigned int dr;
1038 unsigned int dg;
1039 unsigned int db;
1040 grub_size_t srcrowskip;
1041 grub_size_t dstrowskip;
1042
1043 srcrowskip = src->mode_info->pitch - 4 * width;
1044 dstrowskip = dst->mode_info->pitch - 4 * width;
1045
1046 srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y);
1047 dstptr = grub_video_fb_get_video_ptr (dst, x, y);
1048
1049 for (j = 0; j < height; j++)
1050 {
1051 for (i = 0; i < width; i++)
1052 {
1053 color = *srcptr++;
1054
1055 a = color >> 24;
1056
1057 if (a == 0)
1058 {
1059 dstptr++;
1060 continue;
1061 }
1062
1063 if (a == 255)
1064 {
1065 *dstptr++ = color;
1066 continue;
1067 }
1068
1069 sr = (color >> 0) & 0xFF;
1070 sg = (color >> 8) & 0xFF;
1071 sb = (color >> 16) & 0xFF;
1072
1073 color = *dstptr;
1074
1075 dr = (color >> 0) & 0xFF;
1076 dg = (color >> 8) & 0xFF;
1077 db = (color >> 16) & 0xFF;
1078
1079 dr = (dr * (255 - a) + sr * a) / 255;
1080 dg = (dg * (255 - a) + sg * a) / 255;
1081 db = (db * (255 - a) + sb * a) / 255;
1082
1083 color = (a << 24) | (db << 16) | (dg << 8) | dr;
1084
1085 *dstptr++ = color;
1086 }
1087 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
1088 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
1089 }
1090 }
1091
1092 /* Optimized blending blitter for RGBA8888 to RGB888. */
1093 void
1094 grub_video_fbblit_blend_RGB888_RGBA8888 (struct grub_video_fbblit_info *dst,
1095 struct grub_video_fbblit_info *src,
1096 int x, int y,
1097 int width, int height,
1098 int offset_x, int offset_y)
1099 {
1100 grub_uint32_t color;
1101 int i;
1102 int j;
1103 grub_uint32_t *srcptr;
1104 grub_uint8_t *dstptr;
1105 unsigned int sr;
1106 unsigned int sg;
1107 unsigned int sb;
1108 unsigned int a;
1109 unsigned int dr;
1110 unsigned int dg;
1111 unsigned int db;
1112 grub_size_t srcrowskip;
1113 grub_size_t dstrowskip;
1114
1115 srcrowskip = src->mode_info->pitch - 4 * width;
1116 dstrowskip = dst->mode_info->pitch - 3 * width;
1117
1118 srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y);
1119 dstptr = grub_video_fb_get_video_ptr (dst, x, y);
1120
1121 for (j = 0; j < height; j++)
1122 {
1123 for (i = 0; i < width; i++)
1124 {
1125 color = *srcptr++;
1126
1127 a = color >> 24;
1128
1129 if (a == 0)
1130 {
1131 dstptr += 3;
1132 continue;
1133 }
1134
1135 sr = (color >> 0) & 0xFF;
1136 sg = (color >> 8) & 0xFF;
1137 sb = (color >> 16) & 0xFF;
1138
1139 if (a == 255)
1140 {
1141 #ifndef GRUB_CPU_WORDS_BIGENDIAN
1142 *dstptr++ = sr;
1143 *dstptr++ = sg;
1144 *dstptr++ = sb;
1145 #else
1146 *dstptr++ = sb;
1147 *dstptr++ = sg;
1148 *dstptr++ = sr;
1149 #endif
1150
1151 continue;
1152 }
1153
1154 #ifndef GRUB_CPU_WORDS_BIGENDIAN
1155 dr = dstptr[0];
1156 dg = dstptr[1];
1157 db = dstptr[2];
1158 #else
1159 db = dstptr[0];
1160 dg = dstptr[1];
1161 dr = dstptr[2];
1162 #endif
1163
1164 dr = (dr * (255 - a) + sr * a) / 255;
1165 dg = (dg * (255 - a) + sg * a) / 255;
1166 db = (db * (255 - a) + sb * a) / 255;
1167
1168 #ifndef GRUB_CPU_WORDS_BIGENDIAN
1169 *dstptr++ = dr;
1170 *dstptr++ = dg;
1171 *dstptr++ = db;
1172 #else
1173 *dstptr++ = db;
1174 *dstptr++ = dg;
1175 *dstptr++ = dr;
1176 #endif
1177 }
1178 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
1179 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
1180 }
1181 }
1182
1183 /* Optimized blending blitter for RGBA8888 to indexed color. */
1184 void
1185 grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst,
1186 struct grub_video_fbblit_info *src,
1187 int x, int y,
1188 int width, int height,
1189 int offset_x, int offset_y)
1190 {
1191 grub_uint32_t color;
1192 int i;
1193 int j;
1194 grub_uint32_t *srcptr;
1195 grub_uint8_t *dstptr;
1196 unsigned int sr;
1197 unsigned int sg;
1198 unsigned int sb;
1199 unsigned int a;
1200 unsigned char dr;
1201 unsigned char dg;
1202 unsigned char db;
1203 unsigned char da;
1204 grub_size_t srcrowskip;
1205 grub_size_t dstrowskip;
1206
1207 srcrowskip = src->mode_info->pitch - 4 * width;
1208 dstrowskip = dst->mode_info->pitch - width;
1209
1210 srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y);
1211 dstptr = grub_video_fb_get_video_ptr (dst, x, y);
1212
1213 for (j = 0; j < height; j++)
1214 {
1215 for (i = 0; i < width; i++)
1216 {
1217 color = *srcptr++;
1218
1219 a = color >> 24;
1220
1221 if (a == 0)
1222 {
1223 dstptr++;
1224 continue;
1225 }
1226
1227 sr = (color >> 0) & 0xFF;
1228 sg = (color >> 8) & 0xFF;
1229 sb = (color >> 16) & 0xFF;
1230
1231 if (a == 255)
1232 {
1233 color = grub_video_fb_map_rgb(sr, sg, sb);
1234 *dstptr++ = color & 0xFF;
1235 continue;
1236 }
1237
1238 grub_video_fb_unmap_color_int (dst, *dstptr, &dr, &dg, &db, &da);
1239
1240 dr = (dr * (255 - a) + sr * a) / 255;
1241 dg = (dg * (255 - a) + sg * a) / 255;
1242 db = (db * (255 - a) + sb * a) / 255;
1243
1244 color = grub_video_fb_map_rgb(dr, dg, db);
1245
1246 *dstptr++ = color & 0xFF;
1247 }
1248 GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip);
1249 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
1250 }
1251 }
1252
1253 /* Optimized blending blitter for 1-bit to XXXA8888. */
1254 void
1255 grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst,
1256 struct grub_video_fbblit_info *src,
1257 int x, int y,
1258 int width, int height,
1259 int offset_x, int offset_y)
1260 {
1261 int i;
1262 int j;
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;
1269 int bit_index;
1270
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;
1276
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);
1281
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);
1286
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);
1291
1292 for (j = 0; j < height; j++)
1293 {
1294 for (i = 0; i < width; i++)
1295 {
1296 grub_uint32_t color;
1297 grub_uint8_t a;
1298
1299 if (*srcptr & srcmask)
1300 {
1301 color = fgcolor;
1302 a = src->mode_info->fg_alpha;
1303 }
1304 else
1305 {
1306 color = bgcolor;
1307 a = src->mode_info->bg_alpha;
1308 }
1309
1310 if (a == 255)
1311 *dstptr = color;
1312 else if (a != 0)
1313 {
1314 grub_uint8_t s1 = (color >> 0) & 0xFF;
1315 grub_uint8_t s2 = (color >> 8) & 0xFF;
1316 grub_uint8_t s3 = (color >> 16) & 0xFF;
1317
1318 grub_uint8_t d1 = (*dstptr >> 0) & 0xFF;
1319 grub_uint8_t d2 = (*dstptr >> 8) & 0xFF;
1320 grub_uint8_t d3 = (*dstptr >> 16) & 0xFF;
1321
1322 d1 = (d1 * (255 - a) + s1 * a) / 255;
1323 d2 = (d2 * (255 - a) + s2 * a) / 255;
1324 d3 = (d3 * (255 - a) + s3 * a) / 255;
1325
1326 *dstptr = (a << 24) | (d3 << 16) | (d2 << 8) | d1;
1327 }
1328
1329 srcmask >>= 1;
1330 if (!srcmask)
1331 {
1332 srcptr++;
1333 srcmask = 0x80;
1334 }
1335
1336 dstptr++;
1337 }
1338
1339 srcptr += srcrowskipbyte;
1340 if (srcmask >> srcrowskipbit)
1341 srcmask >>= srcrowskipbit;
1342 else
1343 {
1344 srcptr++;
1345 srcmask <<= 8 - srcrowskipbit;
1346 }
1347 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
1348 }
1349 }
1350
1351 /* Optimized blending blitter for 1-bit to XXX888. */
1352 #ifdef GRUB_HAVE_UNALIGNED_ACCESS
1353 void
1354 grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst,
1355 struct grub_video_fbblit_info *src,
1356 int x, int y,
1357 int width, int height,
1358 int offset_x, int offset_y)
1359 {
1360 int i;
1361 int j;
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;
1368 int bit_index;
1369
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;
1375
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);
1380
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);
1385
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);
1390
1391 for (j = 0; j < height; j++)
1392 {
1393 for (i = 0; i < width; i++)
1394 {
1395 grub_uint32_t color;
1396 grub_uint8_t a;
1397 if (*srcptr & srcmask)
1398 {
1399 color = fgcolor;
1400 a = src->mode_info->fg_alpha;
1401 }
1402 else
1403 {
1404 color = bgcolor;
1405 a = src->mode_info->bg_alpha;
1406 }
1407
1408 if (a == 255)
1409 {
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;
1414 #else
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;
1418 #endif
1419 }
1420 else if (a != 0)
1421 {
1422 grub_uint8_t s1 = (color >> 0) & 0xFF;
1423 grub_uint8_t s2 = (color >> 8) & 0xFF;
1424 grub_uint8_t s3 = (color >> 16) & 0xFF;
1425
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;
1429
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;
1433 }
1434
1435 srcmask >>= 1;
1436 if (!srcmask)
1437 {
1438 srcptr++;
1439 srcmask = 0x80;
1440 }
1441
1442 dstptr += 3;
1443 }
1444
1445 srcptr += srcrowskipbyte;
1446 if (srcmask >> srcrowskipbit)
1447 srcmask >>= srcrowskipbit;
1448 else
1449 {
1450 srcptr++;
1451 srcmask <<= 8 - srcrowskipbit;
1452 }
1453 dstptr += dstrowskip;
1454 }
1455 }
1456 #endif
1457
1458 /* Optimized blending blitter for 1-bit to XXX888. */
1459 void
1460 grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst,
1461 struct grub_video_fbblit_info *src,
1462 int x, int y,
1463 int width, int height,
1464 int offset_x, int offset_y)
1465 {
1466 int i;
1467 int j;
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;
1474 int bit_index;
1475
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;
1481
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);
1486
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);
1491
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);
1496
1497 for (j = 0; j < height; j++)
1498 {
1499 for (i = 0; i < width; i++)
1500 {
1501 grub_uint32_t color;
1502 grub_uint8_t a;
1503 if (*srcptr & srcmask)
1504 {
1505 color = fgcolor;
1506 a = src->mode_info->fg_alpha;
1507 }
1508 else
1509 {
1510 color = bgcolor;
1511 a = src->mode_info->bg_alpha;
1512 }
1513
1514 if (a == 255)
1515 *dstptr = color;
1516 else if (a != 0)
1517 {
1518 grub_uint8_t s1 = (color >> 0) & 0x1F;
1519 grub_uint8_t s2 = (color >> 5) & 0x3F;
1520 grub_uint8_t s3 = (color >> 11) & 0x1F;
1521
1522 grub_uint8_t d1 = (*dstptr >> 0) & 0x1F;
1523 grub_uint8_t d2 = (*dstptr >> 5) & 0x3F;
1524 grub_uint8_t d3 = (*dstptr >> 11) & 0x1F;
1525
1526 d1 = (d1 * (255 - a) + s1 * a) / 255;
1527 d2 = (d2 * (255 - a) + s2 * a) / 255;
1528 d3 = (d3 * (255 - a) + s3 * a) / 255;
1529
1530 *dstptr = (d1 & 0x1f) | ((d2 & 0x3f) << 5) | ((d3 & 0x1f) << 11);
1531 }
1532
1533 srcmask >>= 1;
1534 if (!srcmask)
1535 {
1536 srcptr++;
1537 srcmask = 0x80;
1538 }
1539
1540 dstptr++;
1541 }
1542
1543 srcptr += srcrowskipbyte;
1544 if (srcmask >> srcrowskipbit)
1545 srcmask >>= srcrowskipbit;
1546 else
1547 {
1548 srcptr++;
1549 srcmask <<= 8 - srcrowskipbit;
1550 }
1551 GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip);
1552 }
1553 }