1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 Jens Arnold
12 * Rockbox driver for 2bit vertically interleaved LCDs
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.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
36 #include "rbunicode.h"
38 #include "scroll_engine.h"
40 #ifndef LCDFN /* Not compiling for remote - define macros for main LCD. */
41 #define LCDFN(fn) lcd_ ## fn
42 #define FBFN(fn) fb_ ## fn
43 #define LCDM(ma) LCD_ ## ma
44 #define LCDNAME "lcd_"
50 FBFN(data
) LCDFN(framebuffer
)[LCDM(FBHEIGHT
)][LCDM(FBWIDTH
)] IRAM_LCDFRAMEBUFFER
;
52 static const FBFN(data
) patterns
[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
54 static FBFN(data
) *backdrop
= NULL
;
55 static long backdrop_offset IDATA_ATTR
= 0;
57 static struct viewport default_vp
=
62 .height
= LCDM(HEIGHT
),
63 .font
= FONT_SYSFIXED
,
64 .drawmode
= DRMODE_SOLID
,
65 .fg_pattern
= LCDM(DEFAULT_FG
),
66 .bg_pattern
= LCDM(DEFAULT_BG
)
69 static struct viewport
* current_vp IBSS_ATTR
;
71 static unsigned fg_pattern IBSS_ATTR
;
72 static unsigned bg_pattern IBSS_ATTR
;
76 void LCDFN(set_viewport
)(struct viewport
* vp
)
79 current_vp
= &default_vp
;
83 fg_pattern
= patterns
[current_vp
->fg_pattern
& 3];
84 bg_pattern
= patterns
[current_vp
->bg_pattern
& 3];
86 #if defined(SIMULATOR)
87 /* Force the viewport to be within bounds. If this happens it should
88 * be considered an error - the viewport will not draw as it might be
91 if((unsigned) current_vp
->x
> (unsigned) LCDM(WIDTH
)
92 || (unsigned) current_vp
->y
> (unsigned) LCDM(HEIGHT
)
93 || current_vp
->x
+ current_vp
->width
> LCDM(WIDTH
)
94 || current_vp
->y
+ current_vp
->height
> LCDM(HEIGHT
))
96 #if !defined(HAVE_VIEWPORT_CLIP)
101 "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n",
102 current_vp
->x
, current_vp
->y
,
103 current_vp
->width
, current_vp
->height
);
109 void LCDFN(update_viewport
)(void)
111 LCDFN(update_rect
)(current_vp
->x
, current_vp
->y
,
112 current_vp
->width
, current_vp
->height
);
115 void LCDFN(update_viewport_rect
)(int x
, int y
, int width
, int height
)
117 LCDFN(update_rect
)(current_vp
->x
+ x
, current_vp
->y
+ y
, width
, height
);
121 void LCDFN(init
)(void)
123 LCDFN(set_viewport
)(NULL
);
124 LCDFN(clear_display
)();
125 LCDFN(init_device
)();
131 /*** parameter handling ***/
133 #if !defined(MAIN_LCD) && defined(HAVE_LCD_COLOR)
134 /* When compiling for remote LCD and the main LCD is colour. */
135 unsigned lcd_remote_color_to_native(unsigned color
)
137 unsigned r
= (color
& 0xf800) >> 10;
138 unsigned g
= (color
& 0x07e0) >> 5;
139 unsigned b
= (color
& 0x001f) << 2;
142 * |Y'| = |0.299000 0.587000 0.114000| |G|
145 return (5*r
+ 9*g
+ b
) >> 8;
149 void LCDFN(set_drawmode
)(int mode
)
151 current_vp
->drawmode
= mode
& (DRMODE_SOLID
|DRMODE_INVERSEVID
);
154 int LCDFN(get_drawmode
)(void)
156 return current_vp
->drawmode
;
159 void LCDFN(set_foreground
)(unsigned brightness
)
161 current_vp
->fg_pattern
= brightness
;
162 fg_pattern
= patterns
[brightness
& 3];
165 unsigned LCDFN(get_foreground
)(void)
167 return current_vp
->fg_pattern
;
170 void LCDFN(set_background
)(unsigned brightness
)
172 current_vp
->bg_pattern
= brightness
;
173 bg_pattern
= patterns
[brightness
& 3];
176 unsigned LCDFN(get_background
)(void)
178 return current_vp
->bg_pattern
;
181 void LCDFN(set_drawinfo
)(int mode
, unsigned fg_brightness
,
182 unsigned bg_brightness
)
184 LCDFN(set_drawmode
)(mode
);
185 LCDFN(set_foreground
)(fg_brightness
);
186 LCDFN(set_background
)(bg_brightness
);
189 int LCDFN(getwidth
)(void)
191 return current_vp
->width
;
194 int LCDFN(getheight
)(void)
196 return current_vp
->height
;
198 void LCDFN(setfont
)(int newfont
)
200 current_vp
->font
= newfont
;
203 int LCDFN(getfont
)(void)
205 return current_vp
->font
;
208 int LCDFN(getstringsize
)(const unsigned char *str
, int *w
, int *h
)
210 return font_getstringsize(str
, w
, h
, current_vp
->font
);
213 /*** low-level drawing functions ***/
215 static void setpixel(int x
, int y
)
217 unsigned mask
= 0x0101 << (y
& 7);
218 FBFN(data
) *address
= &LCDFN(framebuffer
)[y
>>3][x
];
219 unsigned data
= *address
;
221 *address
= data
^ ((data
^ fg_pattern
) & mask
);
224 static void clearpixel(int x
, int y
)
226 unsigned mask
= 0x0101 << (y
& 7);
227 FBFN(data
) *address
= &LCDFN(framebuffer
)[y
>>3][x
];
228 unsigned data
= *address
;
230 *address
= data
^ ((data
^ bg_pattern
) & mask
);
233 static void clearimgpixel(int x
, int y
)
235 unsigned mask
= 0x0101 << (y
& 7);
236 FBFN(data
) *address
= &LCDFN(framebuffer
)[y
>>3][x
];
237 unsigned data
= *address
;
239 *address
= data
^ ((data
^ *(FBFN(data
) *)((long)address
240 + backdrop_offset
)) & mask
);
243 static void flippixel(int x
, int y
)
245 unsigned mask
= 0x0101 << (y
& 7);
246 FBFN(data
) *address
= &LCDFN(framebuffer
)[y
>>3][x
];
251 static void nopixel(int x
, int y
)
257 LCDFN(pixelfunc_type
)* const LCDFN(pixelfuncs_bgcolor
)[8] = {
258 flippixel
, nopixel
, setpixel
, setpixel
,
259 nopixel
, clearpixel
, nopixel
, clearpixel
262 LCDFN(pixelfunc_type
)* const LCDFN(pixelfuncs_backdrop
)[8] = {
263 flippixel
, nopixel
, setpixel
, setpixel
,
264 nopixel
, clearimgpixel
, nopixel
, clearimgpixel
267 LCDFN(pixelfunc_type
)* const *LCDFN(pixelfuncs
) = LCDFN(pixelfuncs_bgcolor
);
269 /* 'mask' and 'bits' contain 2 bits per pixel */
270 static void ICODE_ATTR
flipblock(FBFN(data
) *address
, unsigned mask
,
273 *address
^= bits
& mask
;
276 static void ICODE_ATTR
bgblock(FBFN(data
) *address
, unsigned mask
,
279 unsigned data
= *address
;
281 *address
= data
^ ((data
^ bg_pattern
) & mask
& ~bits
);
284 static void ICODE_ATTR
bgimgblock(FBFN(data
) *address
, unsigned mask
,
287 unsigned data
= *address
;
289 *address
= data
^ ((data
^ *(FBFN(data
) *)((long)address
290 + backdrop_offset
)) & mask
& ~bits
);
293 static void ICODE_ATTR
fgblock(FBFN(data
) *address
, unsigned mask
,
296 unsigned data
= *address
;
298 *address
= data
^ ((data
^ fg_pattern
) & mask
& bits
);
301 static void ICODE_ATTR
solidblock(FBFN(data
) *address
, unsigned mask
,
304 unsigned data
= *address
;
305 unsigned bgp
= bg_pattern
;
307 bits
= bgp
^ ((bgp
^ fg_pattern
) & bits
);
308 *address
= data
^ ((data
^ bits
) & mask
);
311 static void ICODE_ATTR
solidimgblock(FBFN(data
) *address
, unsigned mask
,
314 unsigned data
= *address
;
315 unsigned bgp
= *(FBFN(data
) *)((long)address
+ backdrop_offset
);
317 bits
= bgp
^ ((bgp
^ fg_pattern
) & bits
);
318 *address
= data
^ ((data
^ bits
) & mask
);
321 static void ICODE_ATTR
flipinvblock(FBFN(data
) *address
, unsigned mask
,
324 *address
^= ~bits
& mask
;
327 static void ICODE_ATTR
bginvblock(FBFN(data
) *address
, unsigned mask
,
330 unsigned data
= *address
;
332 *address
= data
^ ((data
^ bg_pattern
) & mask
& bits
);
335 static void ICODE_ATTR
bgimginvblock(FBFN(data
) *address
, unsigned mask
,
338 unsigned data
= *address
;
340 *address
= data
^ ((data
^ *(FBFN(data
) *)((long)address
341 + backdrop_offset
)) & mask
& bits
);
344 static void ICODE_ATTR
fginvblock(FBFN(data
) *address
, unsigned mask
,
347 unsigned data
= *address
;
349 *address
= data
^ ((data
^ fg_pattern
) & mask
& ~bits
);
352 static void ICODE_ATTR
solidinvblock(FBFN(data
) *address
, unsigned mask
,
355 unsigned data
= *address
;
356 unsigned fgp
= fg_pattern
;
358 bits
= fgp
^ ((fgp
^ bg_pattern
) & bits
);
359 *address
= data
^ ((data
^ bits
) & mask
);
362 static void ICODE_ATTR
solidimginvblock(FBFN(data
) *address
, unsigned mask
,
365 unsigned data
= *address
;
366 unsigned fgp
= fg_pattern
;
368 bits
= fgp
^ ((fgp
^ *(FBFN(data
) *)((long)address
369 + backdrop_offset
)) & bits
);
370 *address
= data
^ ((data
^ bits
) & mask
);
373 LCDFN(blockfunc_type
)* const LCDFN(blockfuncs_bgcolor
)[8] = {
374 flipblock
, bgblock
, fgblock
, solidblock
,
375 flipinvblock
, bginvblock
, fginvblock
, solidinvblock
378 LCDFN(blockfunc_type
)* const LCDFN(blockfuncs_backdrop
)[8] = {
379 flipblock
, bgimgblock
, fgblock
, solidimgblock
,
380 flipinvblock
, bgimginvblock
, fginvblock
, solidimginvblock
383 LCDFN(blockfunc_type
)* const *LCDFN(blockfuncs
) = LCDFN(blockfuncs_bgcolor
);
386 void LCDFN(set_backdrop
)(FBFN(data
) *bd
)
391 backdrop_offset
= (long)bd
- (long)LCDFN(framebuffer
);
392 LCDFN(pixelfuncs
) = LCDFN(pixelfuncs_backdrop
);
393 LCDFN(blockfuncs
) = LCDFN(blockfuncs_backdrop
);
398 LCDFN(pixelfuncs
) = LCDFN(pixelfuncs_bgcolor
);
399 LCDFN(blockfuncs
) = LCDFN(blockfuncs_bgcolor
);
403 FBFN(data
)* LCDFN(get_backdrop
)(void)
408 static inline void setblock(FBFN(data
) *address
, unsigned mask
, unsigned bits
)
410 unsigned data
= *address
;
413 *address
= data
^ (bits
& mask
);
416 /*** drawing functions ***/
418 /* Clear the whole display */
419 void LCDFN(clear_display
)(void)
421 if (default_vp
.drawmode
& DRMODE_INVERSEVID
)
423 memset(LCDFN(framebuffer
), patterns
[default_vp
.fg_pattern
& 3],
424 sizeof LCDFN(framebuffer
));
429 memcpy(LCDFN(framebuffer
), backdrop
, sizeof LCDFN(framebuffer
));
431 memset(LCDFN(framebuffer
), patterns
[default_vp
.bg_pattern
& 3],
432 sizeof LCDFN(framebuffer
));
435 LCDFN(scroll_info
).lines
= 0;
438 /* Clear the current viewport */
439 void LCDFN(clear_viewport
)(void)
443 if (current_vp
== &default_vp
)
445 LCDFN(clear_display
)();
449 lastmode
= current_vp
->drawmode
;
451 /* Invert the INVERSEVID bit and set basic mode to SOLID */
452 current_vp
->drawmode
= (~lastmode
& DRMODE_INVERSEVID
) |
455 LCDFN(fillrect
)(0, 0, current_vp
->width
, current_vp
->height
);
457 current_vp
->drawmode
= lastmode
;
459 LCDFN(scroll_stop
)(current_vp
);
463 /* Set a single pixel */
464 void LCDFN(drawpixel
)(int x
, int y
)
466 if ( ((unsigned)x
< (unsigned)current_vp
->width
)
467 && ((unsigned)y
< (unsigned)current_vp
->height
)
468 #if defined(HAVE_VIEWPORT_CLIP)
469 && ((unsigned)x
< (unsigned)LCDM(WIDTH
))
470 && ((unsigned)y
< (unsigned)LCDM(HEIGHT
))
473 LCDFN(pixelfuncs
)[current_vp
->drawmode
](current_vp
->x
+x
, current_vp
->y
+y
);
477 void LCDFN(drawline
)(int x1
, int y1
, int x2
, int y2
)
485 LCDFN(pixelfunc_type
) *pfunc
= LCDFN(pixelfuncs
)[current_vp
->drawmode
];
487 deltax
= abs(x2
- x1
);
490 /* DEBUGF(LCDNAME "drawline() called for vertical line - optimisation.\n"); */
491 LCDFN(vline
)(x1
, y1
, y2
);
494 deltay
= abs(y2
- y1
);
497 /* DEBUGF(LCDNAME "drawline() called for horizontal line - optimisation.\n"); */
498 LCDFN(hline
)(x1
, x2
, y1
);
504 if (deltax
>= deltay
)
507 d
= 2 * deltay
- deltax
;
509 dinc2
= (deltay
- deltax
) * 2;
516 d
= 2 * deltax
- deltay
;
518 dinc2
= (deltax
- deltay
) * 2;
522 numpixels
++; /* include endpoints */
539 for (i
= 0; i
< numpixels
; i
++)
541 if ( ((unsigned)x
< (unsigned)current_vp
->width
)
542 && ((unsigned)y
< (unsigned)current_vp
->height
)
543 #if defined(HAVE_VIEWPORT_CLIP)
544 && ((unsigned)x
< (unsigned)LCDM(WIDTH
))
545 && ((unsigned)y
< (unsigned)LCDM(HEIGHT
))
548 pfunc(current_vp
->x
+ x
, current_vp
->y
+ y
);
565 /* Draw a horizontal line (optimised) */
566 void LCDFN(hline
)(int x1
, int x2
, int y
)
570 FBFN(data
) *dst
, *dst_end
;
572 LCDFN(blockfunc_type
) *bfunc
;
582 /******************** In viewport clipping **********************/
583 /* nothing to draw? */
584 if (((unsigned)y
>= (unsigned)current_vp
->height
) || (x1
>= current_vp
->width
)
590 if (x2
>= current_vp
->width
)
591 x2
= current_vp
->width
-1;
593 /* adjust x1 and y to viewport */
598 #if defined(HAVE_VIEWPORT_CLIP)
599 /********************* Viewport on screen clipping ********************/
600 /* nothing to draw? */
601 if (((unsigned)y
>= (unsigned) LCDM(HEIGHT
)) || (x1
>= LCDM(WIDTH
))
608 if (x2
>= LCDM(WIDTH
))
614 bfunc
= LCDFN(blockfuncs
)[current_vp
->drawmode
];
615 dst
= &LCDFN(framebuffer
)[y
>>3][x1
];
616 mask
= 0x0101 << (y
& 7);
618 dst_end
= dst
+ width
;
620 bfunc(dst
++, mask
, 0xFFFFu
);
621 while (dst
< dst_end
);
624 /* Draw a vertical line (optimised) */
625 void LCDFN(vline
)(int x
, int y1
, int y2
)
629 unsigned mask
, mask_bottom
;
630 LCDFN(blockfunc_type
) *bfunc
;
640 /******************** In viewport clipping **********************/
641 /* nothing to draw? */
642 if (((unsigned)x
>= (unsigned)current_vp
->width
) || (y1
>= current_vp
->height
)
648 if (y2
>= current_vp
->height
)
649 y2
= current_vp
->height
-1;
651 /* adjust for viewport */
656 #if defined(HAVE_VIEWPORT_CLIP)
657 /********************* Viewport on screen clipping ********************/
658 /* nothing to draw? */
659 if (( (unsigned) x
>= (unsigned)LCDM(WIDTH
)) || (y1
>= LCDM(HEIGHT
))
666 if (y2
>= LCDM(HEIGHT
))
670 bfunc
= LCDFN(blockfuncs
)[current_vp
->drawmode
];
671 dst
= &LCDFN(framebuffer
)[y1
>>3][x
];
673 mask
= (0xFFu
<< (y1
& 7)) & 0xFFu
;
675 mask_bottom
= 0xFFu
>> (~ny
& 7);
676 mask_bottom
|= mask_bottom
<< 8;
678 for (; ny
>= 8; ny
-= 8)
680 bfunc(dst
, mask
, 0xFFFFu
);
685 bfunc(dst
, mask
, 0xFFFFu
);
688 /* Draw a rectangular box */
689 void LCDFN(drawrect
)(int x
, int y
, int width
, int height
)
691 if ((width
<= 0) || (height
<= 0))
694 int x2
= x
+ width
- 1;
695 int y2
= y
+ height
- 1;
697 LCDFN(vline
)(x
, y
, y2
);
698 LCDFN(vline
)(x2
, y
, y2
);
699 LCDFN(hline
)(x
, x2
, y
);
700 LCDFN(hline
)(x
, x2
, y2
);
703 /* Fill a rectangular area */
704 void LCDFN(fillrect
)(int x
, int y
, int width
, int height
)
707 FBFN(data
) *dst
, *dst_end
;
708 unsigned mask
, mask_bottom
;
710 LCDFN(blockfunc_type
) *bfunc
;
711 bool fillopt
= false;
713 /******************** In viewport clipping **********************/
714 /* nothing to draw? */
715 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
)
716 || (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
729 if (x
+ width
> current_vp
->width
)
730 width
= current_vp
->width
- x
;
731 if (y
+ height
> current_vp
->height
)
732 height
= current_vp
->height
- y
;
734 /* adjust for viewport */
738 #if defined(HAVE_VIEWPORT_CLIP)
739 /********************* Viewport on screen clipping ********************/
740 /* nothing to draw? */
741 if ((x
>= LCDM(WIDTH
)) || (y
>= LCDM(HEIGHT
))
742 || (x
+ width
<= 0) || (y
+ height
<= 0))
745 /* clip image in viewport in screen */
756 if (x
+ width
> LCDM(WIDTH
))
757 width
= LCDM(WIDTH
) - x
;
758 if (y
+ height
> LCDM(HEIGHT
))
759 height
= LCDM(HEIGHT
) - y
;
763 if (current_vp
->drawmode
& DRMODE_INVERSEVID
)
765 if ((current_vp
->drawmode
& DRMODE_BG
) && !backdrop
)
773 if (current_vp
->drawmode
& DRMODE_FG
)
779 bfunc
= LCDFN(blockfuncs
)[current_vp
->drawmode
];
780 dst
= &LCDFN(framebuffer
)[y
>>3][x
];
781 ny
= height
- 1 + (y
& 7);
782 mask
= (0xFFu
<< (y
& 7)) & 0xFFu
;
784 mask_bottom
= 0xFFu
>> (~ny
& 7);
785 mask_bottom
|= mask_bottom
<< 8;
787 for (; ny
>= 8; ny
-= 8)
789 if (fillopt
&& (mask
== 0xFFFFu
))
790 memset16(dst
, bits
, width
);
793 FBFN(data
) *dst_row
= dst
;
795 dst_end
= dst_row
+ width
;
797 bfunc(dst_row
++, mask
, 0xFFFFu
);
798 while (dst_row
< dst_end
);
806 if (fillopt
&& (mask
== 0xFFFFu
))
807 memset16(dst
, bits
, width
);
810 dst_end
= dst
+ width
;
812 bfunc(dst
++, mask
, 0xFFFFu
);
813 while (dst
< dst_end
);
817 /* About Rockbox' internal monochrome bitmap format:
819 * A bitmap contains one bit for every pixel that defines if that pixel is
820 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
822 * The bytes are stored in row-major order, with byte 0 being top left,
823 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
824 * 0..7, the second row defines pixel row 8..15 etc.
826 * This is similar to the internal lcd hw format. */
828 /* Draw a partial monochrome bitmap */
829 void ICODE_ATTR
LCDFN(mono_bitmap_part
)(const unsigned char *src
, int src_x
,
830 int src_y
, int stride
, int x
, int y
,
831 int width
, int height
)
834 FBFN(data
) *dst
, *dst_end
;
835 unsigned data
, mask
, mask_bottom
;
836 LCDFN(blockfunc_type
) *bfunc
;
838 /******************** Image in viewport clipping **********************/
839 /* nothing to draw? */
840 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
) ||
841 (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
856 if (x
+ width
> current_vp
->width
)
857 width
= current_vp
->width
- x
;
858 if (y
+ height
> current_vp
->height
)
859 height
= current_vp
->height
- y
;
861 /* adjust for viewport */
865 #if defined(HAVE_VIEWPORT_CLIP)
866 /********************* Viewport on screen clipping ********************/
867 /* nothing to draw? */
868 if ((x
>= LCDM(WIDTH
)) || (y
>= LCDM(HEIGHT
))
869 || (x
+ width
<= 0) || (y
+ height
<= 0))
872 /* clip image in viewport in screen */
885 if (x
+ width
> LCDM(WIDTH
))
886 width
= LCDM(WIDTH
) - x
;
887 if (y
+ height
> LCDM(HEIGHT
))
888 height
= LCDM(HEIGHT
) - y
;
891 src
+= stride
* (src_y
>> 3) + src_x
; /* move starting point */
894 dst
= &LCDFN(framebuffer
)[y
>>3][x
];
896 ny
= height
- 1 + shift
+ src_y
;
898 bfunc
= LCDFN(blockfuncs
)[current_vp
->drawmode
];
899 mask
= 0xFFu
<< (shift
+ src_y
);
900 /* not byte-doubled here because shift+src_y can be > 7 */
901 mask_bottom
= 0xFFu
>> (~ny
& 7);
902 mask_bottom
|= mask_bottom
<< 8;
909 for (; ny
>= 8; ny
-= 8)
911 const unsigned char *src_row
= src
;
912 FBFN(data
) *dst_row
= dst
;
914 dst_end
= dst_row
+ width
;
918 bfunc(dst_row
++, mask
, data
| (data
<< 8));
920 while (dst_row
< dst_end
);
928 dst_end
= dst
+ width
;
932 bfunc(dst
++, mask
, data
| (data
<< 8));
934 while (dst
< dst_end
);
940 dst_end
= dst
+ width
;
943 const unsigned char *src_col
= src
++;
944 FBFN(data
) *dst_col
= dst
++;
945 unsigned mask_col
= mask
& 0xFFu
;
947 mask_col
|= mask_col
<< 8;
950 for (y
= ny
; y
>= 8; y
-= 8)
952 data
|= *src_col
<< shift
;
956 ddata
= data
& 0xFFu
;
957 bfunc(dst_col
, mask_col
, ddata
| (ddata
<< 8));
962 mask_col
= (mask
>> 8) & 0xFFu
;
963 mask_col
|= mask_col
<< 8;
967 dst_col
+= LCDM(WIDTH
);
970 data
|= *src_col
<< shift
;
971 mask_col
&= mask_bottom
;
972 ddata
= data
& 0xFFu
;
973 bfunc(dst_col
, mask_col
, ddata
| (ddata
<< 8));
975 while (dst
< dst_end
);
979 /* Draw a full monochrome bitmap */
980 void LCDFN(mono_bitmap
)(const unsigned char *src
, int x
, int y
, int width
,
983 LCDFN(mono_bitmap_part
)(src
, 0, 0, width
, x
, y
, width
, height
);
986 /* About Rockbox' internal native bitmap format:
988 * A bitmap contains one bit in each byte of a pair of bytes for every pixel.
989 * 00 = white, 01 = light grey, 10 = dark grey, 11 = black. Bits within a byte
990 * are arranged vertically, LSB at top.
991 * The pairs of bytes are stored as shorts, in row-major order, with word 0
992 * being top left, word 1 2nd from left etc. The first row of words defines
993 * pixel rows 0..7, the second row defines pixel row 8..15 etc.
995 * This is the same as the internal lcd hw format. */
997 /* Draw a partial native bitmap */
998 void ICODE_ATTR
LCDFN(bitmap_part
)(const FBFN(data
) *src
, int src_x
,
999 int src_y
, int stride
, int x
, int y
,
1000 int width
, int height
)
1003 FBFN(data
) *dst
, *dst_end
;
1004 unsigned mask
, mask_bottom
;
1006 /******************** Image in viewport clipping **********************/
1007 /* nothing to draw? */
1008 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
)
1009 || (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
1024 if (x
+ width
> current_vp
->width
)
1025 width
= current_vp
->width
- x
;
1026 if (y
+ height
> current_vp
->height
)
1027 height
= current_vp
->height
- y
;
1029 /* adjust for viewport */
1033 #if defined(HAVE_VIEWPORT_CLIP)
1034 /********************* Viewport on screen clipping ********************/
1035 /* nothing to draw? */
1036 if ((x
>= LCDM(WIDTH
)) || (y
>= LCDM(HEIGHT
))
1037 || (x
+ width
<= 0) || (y
+ height
<= 0))
1040 /* clip image in viewport in screen */
1053 if (x
+ width
> LCDM(WIDTH
))
1054 width
= LCDM(WIDTH
) - x
;
1055 if (y
+ height
> LCDM(HEIGHT
))
1056 height
= LCDM(HEIGHT
) - y
;
1059 src
+= stride
* (src_y
>> 3) + src_x
; /* move starting point */
1062 dst
= &LCDFN(framebuffer
)[y
>>3][x
];
1064 ny
= height
- 1 + shift
+ src_y
;
1066 mask
= 0xFFu
<< (shift
+ src_y
);
1067 /* not byte-doubled here because shift+src_y can be > 7 */
1068 mask_bottom
= 0xFFu
>> (~ny
& 7);
1069 mask_bottom
|= mask_bottom
<< 8;
1076 for (; ny
>= 8; ny
-= 8)
1078 if (mask
== 0xFFFFu
)
1079 memcpy(dst
, src
, width
* sizeof(FBFN(data
)));
1082 const FBFN(data
) *src_row
= src
;
1083 FBFN(data
) *dst_row
= dst
;
1085 dst_end
= dst_row
+ width
;
1087 setblock(dst_row
++, mask
, *src_row
++);
1088 while (dst_row
< dst_end
);
1094 mask
&= mask_bottom
;
1096 if (mask
== 0xFFFFu
)
1097 memcpy(dst
, src
, width
* sizeof(FBFN(data
)));
1100 dst_end
= dst
+ width
;
1102 setblock(dst
++, mask
, *src
++);
1103 while (dst
< dst_end
);
1108 unsigned datamask
= (0xFFu
<< shift
) & 0xFFu
;
1110 datamask
|= datamask
<< 8;
1112 dst_end
= dst
+ width
;
1115 const FBFN(data
) *src_col
= src
++;
1116 FBFN(data
) *dst_col
= dst
++;
1117 unsigned mask_col
= mask
& 0xFFu
;
1118 unsigned data
, olddata
= 0;
1120 mask_col
|= mask_col
<< 8;
1122 for (y
= ny
; y
>= 8; y
-= 8)
1124 data
= *src_col
<< shift
;
1128 setblock(dst_col
, mask_col
,
1129 olddata
^((olddata
^ data
) & datamask
));
1134 mask_col
= (mask
>> 8) & 0xFFu
;
1135 mask_col
|= mask_col
<< 8;
1138 dst_col
+= LCDM(WIDTH
);
1139 olddata
= data
>> 8;
1141 data
= *src_col
<< shift
;
1142 setblock(dst_col
, mask_col
& mask_bottom
,
1143 olddata
^((olddata
^ data
) & datamask
));
1145 while (dst
< dst_end
);
1149 /* Draw a full native bitmap */
1150 void LCDFN(bitmap
)(const FBFN(data
) *src
, int x
, int y
, int width
, int height
)
1152 LCDFN(bitmap_part
)(src
, 0, 0, width
, x
, y
, width
, height
);
1155 #include "lcd-bitmap-common.c"