summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2011-03-08 17:11:56 +0000
committerThomas Martitz <kugel@rockbox.org>2011-03-08 17:11:56 +0000
commitcbf889d3e2cbed5e1476b292137a5a43e75c941b (patch)
treee3a235524d6750a07f5a978876297f3fcd365e6f
parent4594b133b063d032aee3c378bb6d9221941be140 (diff)
downloadrockbox-cbf889d3e2cbed5e1476b292137a5a43e75c941b.tar.gz
rockbox-cbf889d3e2cbed5e1476b292137a5a43e75c941b.zip
Merge lcd_{alpha,mono}_bitmap_part() for both lcd-16bit. Add small loop optimizations too.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29541 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/lcd-16bit-common.c517
-rw-r--r--firmware/drivers/lcd-16bit-vert.c492
-rw-r--r--firmware/drivers/lcd-16bit.c487
3 files changed, 531 insertions, 965 deletions
diff --git a/firmware/drivers/lcd-16bit-common.c b/firmware/drivers/lcd-16bit-common.c
new file mode 100644
index 0000000000..1e1548e997
--- /dev/null
+++ b/firmware/drivers/lcd-16bit-common.c
@@ -0,0 +1,517 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Dave Chapman
11 *
12 * Rockbox driver for 16-bit colour LCDs
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23
24
25/* to be #included by lcd-16bit*.c */
26
27#if !defined(ROW_INC) || !defined(COL_INC)
28#error ROW_INC or COL_INC not defined
29#endif
30
31/* About Rockbox' internal monochrome bitmap format:
32 *
33 * A bitmap contains one bit for every pixel that defines if that pixel is
34 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
35 * at top.
36 * The bytes are stored in row-major order, with byte 0 being top left,
37 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
38 * 0..7, the second row defines pixel row 8..15 etc.
39 *
40 * This is the mono bitmap format used on all other targets so far; the
41 * pixel packing doesn't really matter on a 8bit+ target. */
42
43/* Draw a partial monochrome bitmap */
44
45void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
46 int src_y, int stride, int x, int y,
47 int width, int height)
48{
49 const unsigned char *src_end;
50 fb_data *dst, *dst_col;
51 unsigned dmask = 0x100; /* bit 8 == sentinel */
52 int drmode = current_vp->drawmode;
53 int row;
54
55 /******************** Image in viewport clipping **********************/
56 /* nothing to draw? */
57 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
58 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
59 return;
60
61 if (x < 0)
62 {
63 width += x;
64 src_x -= x;
65 x = 0;
66 }
67 if (y < 0)
68 {
69 height += y;
70 src_y -= y;
71 y = 0;
72 }
73 if (x + width > current_vp->width)
74 width = current_vp->width - x;
75 if (y + height > current_vp->height)
76 height = current_vp->height - y;
77
78 /* adjust for viewport */
79 x += current_vp->x;
80 y += current_vp->y;
81
82#if defined(HAVE_VIEWPORT_CLIP)
83 /********************* Viewport on screen clipping ********************/
84 /* nothing to draw? */
85 if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
86 || (x + width <= 0) || (y + height <= 0))
87 return;
88
89 /* clip image in viewport in screen */
90 if (x < 0)
91 {
92 width += x;
93 src_x -= x;
94 x = 0;
95 }
96 if (y < 0)
97 {
98 height += y;
99 src_y -= y;
100 y = 0;
101 }
102 if (x + width > LCD_WIDTH)
103 width = LCD_WIDTH - x;
104 if (y + height > LCD_HEIGHT)
105 height = LCD_HEIGHT - y;
106#endif
107
108 src += stride * (src_y >> 3) + src_x; /* move starting point */
109 src_y &= 7;
110 src_end = src + width;
111 dst_col = LCDADDR(x, y);
112
113
114 if (drmode & DRMODE_INVERSEVID)
115 {
116 dmask = 0x1ff; /* bit 8 == sentinel */
117 drmode &= DRMODE_SOLID; /* mask out inversevid */
118 }
119
120 /* go through each column and update each pixel */
121 do
122 {
123 const unsigned char *src_col = src++;
124 unsigned data = (*src_col ^ dmask) >> src_y;
125 int fg, bg;
126 long bo;
127
128 dst = dst_col;
129 dst_col += COL_INC;
130 row = height;
131
132#define UPDATE_SRC do { \
133 data >>= 1; \
134 if (data == 0x001) { \
135 src_col += stride; \
136 data = *src_col ^ dmask; \
137 } \
138 } while (0)
139
140 switch (drmode)
141 {
142 case DRMODE_COMPLEMENT:
143 do
144 {
145 if (data & 0x01)
146 *dst = ~(*dst);
147
148 dst += ROW_INC;
149 UPDATE_SRC;
150 }
151 while (--row);
152 break;
153
154 case DRMODE_BG:
155 if (lcd_backdrop)
156 {
157 bo = lcd_backdrop_offset;
158 do
159 {
160 if (!(data & 0x01))
161 *dst = *(fb_data *)((long)dst + bo);
162
163 dst += ROW_INC;
164 UPDATE_SRC;
165 }
166 while (--row);
167 }
168 else
169 {
170 bg = current_vp->bg_pattern;
171 do
172 {
173 if (!(data & 0x01))
174 *dst = bg;
175
176 dst += ROW_INC;
177 UPDATE_SRC;
178 }
179 while (--row);
180 }
181 break;
182
183 case DRMODE_FG:
184 fg = current_vp->fg_pattern;
185 do
186 {
187 if (data & 0x01)
188 *dst = fg;
189
190 dst += ROW_INC;
191 UPDATE_SRC;
192 }
193 while (--row);
194 break;
195
196 case DRMODE_SOLID:
197 fg = current_vp->fg_pattern;
198 if (lcd_backdrop)
199 {
200 bo = lcd_backdrop_offset;
201 do
202 {
203 *dst = (data & 0x01) ? fg
204 : *(fb_data *)((long)dst + bo);
205 dst += ROW_INC;
206 UPDATE_SRC;
207 }
208 while (--row);
209 }
210 else
211 {
212 bg = current_vp->bg_pattern;
213 do
214 {
215 *dst = (data & 0x01) ? fg : bg;
216 dst += ROW_INC;
217 UPDATE_SRC;
218 }
219 while (--row);
220 }
221 break;
222 }
223 }
224 while (src < src_end);
225}
226/* Draw a full monochrome bitmap */
227void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int height)
228{
229 lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height);
230}
231
232/* draw alpha bitmap for anti-alias font */
233#define ALPHA_COLOR_FONT_DEPTH 2
234#define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH)
235#define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1)
236#define ALPHA_COLOR_PIXEL_PER_BYTE (8 >> ALPHA_COLOR_FONT_DEPTH)
237#define ALPHA_COLOR_PIXEL_PER_WORD (32 >> ALPHA_COLOR_FONT_DEPTH)
238#ifdef CPU_ARM
239#define BLEND_INIT do {} while (0)
240#define BLEND_START(acc, color, alpha) \
241 asm volatile("mul %0, %1, %2" : "=&r" (acc) : "r" (color), "r" (alpha))
242#define BLEND_CONT(acc, color, alpha) \
243 asm volatile("mla %0, %1, %2, %0" : "+&r" (acc) : "r" (color), "r" (alpha))
244#define BLEND_OUT(acc) do {} while (0)
245#elif defined(CPU_COLDFIRE)
246#define ALPHA_BITMAP_READ_WORDS
247#define BLEND_INIT coldfire_set_macsr(EMAC_UNSIGNED)
248#define BLEND_START(acc, color, alpha) \
249 asm volatile("mac.l %0, %1, %%acc0" :: "%d" (color), "d" (alpha))
250#define BLEND_CONT BLEND_START
251#define BLEND_OUT(acc) asm volatile("movclr.l %%acc0, %0" : "=d" (acc))
252#else
253#define BLEND_INIT do {} while (0)
254#define BLEND_START(acc, color, alpha) ((acc) = (color) * (alpha))
255#define BLEND_CONT(acc, color, alpha) ((acc) += (color) * (alpha))
256#define BLEND_OUT(acc) do {} while (0)
257#endif
258
259/* Blend the given two colors */
260static inline unsigned blend_two_colors(unsigned c1, unsigned c2, unsigned a)
261{
262 a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1);
263#if (LCD_PIXELFORMAT == RGB565SWAPPED)
264 c1 = swap16(c1);
265 c2 = swap16(c2);
266#endif
267 unsigned c1l = (c1 | (c1 << 16)) & 0x07e0f81f;
268 unsigned c2l = (c2 | (c2 << 16)) & 0x07e0f81f;
269 unsigned p;
270 BLEND_START(p, c1l, a);
271 BLEND_CONT(p, c2l, ALPHA_COLOR_LOOKUP_SIZE + 1 - a);
272 BLEND_OUT(p);
273 p = (p >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f;
274 p |= (p >> 16);
275#if (LCD_PIXELFORMAT == RGB565SWAPPED)
276 return swap16(p);
277#else
278 return p;
279#endif
280}
281
282/* Blend the given color with the value from the alpha_color_lookup table */
283static inline unsigned blend_color(unsigned c, unsigned a)
284{
285 return blend_two_colors(c, current_vp->fg_pattern, a);
286}
287
288void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x,
289 int src_y, int stride, int x, int y,
290 int width, int height)
291{
292 fb_data *dst, *dst_row;
293 unsigned dmask = 0x00000000;
294 int drmode = current_vp->drawmode;
295 /* nothing to draw? */
296 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
297 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
298 return;
299 /* initialize blending */
300 BLEND_INIT;
301
302 /* clipping */
303 if (x < 0)
304 {
305 width += x;
306 src_x -= x;
307 x = 0;
308 }
309 if (y < 0)
310 {
311 height += y;
312 src_y -= y;
313 y = 0;
314 }
315 if (x + width > current_vp->width)
316 width = current_vp->width - x;
317 if (y + height > current_vp->height)
318 height = current_vp->height - y;
319
320 /* adjust for viewport */
321 x += current_vp->x;
322 y += current_vp->y;
323
324#if defined(HAVE_VIEWPORT_CLIP)
325 /********************* Viewport on screen clipping ********************/
326 /* nothing to draw? */
327 if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
328 || (x + width <= 0) || (y + height <= 0))
329 return;
330
331 /* clip image in viewport in screen */
332 if (x < 0)
333 {
334 width += x;
335 src_x -= x;
336 x = 0;
337 }
338 if (y < 0)
339 {
340 height += y;
341 src_y -= y;
342 y = 0;
343 }
344 if (x + width > LCD_WIDTH)
345 width = LCD_WIDTH - x;
346 if (y + height > LCD_HEIGHT)
347 height = LCD_HEIGHT - y;
348#endif
349
350 if (drmode & DRMODE_INVERSEVID)
351 {
352 dmask = 0xffffffff;
353 drmode &= DRMODE_SOLID; /* mask out inversevid */
354 }
355 if (drmode == DRMODE_BG)
356 {
357 dmask = ~dmask;
358 }
359
360 dst_row = LCDADDR(x, y);
361
362 int col, row = height;
363 unsigned data, pixels;
364 unsigned skip_end = (stride - width);
365 unsigned skip_start = src_y * stride + src_x;
366
367#ifdef ALPHA_BITMAP_READ_WORDS
368 uint32_t *src_w = (uint32_t *)((uintptr_t)src & ~3);
369 skip_start += ALPHA_COLOR_PIXEL_PER_BYTE * ((uintptr_t)src & 3);
370 src_w += skip_start / ALPHA_COLOR_PIXEL_PER_WORD;
371 data = letoh32(*src_w++) ^ dmask;
372 pixels = skip_start % ALPHA_COLOR_PIXEL_PER_WORD;
373#else
374 src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE;
375 data = *src ^ dmask;
376 pixels = skip_start % ALPHA_COLOR_PIXEL_PER_BYTE;
377#endif
378 data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT;
379#ifdef ALPHA_BITMAP_READ_WORDS
380 pixels = 8 - pixels;
381#endif
382
383 /* go through the rows and update each pixel */
384 do
385 {
386 col = width;
387 dst = dst_row;
388 dst_row += ROW_INC;
389#ifdef ALPHA_BITMAP_READ_WORDS
390#define UPDATE_SRC_ALPHA do { \
391 if (--pixels) \
392 data >>= ALPHA_COLOR_LOOKUP_SHIFT; \
393 else \
394 { \
395 data = letoh32(*src_w++) ^ dmask; \
396 pixels = ALPHA_COLOR_PIXEL_PER_WORD; \
397 } \
398 } while (0)
399#elif ALPHA_COLOR_PIXEL_PER_BYTE == 2
400#define UPDATE_SRC_ALPHA do { \
401 if (pixels ^= 1) \
402 data >>= ALPHA_COLOR_LOOKUP_SHIFT; \
403 else \
404 data = *(++src) ^ dmask; \
405 } while (0)
406#else
407#define UPDATE_SRC_ALPHA do { \
408 if (pixels = (++pixels % ALPHA_COLOR_PIXEL_PER_BYTE)) \
409 data >>= ALPHA_COLOR_LOOKUP_SHIFT; \
410 else \
411 data = *(++src) ^ dmask; \
412 } while (0)
413#endif
414 /* we don't want to have this in our inner
415 * loop and the codesize increase is minimal */
416 switch (drmode)
417 {
418 case DRMODE_COMPLEMENT:
419 do
420 {
421 *dst = blend_two_colors(*dst, ~(*dst),
422 data & ALPHA_COLOR_LOOKUP_SIZE );
423 dst += COL_INC;
424 UPDATE_SRC_ALPHA;
425 }
426 while (--col);
427 break;
428 case DRMODE_BG:
429 if(lcd_backdrop)
430 {
431 uintptr_t bo = lcd_backdrop_offset;
432 do
433 {
434 *dst = blend_two_colors(*dst, *(fb_data *)((uintptr_t)dst + bo),
435 data & ALPHA_COLOR_LOOKUP_SIZE );
436
437 dst += COL_INC;
438 UPDATE_SRC_ALPHA;
439 }
440 while (--col);
441 }
442 else
443 {
444 do
445 {
446 *dst = blend_two_colors(*dst, current_vp->bg_pattern,
447 data & ALPHA_COLOR_LOOKUP_SIZE );
448 dst += COL_INC;
449 UPDATE_SRC_ALPHA;
450 }
451 while (--col);
452 }
453 break;
454 case DRMODE_FG:
455 do
456 {
457 *dst = blend_color(*dst, data & ALPHA_COLOR_LOOKUP_SIZE );
458 dst += COL_INC;
459 UPDATE_SRC_ALPHA;
460 }
461 while (--col);
462 break;
463 case DRMODE_SOLID:
464 if(lcd_backdrop)
465 {
466 uintptr_t bo = lcd_backdrop_offset;
467 do
468 {
469 *dst = blend_color(*(fb_data *)((uintptr_t)dst + bo),
470 data & ALPHA_COLOR_LOOKUP_SIZE );
471 dst += COL_INC;
472 UPDATE_SRC_ALPHA;
473 }
474 while (--col);
475 }
476 else
477 {
478 do
479 {
480 *dst = blend_color(current_vp->bg_pattern,
481 data & ALPHA_COLOR_LOOKUP_SIZE );
482 dst += COL_INC;
483 UPDATE_SRC_ALPHA;
484 }
485 while (--col);
486 }
487 break;
488 }
489#ifdef ALPHA_BITMAP_READ_WORDS
490 if (skip_end < pixels)
491 {
492 pixels -= skip_end;
493 data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT;
494 } else {
495 pixels = skip_end - pixels;
496 src_w += pixels / ALPHA_COLOR_PIXEL_PER_WORD;
497 pixels %= ALPHA_COLOR_PIXEL_PER_WORD;
498 data = letoh32(*src_w++) ^ dmask;
499 data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT;
500 pixels = 8 - pixels;
501 }
502#else
503 if (skip_end)
504 {
505 pixels += skip_end;
506 if (pixels >= ALPHA_COLOR_PIXEL_PER_BYTE)
507 {
508 src += pixels / ALPHA_COLOR_PIXEL_PER_BYTE;
509 pixels %= ALPHA_COLOR_PIXEL_PER_BYTE;
510 data = *src ^ dmask;
511 data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT;
512 } else
513 data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT;
514 }
515#endif
516 } while (--row);
517}
diff --git a/firmware/drivers/lcd-16bit-vert.c b/firmware/drivers/lcd-16bit-vert.c
index 552d80c5aa..17a1a2dda2 100644
--- a/firmware/drivers/lcd-16bit-vert.c
+++ b/firmware/drivers/lcd-16bit-vert.c
@@ -712,493 +712,6 @@ void lcd_fillrect(int x, int y, int width, int height)
712 while (dst < dst_end); 712 while (dst < dst_end);
713} 713}
714 714
715/* About Rockbox' internal monochrome bitmap format:
716 *
717 * A bitmap contains one bit for every pixel that defines if that pixel is
718 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
719 * at top.
720 * The bytes are stored in row-major order, with byte 0 being top left,
721 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
722 * 0..7, the second row defines pixel row 8..15 etc.
723 *
724 * This is the mono bitmap format used on all other targets so far; the
725 * pixel packing doesn't really matter on a 8bit+ target. */
726
727/* Draw a partial monochrome bitmap */
728
729void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
730 int src_y, int stride, int x, int y,
731 int width, int height)
732{
733 const unsigned char *src_end;
734 fb_data *dst, *dst_end;
735 unsigned dmask = 0x100; /* bit 8 == sentinel */
736 int drmode = current_vp->drawmode;
737
738 /******************** Image in viewport clipping **********************/
739 /* nothing to draw? */
740 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
741 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
742 return;
743
744 if (x < 0)
745 {
746 width += x;
747 src_x -= x;
748 x = 0;
749 }
750 if (y < 0)
751 {
752 height += y;
753 src_y -= y;
754 y = 0;
755 }
756 if (x + width > current_vp->width)
757 width = current_vp->width - x;
758 if (y + height > current_vp->height)
759 height = current_vp->height - y;
760
761 /* adjust for viewport */
762 x += current_vp->x;
763 y += current_vp->y;
764
765#if defined(HAVE_VIEWPORT_CLIP)
766 /********************* Viewport on screen clipping ********************/
767 /* nothing to draw? */
768 if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
769 || (x + width <= 0) || (y + height <= 0))
770 return;
771
772 /* clip image in viewport in screen */
773 if (x < 0)
774 {
775 width += x;
776 src_x -= x;
777 x = 0;
778 }
779 if (y < 0)
780 {
781 height += y;
782 src_y -= y;
783 y = 0;
784 }
785 if (x + width > LCD_WIDTH)
786 width = LCD_WIDTH - x;
787 if (y + height > LCD_HEIGHT)
788 height = LCD_HEIGHT - y;
789#endif
790
791 src += stride * (src_y >> 3) + src_x; /* move starting point */
792 src_y &= 7;
793 src_end = src + width;
794 dst = LCDADDR(x, y);
795 dst_end = dst + height;
796
797 if (drmode & DRMODE_INVERSEVID)
798 {
799 dmask = 0x1ff; /* bit 8 == sentinel */
800 drmode &= DRMODE_SOLID; /* mask out inversevid */
801 }
802
803 do
804 {
805 const unsigned char *src_col = src++;
806 unsigned data = (*src_col ^ dmask) >> src_y;
807 fb_data *dst_col = dst;
808 int fg, bg;
809 long bo;
810
811#define UPDATE_SRC do { \
812 data >>= 1; \
813 if (data == 0x001) { \
814 src_col += stride; \
815 data = *src_col ^ dmask; \
816 } \
817 } while (0)
818
819 switch (drmode)
820 {
821 case DRMODE_COMPLEMENT:
822 do
823 {
824 if (data & 0x01)
825 *dst_col = ~(*dst_col);
826
827 dst_col++;
828 UPDATE_SRC;
829 }
830 while (dst_col < dst_end);
831 break;
832
833 case DRMODE_BG:
834 if (lcd_backdrop)
835 {
836 bo = lcd_backdrop_offset;
837 do
838 {
839 if (!(data & 0x01))
840 *dst_col = *(fb_data *)((long)dst_col + bo);
841
842 dst_col++;
843 UPDATE_SRC;
844 }
845 while (dst_col < dst_end);
846 }
847 else
848 {
849 bg = current_vp->bg_pattern;
850 do
851 {
852 if (!(data & 0x01))
853 *dst_col = bg;
854
855 dst_col++;
856 UPDATE_SRC;
857 }
858 while (dst_col < dst_end);
859 }
860 break;
861
862 case DRMODE_FG:
863 fg = current_vp->fg_pattern;
864 do
865 {
866 if (data & 0x01)
867 *dst_col = fg;
868
869 dst_col++;
870 UPDATE_SRC;
871 }
872 while (dst_col < dst_end);
873 break;
874
875 case DRMODE_SOLID:
876 fg = current_vp->fg_pattern;
877 if (lcd_backdrop)
878 {
879 bo = lcd_backdrop_offset;
880 do
881 {
882 *dst_col = (data & 0x01) ? fg
883 : *(fb_data *)((long)dst_col + bo);
884 dst_col++;
885 UPDATE_SRC;
886 }
887 while (dst_col < dst_end);
888 }
889 else
890 {
891 bg = current_vp->bg_pattern;
892 do
893 {
894 *dst_col = (data & 0x01) ? fg : bg;
895 dst_col ++;
896 UPDATE_SRC;
897 }
898 while (dst_col < dst_end);
899 }
900 break;
901 }
902
903 dst += LCD_HEIGHT;
904 dst_end += LCD_HEIGHT;
905 } while (src < src_end);
906}
907/* Draw a full monochrome bitmap */
908void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int height)
909{
910 lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height);
911}
912
913/* draw alpha bitmap for anti-alias font */
914#define ALPHA_COLOR_FONT_DEPTH 2
915#define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH)
916#define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1)
917#define ALPHA_COLOR_PIXEL_PER_BYTE (8 >> ALPHA_COLOR_FONT_DEPTH)
918#define ALPHA_COLOR_PIXEL_PER_WORD (32 >> ALPHA_COLOR_FONT_DEPTH)
919#ifdef CPU_ARM
920#define BLEND_INIT do {} while (0)
921#define BLEND_START(acc, color, alpha) \
922 asm volatile("mul %0, %1, %2" : "=&r" (acc) : "r" (color), "r" (alpha))
923#define BLEND_CONT(acc, color, alpha) \
924 asm volatile("mla %0, %1, %2, %0" : "+&r" (acc) : "r" (color), "r" (alpha))
925#define BLEND_OUT(acc) do {} while (0)
926#elif defined(CPU_COLDFIRE)
927#define ALPHA_BITMAP_READ_WORDS
928#define BLEND_INIT coldfire_set_macsr(EMAC_UNSIGNED)
929#define BLEND_START(acc, color, alpha) \
930 asm volatile("mac.l %0, %1, %%acc0" :: "%d" (color), "d" (alpha))
931#define BLEND_CONT BLEND_START
932#define BLEND_OUT(acc) asm volatile("movclr.l %%acc0, %0" : "=d" (acc))
933#else
934#define BLEND_INIT do {} while (0)
935#define BLEND_START(acc, color, alpha) ((acc) = (color) * (alpha))
936#define BLEND_CONT(acc, color, alpha) ((acc) += (color) * (alpha))
937#define BLEND_OUT(acc) do {} while (0)
938#endif
939
940/* Blend the given two colors */
941static inline unsigned blend_two_colors(unsigned c1, unsigned c2, unsigned a)
942{
943 a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1);
944#if (LCD_PIXELFORMAT == RGB565SWAPPED)
945 c1 = swap16(c1);
946 c2 = swap16(c2);
947#endif
948 unsigned c1l = (c1 | (c1 << 16)) & 0x07e0f81f;
949 unsigned c2l = (c2 | (c2 << 16)) & 0x07e0f81f;
950 unsigned p;
951 BLEND_START(p, c1l, a);
952 BLEND_CONT(p, c2l, ALPHA_COLOR_LOOKUP_SIZE + 1 - a);
953 BLEND_OUT(p);
954 p = (p >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f;
955 p |= (p >> 16);
956#if (LCD_PIXELFORMAT == RGB565SWAPPED)
957 return swap16(p);
958#else
959 return p;
960#endif
961}
962
963/* Blend the given color with the value from the alpha_color_lookup table */
964static inline unsigned blend_color(unsigned c, unsigned a)
965{
966 return blend_two_colors(c, current_vp->fg_pattern, a);
967}
968
969void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x,
970 int src_y, int stride, int x, int y,
971 int width, int height)
972{
973 fb_data *dst, *dst_row, *backdrop;
974 unsigned dmask = 0x00000000;
975 int drmode = current_vp->drawmode;
976 /* nothing to draw? */
977 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
978 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
979 return;
980 /* initialize blending */
981 BLEND_INIT;
982
983 /* clipping */
984 if (x < 0)
985 {
986 width += x;
987 src_x -= x;
988 x = 0;
989 }
990 if (y < 0)
991 {
992 height += y;
993 src_y -= y;
994 y = 0;
995 }
996 if (x + width > current_vp->width)
997 width = current_vp->width - x;
998 if (y + height > current_vp->height)
999 height = current_vp->height - y;
1000
1001
1002 if (drmode & DRMODE_INVERSEVID)
1003 {
1004 dmask = 0xffffffff;
1005 drmode &= DRMODE_SOLID; /* mask out inversevid */
1006 }
1007 if (drmode == DRMODE_BG)
1008 {
1009 dmask = ~dmask;
1010 }
1011
1012 /* adjust for viewport */
1013 x += current_vp->x;
1014 y += current_vp->y;
1015
1016#if defined(HAVE_VIEWPORT_CLIP)
1017 /********************* Viewport on screen clipping ********************/
1018 /* nothing to draw? */
1019 if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
1020 || (x + width <= 0) || (y + height <= 0))
1021 return;
1022
1023 /* clip image in viewport in screen */
1024 if (x < 0)
1025 {
1026 width += x;
1027 src_x -= x;
1028 x = 0;
1029 }
1030 if (y < 0)
1031 {
1032 height += y;
1033 src_y -= y;
1034 y = 0;
1035 }
1036 if (x + width > LCD_WIDTH)
1037 width = LCD_WIDTH - x;
1038 if (y + height > LCD_HEIGHT)
1039 height = LCD_HEIGHT - y;
1040#endif
1041
1042 dst_row = dst = LCDADDR(x, y);
1043
1044
1045 int col, row = height;
1046 unsigned data, pixels;
1047 unsigned skip_end = (stride - width);
1048 unsigned skip_start = src_y * stride + src_x;
1049
1050#ifdef ALPHA_BITMAP_READ_WORDS
1051 uint32_t *src_w = (uint32_t *)((uintptr_t)src & ~3);
1052 skip_start += ALPHA_COLOR_PIXEL_PER_BYTE * ((uintptr_t)src & 3);
1053 src_w += skip_start / ALPHA_COLOR_PIXEL_PER_WORD;
1054 data = letoh32(*src_w++) ^ dmask;
1055 pixels = skip_start % ALPHA_COLOR_PIXEL_PER_WORD;
1056#else
1057 src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE;
1058 data = *src ^ dmask;
1059 pixels = skip_start % ALPHA_COLOR_PIXEL_PER_BYTE;
1060#endif
1061 data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT;
1062#ifdef ALPHA_BITMAP_READ_WORDS
1063 pixels = 8 - pixels;
1064#endif
1065
1066 do
1067 {
1068 col = width;
1069 dst = dst_row++;
1070
1071#ifdef ALPHA_BITMAP_READ_WORDS
1072#define UPDATE_SRC_ALPHA do { \
1073 if (--pixels) \
1074 data >>= ALPHA_COLOR_LOOKUP_SHIFT; \
1075 else \
1076 { \
1077 data = letoh32(*src_w++) ^ dmask; \
1078 pixels = ALPHA_COLOR_PIXEL_PER_WORD; \
1079 } \
1080 } while (0)
1081#elif ALPHA_COLOR_PIXEL_PER_BYTE == 2
1082#define UPDATE_SRC_ALPHA do { \
1083 if (pixels ^= 1) \
1084 data >>= ALPHA_COLOR_LOOKUP_SHIFT; \
1085 else \
1086 data = *(++src) ^ dmask; \
1087 } while (0)
1088#else
1089#define UPDATE_SRC_ALPHA do { \
1090 if (pixels = (++pixels % ALPHA_COLOR_PIXEL_PER_BYTE)) \
1091 data >>= ALPHA_COLOR_LOOKUP_SHIFT; \
1092 else \
1093 data = *(++src) ^ dmask; \
1094 } while (0)
1095#endif
1096 /* we don't want to have this in our inner
1097 * loop and the codesize increase is minimal */
1098 switch (drmode)
1099 {
1100 case DRMODE_COMPLEMENT:
1101 do
1102 {
1103 *dst=blend_two_colors(*dst, ~(*dst),
1104 data & ALPHA_COLOR_LOOKUP_SIZE );
1105 dst += LCD_HEIGHT;
1106 UPDATE_SRC_ALPHA;
1107 }
1108 while (--col);
1109 break;
1110 case DRMODE_BG:
1111 if(lcd_backdrop)
1112 {
1113 backdrop = (fb_data *)((long)dst+lcd_backdrop_offset);
1114 do
1115 {
1116 *dst=blend_two_colors(*dst, *backdrop,
1117 data & ALPHA_COLOR_LOOKUP_SIZE );
1118 dst += LCD_HEIGHT;
1119 backdrop += LCD_HEIGHT;
1120 UPDATE_SRC_ALPHA;
1121 }
1122 while (--col);
1123 }
1124 else
1125 {
1126 do
1127 {
1128 *dst=blend_two_colors(*dst, current_vp->bg_pattern,
1129 data & ALPHA_COLOR_LOOKUP_SIZE );
1130 dst += LCD_HEIGHT;
1131 UPDATE_SRC_ALPHA;
1132 }
1133 while (--col);
1134 }
1135 break;
1136 case DRMODE_FG:
1137 do
1138 {
1139 *dst=blend_color(*dst, data & ALPHA_COLOR_LOOKUP_SIZE );
1140 dst += LCD_HEIGHT;
1141 UPDATE_SRC_ALPHA;
1142 }
1143 while (--col);
1144 break;
1145 case DRMODE_SOLID:
1146 if(lcd_backdrop)
1147 {
1148 backdrop = (fb_data *)((long)dst+lcd_backdrop_offset);
1149 do
1150 {
1151 *(dst)=blend_color(*backdrop,
1152 data & ALPHA_COLOR_LOOKUP_SIZE );
1153 dst += LCD_HEIGHT;
1154 backdrop += LCD_HEIGHT;
1155 UPDATE_SRC_ALPHA;
1156 }
1157 while (--col);
1158 }
1159 else
1160 {
1161 do
1162 {
1163 *(dst)=blend_color(current_vp->bg_pattern,
1164 data & ALPHA_COLOR_LOOKUP_SIZE );
1165 dst += LCD_HEIGHT;
1166 UPDATE_SRC_ALPHA;
1167 }
1168 while (--col);
1169 }
1170 break;
1171 }
1172#ifdef ALPHA_BITMAP_READ_WORDS
1173 if (skip_end < pixels)
1174 {
1175 pixels -= skip_end;
1176 data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT;
1177 } else {
1178 pixels = skip_end - pixels;
1179 src_w += pixels / ALPHA_COLOR_PIXEL_PER_WORD;
1180 pixels %= ALPHA_COLOR_PIXEL_PER_WORD;
1181 data = letoh32(*src_w++) ^ dmask;
1182 data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT;
1183 pixels = 8 - pixels;
1184 }
1185#else
1186 if (skip_end)
1187 {
1188 pixels += skip_end;
1189 if (pixels >= ALPHA_COLOR_PIXEL_PER_BYTE)
1190 {
1191 src += pixels / ALPHA_COLOR_PIXEL_PER_BYTE;
1192 pixels %= ALPHA_COLOR_PIXEL_PER_BYTE;
1193 data = *src ^ dmask;
1194 data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT;
1195 } else
1196 data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT;
1197 }
1198#endif
1199 } while (--row);
1200}
1201
1202/* Draw a partial native bitmap */ 715/* Draw a partial native bitmap */
1203void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, 716void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
1204 int stride, int x, int y, int width, 717 int stride, int x, int y, int width,
@@ -1371,4 +884,9 @@ void lcd_bitmap_transparent(const fb_data *src, int x, int y,
1371 STRIDE(SCREEN_MAIN, width, height), x, y, width, height); 884 STRIDE(SCREEN_MAIN, width, height), x, y, width, height);
1372} 885}
1373 886
887#define ROW_INC 1
888#define COL_INC LCD_HEIGHT
889
890#include "lcd-16bit-common.c"
891
1374#include "lcd-bitmap-common.c" 892#include "lcd-bitmap-common.c"
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c
index 2017a7e5ab..28c3285a9c 100644
--- a/firmware/drivers/lcd-16bit.c
+++ b/firmware/drivers/lcd-16bit.c
@@ -8,6 +8,8 @@
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2005 by Dave Chapman 10 * Copyright (C) 2005 by Dave Chapman
11 *
12 * Copyright (C) 2009 by Karl Kurbjun
11 * 13 *
12 * Rockbox driver for 16-bit colour LCDs 14 * Rockbox driver for 16-bit colour LCDs
13 * 15 *
@@ -20,6 +22,7 @@
20 * KIND, either express or implied. 22 * KIND, either express or implied.
21 * 23 *
22 ****************************************************************************/ 24 ****************************************************************************/
25
23#include "config.h" 26#include "config.h"
24 27
25#include "cpu.h" 28#include "cpu.h"
@@ -705,484 +708,6 @@ void lcd_fillrect(int x, int y, int width, int height)
705 while (dst < dst_end); 708 while (dst < dst_end);
706} 709}
707 710
708/* About Rockbox' internal monochrome bitmap format:
709 *
710 * A bitmap contains one bit for every pixel that defines if that pixel is
711 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
712 * at top.
713 * The bytes are stored in row-major order, with byte 0 being top left,
714 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
715 * 0..7, the second row defines pixel row 8..15 etc.
716 *
717 * This is the mono bitmap format used on all other targets so far; the
718 * pixel packing doesn't really matter on a 8bit+ target. */
719
720/* Draw a partial monochrome bitmap */
721
722void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
723 int src_y, int stride, int x, int y,
724 int width, int height)
725{
726 const unsigned char *src_end;
727 fb_data *dst, *dst_end;
728 unsigned dmask = 0x100; /* bit 8 == sentinel */
729 int drmode = current_vp->drawmode;
730
731 /******************** Image in viewport clipping **********************/
732 /* nothing to draw? */
733 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
734 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
735 return;
736
737 if (x < 0)
738 {
739 width += x;
740 src_x -= x;
741 x = 0;
742 }
743 if (y < 0)
744 {
745 height += y;
746 src_y -= y;
747 y = 0;
748 }
749 if (x + width > current_vp->width)
750 width = current_vp->width - x;
751 if (y + height > current_vp->height)
752 height = current_vp->height - y;
753
754 /* adjust for viewport */
755 x += current_vp->x;
756 y += current_vp->y;
757
758#if defined(HAVE_VIEWPORT_CLIP)
759 /********************* Viewport on screen clipping ********************/
760 /* nothing to draw? */
761 if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
762 || (x + width <= 0) || (y + height <= 0))
763 return;
764
765 /* clip image in viewport in screen */
766 if (x < 0)
767 {
768 width += x;
769 src_x -= x;
770 x = 0;
771 }
772 if (y < 0)
773 {
774 height += y;
775 src_y -= y;
776 y = 0;
777 }
778 if (x + width > LCD_WIDTH)
779 width = LCD_WIDTH - x;
780 if (y + height > LCD_HEIGHT)
781 height = LCD_HEIGHT - y;
782#endif
783
784 src += stride * (src_y >> 3) + src_x; /* move starting point */
785 src_y &= 7;
786 src_end = src + width;
787 dst = LCDADDR(x, y);
788 dst_end = dst + height * LCD_WIDTH;
789
790 if (drmode & DRMODE_INVERSEVID)
791 {
792 dmask = 0x1ff; /* bit 8 == sentinel */
793 drmode &= DRMODE_SOLID; /* mask out inversevid */
794 }
795
796 do
797 {
798 const unsigned char *src_col = src++;
799 unsigned data = (*src_col ^ dmask) >> src_y;
800 fb_data *dst_col = dst++;
801 int fg, bg;
802 long bo;
803
804#define UPDATE_SRC do { \
805 data >>= 1; \
806 if (data == 0x001) { \
807 src_col += stride; \
808 data = *src_col ^ dmask; \
809 } \
810 } while (0)
811
812 switch (drmode)
813 {
814 case DRMODE_COMPLEMENT:
815 do
816 {
817 if (data & 0x01)
818 *dst_col = ~(*dst_col);
819
820 dst_col += LCD_WIDTH;
821 UPDATE_SRC;
822 }
823 while (dst_col < dst_end);
824 break;
825
826 case DRMODE_BG:
827 if (lcd_backdrop)
828 {
829 bo = lcd_backdrop_offset;
830 do
831 {
832 if (!(data & 0x01))
833 *dst_col = *(fb_data *)((long)dst_col + bo);
834
835 dst_col += LCD_WIDTH;
836 UPDATE_SRC;
837 }
838 while (dst_col < dst_end);
839 }
840 else
841 {
842 bg = current_vp->bg_pattern;
843 do
844 {
845 if (!(data & 0x01))
846 *dst_col = bg;
847
848 dst_col += LCD_WIDTH;
849 UPDATE_SRC;
850 }
851 while (dst_col < dst_end);
852 }
853 break;
854
855 case DRMODE_FG:
856 fg = current_vp->fg_pattern;
857 do
858 {
859 if (data & 0x01)
860 *dst_col = fg;
861
862 dst_col += LCD_WIDTH;
863 UPDATE_SRC;
864 }
865 while (dst_col < dst_end);
866 break;
867
868 case DRMODE_SOLID:
869 fg = current_vp->fg_pattern;
870 if (lcd_backdrop)
871 {
872 bo = lcd_backdrop_offset;
873 do
874 {
875 *dst_col = (data & 0x01) ? fg
876 : *(fb_data *)((long)dst_col + bo);
877 dst_col += LCD_WIDTH;
878 UPDATE_SRC;
879 }
880 while (dst_col < dst_end);
881 }
882 else
883 {
884 bg = current_vp->bg_pattern;
885 do
886 {
887 *dst_col = (data & 0x01) ? fg : bg;
888 dst_col += LCD_WIDTH;
889 UPDATE_SRC;
890 }
891 while (dst_col < dst_end);
892 }
893 break;
894 }
895 }
896 while (src < src_end);
897}
898/* Draw a full monochrome bitmap */
899void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int height)
900{
901 lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height);
902}
903
904/* draw alpha bitmap for anti-alias font */
905#define ALPHA_COLOR_FONT_DEPTH 2
906#define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH)
907#define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1)
908#define ALPHA_COLOR_PIXEL_PER_BYTE (8 >> ALPHA_COLOR_FONT_DEPTH)
909#define ALPHA_COLOR_PIXEL_PER_WORD (32 >> ALPHA_COLOR_FONT_DEPTH)
910#ifdef CPU_ARM
911#define BLEND_INIT do {} while (0)
912#define BLEND_START(acc, color, alpha) \
913 asm volatile("mul %0, %1, %2" : "=&r" (acc) : "r" (color), "r" (alpha))
914#define BLEND_CONT(acc, color, alpha) \
915 asm volatile("mla %0, %1, %2, %0" : "+&r" (acc) : "r" (color), "r" (alpha))
916#define BLEND_OUT(acc) do {} while (0)
917#elif defined(CPU_COLDFIRE)
918#define ALPHA_BITMAP_READ_WORDS
919#define BLEND_INIT coldfire_set_macsr(EMAC_UNSIGNED)
920#define BLEND_START(acc, color, alpha) \
921 asm volatile("mac.l %0, %1, %%acc0" :: "%d" (color), "d" (alpha))
922#define BLEND_CONT BLEND_START
923#define BLEND_OUT(acc) asm volatile("movclr.l %%acc0, %0" : "=d" (acc))
924#else
925#define BLEND_INIT do {} while (0)
926#define BLEND_START(acc, color, alpha) ((acc) = (color) * (alpha))
927#define BLEND_CONT(acc, color, alpha) ((acc) += (color) * (alpha))
928#define BLEND_OUT(acc) do {} while (0)
929#endif
930
931/* Blend the given two colors */
932static inline unsigned blend_two_colors(unsigned c1, unsigned c2, unsigned a)
933{
934 a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1);
935#if (LCD_PIXELFORMAT == RGB565SWAPPED)
936 c1 = swap16(c1);
937 c2 = swap16(c2);
938#endif
939 unsigned c1l = (c1 | (c1 << 16)) & 0x07e0f81f;
940 unsigned c2l = (c2 | (c2 << 16)) & 0x07e0f81f;
941 unsigned p;
942 BLEND_START(p, c1l, a);
943 BLEND_CONT(p, c2l, ALPHA_COLOR_LOOKUP_SIZE + 1 - a);
944 BLEND_OUT(p);
945 p = (p >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f;
946 p |= (p >> 16);
947#if (LCD_PIXELFORMAT == RGB565SWAPPED)
948 return swap16(p);
949#else
950 return p;
951#endif
952}
953
954/* Blend the given color with the value from the alpha_color_lookup table */
955static inline unsigned blend_color(unsigned c, unsigned a)
956{
957 return blend_two_colors(c, current_vp->fg_pattern, a);
958}
959
960void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x,
961 int src_y, int stride, int x, int y,
962 int width, int height)
963{
964 fb_data *dst, *backdrop;
965 unsigned dmask = 0x00000000;
966 int drmode = current_vp->drawmode;
967 /* nothing to draw? */
968 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
969 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
970 return;
971 /* initialize blending */
972 BLEND_INIT;
973
974 /* clipping */
975 if (x < 0)
976 {
977 width += x;
978 src_x -= x;
979 x = 0;
980 }
981 if (y < 0)
982 {
983 height += y;
984 src_y -= y;
985 y = 0;
986 }
987 if (x + width > current_vp->width)
988 width = current_vp->width - x;
989 if (y + height > current_vp->height)
990 height = current_vp->height - y;
991
992 /* adjust for viewport */
993 x += current_vp->x;
994 y += current_vp->y;
995
996#if defined(HAVE_VIEWPORT_CLIP)
997 /********************* Viewport on screen clipping ********************/
998 /* nothing to draw? */
999 if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
1000 || (x + width <= 0) || (y + height <= 0))
1001 return;
1002
1003 /* clip image in viewport in screen */
1004 if (x < 0)
1005 {
1006 width += x;
1007 src_x -= x;
1008 x = 0;
1009 }
1010 if (y < 0)
1011 {
1012 height += y;
1013 src_y -= y;
1014 y = 0;
1015 }
1016 if (x + width > LCD_WIDTH)
1017 width = LCD_WIDTH - x;
1018 if (y + height > LCD_HEIGHT)
1019 height = LCD_HEIGHT - y;
1020#endif
1021
1022 if (drmode & DRMODE_INVERSEVID)
1023 {
1024 dmask = 0xffffffff;
1025 drmode &= DRMODE_SOLID; /* mask out inversevid */
1026 }
1027 if (drmode == DRMODE_BG)
1028 {
1029 dmask = ~dmask;
1030 }
1031
1032 dst = LCDADDR(x, y);
1033
1034 int col, row = height;
1035 unsigned data, pixels;
1036 unsigned skip_end = (stride - width);
1037 unsigned skip_start = src_y * stride + src_x;
1038
1039#ifdef ALPHA_BITMAP_READ_WORDS
1040 uint32_t *src_w = (uint32_t *)((uintptr_t)src & ~3);
1041 skip_start += ALPHA_COLOR_PIXEL_PER_BYTE * ((uintptr_t)src & 3);
1042 src_w += skip_start / ALPHA_COLOR_PIXEL_PER_WORD;
1043 data = letoh32(*src_w++) ^ dmask;
1044 pixels = skip_start % ALPHA_COLOR_PIXEL_PER_WORD;
1045#else
1046 src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE;
1047 data = *src ^ dmask;
1048 pixels = skip_start % ALPHA_COLOR_PIXEL_PER_BYTE;
1049#endif
1050 data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT;
1051#ifdef ALPHA_BITMAP_READ_WORDS
1052 pixels = 8 - pixels;
1053#endif
1054
1055 do
1056 {
1057 col = width;
1058#ifdef ALPHA_BITMAP_READ_WORDS
1059#define UPDATE_SRC_ALPHA do { \
1060 if (--pixels) \
1061 data >>= ALPHA_COLOR_LOOKUP_SHIFT; \
1062 else \
1063 { \
1064 data = letoh32(*src_w++) ^ dmask; \
1065 pixels = ALPHA_COLOR_PIXEL_PER_WORD; \
1066 } \
1067 } while (0)
1068#elif ALPHA_COLOR_PIXEL_PER_BYTE == 2
1069#define UPDATE_SRC_ALPHA do { \
1070 if (pixels ^= 1) \
1071 data >>= ALPHA_COLOR_LOOKUP_SHIFT; \
1072 else \
1073 data = *(++src) ^ dmask; \
1074 } while (0)
1075#else
1076#define UPDATE_SRC_ALPHA do { \
1077 if (pixels = (++pixels % ALPHA_COLOR_PIXEL_PER_BYTE)) \
1078 data >>= ALPHA_COLOR_LOOKUP_SHIFT; \
1079 else \
1080 data = *(++src) ^ dmask; \
1081 } while (0)
1082#endif
1083 /* we don't want to have this in our inner
1084 * loop and the codesize increase is minimal */
1085 switch (drmode)
1086 {
1087 case DRMODE_COMPLEMENT:
1088 do
1089 {
1090 *dst=blend_two_colors(*dst, ~(*dst),
1091 data & ALPHA_COLOR_LOOKUP_SIZE );
1092 dst++;
1093 UPDATE_SRC_ALPHA;
1094 }
1095 while (--col);
1096 break;
1097 case DRMODE_BG:
1098 if(lcd_backdrop)
1099 {
1100 backdrop = (fb_data *)((long)dst+lcd_backdrop_offset);
1101 do
1102 {
1103 *dst=blend_two_colors(*dst, *(backdrop++),
1104 data & ALPHA_COLOR_LOOKUP_SIZE );
1105 dst++;
1106 UPDATE_SRC_ALPHA;
1107 }
1108 while (--col);
1109 }
1110 else
1111 {
1112 do
1113 {
1114 *dst=blend_two_colors(*dst, current_vp->bg_pattern,
1115 data & ALPHA_COLOR_LOOKUP_SIZE );
1116 dst++;
1117 UPDATE_SRC_ALPHA;
1118 }
1119 while (--col);
1120 }
1121 break;
1122 case DRMODE_FG:
1123 do
1124 {
1125 *dst=blend_color(*dst, data & ALPHA_COLOR_LOOKUP_SIZE );
1126 dst++;
1127 UPDATE_SRC_ALPHA;
1128 }
1129 while (--col);
1130 break;
1131 case DRMODE_SOLID:
1132 if(lcd_backdrop)
1133 {
1134 backdrop = (fb_data *)((long)dst+lcd_backdrop_offset);
1135 do
1136 {
1137 *(dst++)=blend_color(*(backdrop++),
1138 data & ALPHA_COLOR_LOOKUP_SIZE );
1139 UPDATE_SRC_ALPHA;
1140 }
1141 while (--col);
1142 }
1143 else
1144 {
1145 do
1146 {
1147 *(dst++)=blend_color(current_vp->bg_pattern,
1148 data & ALPHA_COLOR_LOOKUP_SIZE );
1149 UPDATE_SRC_ALPHA;
1150 }
1151 while (--col);
1152 }
1153 break;
1154 }
1155#ifdef ALPHA_BITMAP_READ_WORDS
1156 if (skip_end < pixels)
1157 {
1158 pixels -= skip_end;
1159 data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT;
1160 } else {
1161 pixels = skip_end - pixels;
1162 src_w += pixels / ALPHA_COLOR_PIXEL_PER_WORD;
1163 pixels %= ALPHA_COLOR_PIXEL_PER_WORD;
1164 data = letoh32(*src_w++) ^ dmask;
1165 data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT;
1166 pixels = 8 - pixels;
1167 }
1168#else
1169 if (skip_end)
1170 {
1171 pixels += skip_end;
1172 if (pixels >= ALPHA_COLOR_PIXEL_PER_BYTE)
1173 {
1174 src += pixels / ALPHA_COLOR_PIXEL_PER_BYTE;
1175 pixels %= ALPHA_COLOR_PIXEL_PER_BYTE;
1176 data = *src ^ dmask;
1177 data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT;
1178 } else
1179 data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT;
1180 }
1181#endif
1182 dst += LCD_WIDTH - width;
1183 } while (--row);
1184}
1185
1186/* Draw a partial native bitmap */ 711/* Draw a partial native bitmap */
1187void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, 712void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
1188 int stride, int x, int y, int width, 713 int stride, int x, int y, int width,
@@ -1388,4 +913,10 @@ void lcd_bitmap_transparent(const fb_data *src, int x, int y,
1388 lcd_bitmap_transparent_part(src, 0, 0, width, x, y, width, height); 913 lcd_bitmap_transparent_part(src, 0, 0, width, x, y, width, height);
1389} 914}
1390 915
916#define ROW_INC LCD_WIDTH
917#define COL_INC 1
918
919#include "lcd-16bit-common.c"
920
1391#include "lcd-bitmap-common.c" 921#include "lcd-bitmap-common.c"
922