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 ****************************************************************************/
30 #include "string-extra.h" /* mem*() */
35 #include "rbunicode.h"
37 #include "scroll_engine.h"
39 #ifndef LCDFN /* Not compiling for remote - define macros for main LCD. */
40 #define LCDFN(fn) lcd_ ## fn
41 #define FBFN(fn) fb_ ## fn
42 #define LCDM(ma) LCD_ ## ma
43 #define FBSIZE FRAMEBUFFER_SIZE
44 #define LCDNAME "lcd_"
45 #define LCDFB(x,y) FBADDR(x, y)
51 FBFN(data
) LCDFN(static_framebuffer
)[LCDM(FBHEIGHT
)][LCDM(FBWIDTH
)] IRAM_LCDFRAMEBUFFER
;
52 FBFN(data
) *LCDFN(framebuffer
) = &LCDFN(static_framebuffer
)[0][0];
55 static const FBFN(data
) patterns
[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
57 static FBFN(data
) *backdrop
= NULL
;
58 static long backdrop_offset IDATA_ATTR
= 0;
60 static struct viewport default_vp
=
65 .height
= LCDM(HEIGHT
),
66 .font
= FONT_SYSFIXED
,
67 .drawmode
= DRMODE_SOLID
,
68 .fg_pattern
= LCDM(DEFAULT_FG
),
69 .bg_pattern
= LCDM(DEFAULT_BG
)
72 static struct viewport
* current_vp IBSS_ATTR
;
74 static unsigned fg_pattern IBSS_ATTR
;
75 static unsigned bg_pattern IBSS_ATTR
;
79 void LCDFN(set_viewport
)(struct viewport
* vp
)
82 current_vp
= &default_vp
;
86 fg_pattern
= patterns
[current_vp
->fg_pattern
& 3];
87 bg_pattern
= patterns
[current_vp
->bg_pattern
& 3];
89 #if defined(SIMULATOR)
90 /* Force the viewport to be within bounds. If this happens it should
91 * be considered an error - the viewport will not draw as it might be
94 if((unsigned) current_vp
->x
> (unsigned) LCDM(WIDTH
)
95 || (unsigned) current_vp
->y
> (unsigned) LCDM(HEIGHT
)
96 || current_vp
->x
+ current_vp
->width
> LCDM(WIDTH
)
97 || current_vp
->y
+ current_vp
->height
> LCDM(HEIGHT
))
99 #if !defined(HAVE_VIEWPORT_CLIP)
104 "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n",
105 current_vp
->x
, current_vp
->y
,
106 current_vp
->width
, current_vp
->height
);
112 void LCDFN(update_viewport
)(void)
114 LCDFN(update_rect
)(current_vp
->x
, current_vp
->y
,
115 current_vp
->width
, current_vp
->height
);
118 void LCDFN(update_viewport_rect
)(int x
, int y
, int width
, int height
)
120 LCDFN(update_rect
)(current_vp
->x
+ x
, current_vp
->y
+ y
, width
, height
);
124 void LCDFN(init
)(void)
126 LCDFN(set_viewport
)(NULL
);
127 LCDFN(clear_display
)();
128 LCDFN(init_device
)();
134 /*** parameter handling ***/
136 #if !defined(MAIN_LCD) && defined(HAVE_LCD_COLOR)
137 /* When compiling for remote LCD and the main LCD is colour. */
138 unsigned lcd_remote_color_to_native(unsigned color
)
140 unsigned r
= (color
& 0xf800) >> 10;
141 unsigned g
= (color
& 0x07e0) >> 5;
142 unsigned b
= (color
& 0x001f) << 2;
145 * |Y'| = |0.299000 0.587000 0.114000| |G|
148 return (5*r
+ 9*g
+ b
) >> 8;
152 void LCDFN(set_drawmode
)(int mode
)
154 current_vp
->drawmode
= mode
& (DRMODE_SOLID
|DRMODE_INVERSEVID
);
157 int LCDFN(get_drawmode
)(void)
159 return current_vp
->drawmode
;
162 void LCDFN(set_foreground
)(unsigned brightness
)
164 current_vp
->fg_pattern
= brightness
;
165 fg_pattern
= patterns
[brightness
& 3];
168 unsigned LCDFN(get_foreground
)(void)
170 return current_vp
->fg_pattern
;
173 void LCDFN(set_background
)(unsigned brightness
)
175 current_vp
->bg_pattern
= brightness
;
176 bg_pattern
= patterns
[brightness
& 3];
179 unsigned LCDFN(get_background
)(void)
181 return current_vp
->bg_pattern
;
184 void LCDFN(set_drawinfo
)(int mode
, unsigned fg_brightness
,
185 unsigned bg_brightness
)
187 LCDFN(set_drawmode
)(mode
);
188 LCDFN(set_foreground
)(fg_brightness
);
189 LCDFN(set_background
)(bg_brightness
);
192 int LCDFN(getwidth
)(void)
194 return current_vp
->width
;
197 int LCDFN(getheight
)(void)
199 return current_vp
->height
;
201 void LCDFN(setfont
)(int newfont
)
203 current_vp
->font
= newfont
;
206 int LCDFN(getfont
)(void)
208 return current_vp
->font
;
211 int LCDFN(getstringsize
)(const unsigned char *str
, int *w
, int *h
)
213 return font_getstringsize(str
, w
, h
, current_vp
->font
);
216 /*** low-level drawing functions ***/
218 static void setpixel(int x
, int y
)
220 unsigned mask
= 0x0101 << (y
& 7);
221 FBFN(data
) *address
= LCDFB(x
,y
>>3);
222 unsigned data
= *address
;
224 *address
= data
^ ((data
^ fg_pattern
) & mask
);
227 static void clearpixel(int x
, int y
)
229 unsigned mask
= 0x0101 << (y
& 7);
230 FBFN(data
) *address
= LCDFB(x
,y
>>3);
231 unsigned data
= *address
;
233 *address
= data
^ ((data
^ bg_pattern
) & mask
);
236 static void clearimgpixel(int x
, int y
)
238 unsigned mask
= 0x0101 << (y
& 7);
239 FBFN(data
) *address
= LCDFB(x
,y
>>3);
240 unsigned data
= *address
;
242 *address
= data
^ ((data
^ *(FBFN(data
) *)((long)address
243 + backdrop_offset
)) & mask
);
246 static void flippixel(int x
, int y
)
248 unsigned mask
= 0x0101 << (y
& 7);
249 FBFN(data
) *address
= LCDFB(x
,y
>>3);
254 static void nopixel(int x
, int y
)
260 LCDFN(pixelfunc_type
)* const LCDFN(pixelfuncs_bgcolor
)[8] = {
261 flippixel
, nopixel
, setpixel
, setpixel
,
262 nopixel
, clearpixel
, nopixel
, clearpixel
265 LCDFN(pixelfunc_type
)* const LCDFN(pixelfuncs_backdrop
)[8] = {
266 flippixel
, nopixel
, setpixel
, setpixel
,
267 nopixel
, clearimgpixel
, nopixel
, clearimgpixel
270 LCDFN(pixelfunc_type
)* const *LCDFN(pixelfuncs
) = LCDFN(pixelfuncs_bgcolor
);
272 /* 'mask' and 'bits' contain 2 bits per pixel */
273 static void ICODE_ATTR
flipblock(FBFN(data
) *address
, unsigned mask
,
276 *address
^= bits
& mask
;
279 static void ICODE_ATTR
bgblock(FBFN(data
) *address
, unsigned mask
,
282 unsigned data
= *address
;
284 *address
= data
^ ((data
^ bg_pattern
) & mask
& ~bits
);
287 static void ICODE_ATTR
bgimgblock(FBFN(data
) *address
, unsigned mask
,
290 unsigned data
= *address
;
292 *address
= data
^ ((data
^ *(FBFN(data
) *)((long)address
293 + backdrop_offset
)) & mask
& ~bits
);
296 static void ICODE_ATTR
fgblock(FBFN(data
) *address
, unsigned mask
,
299 unsigned data
= *address
;
301 *address
= data
^ ((data
^ fg_pattern
) & mask
& bits
);
304 static void ICODE_ATTR
solidblock(FBFN(data
) *address
, unsigned mask
,
307 unsigned data
= *address
;
308 unsigned bgp
= bg_pattern
;
310 bits
= bgp
^ ((bgp
^ fg_pattern
) & bits
);
311 *address
= data
^ ((data
^ bits
) & mask
);
314 static void ICODE_ATTR
solidimgblock(FBFN(data
) *address
, unsigned mask
,
317 unsigned data
= *address
;
318 unsigned bgp
= *(FBFN(data
) *)((long)address
+ backdrop_offset
);
320 bits
= bgp
^ ((bgp
^ fg_pattern
) & bits
);
321 *address
= data
^ ((data
^ bits
) & mask
);
324 static void ICODE_ATTR
flipinvblock(FBFN(data
) *address
, unsigned mask
,
327 *address
^= ~bits
& mask
;
330 static void ICODE_ATTR
bginvblock(FBFN(data
) *address
, unsigned mask
,
333 unsigned data
= *address
;
335 *address
= data
^ ((data
^ bg_pattern
) & mask
& bits
);
338 static void ICODE_ATTR
bgimginvblock(FBFN(data
) *address
, unsigned mask
,
341 unsigned data
= *address
;
343 *address
= data
^ ((data
^ *(FBFN(data
) *)((long)address
344 + backdrop_offset
)) & mask
& bits
);
347 static void ICODE_ATTR
fginvblock(FBFN(data
) *address
, unsigned mask
,
350 unsigned data
= *address
;
352 *address
= data
^ ((data
^ fg_pattern
) & mask
& ~bits
);
355 static void ICODE_ATTR
solidinvblock(FBFN(data
) *address
, unsigned mask
,
358 unsigned data
= *address
;
359 unsigned fgp
= fg_pattern
;
361 bits
= fgp
^ ((fgp
^ bg_pattern
) & bits
);
362 *address
= data
^ ((data
^ bits
) & mask
);
365 static void ICODE_ATTR
solidimginvblock(FBFN(data
) *address
, unsigned mask
,
368 unsigned data
= *address
;
369 unsigned fgp
= fg_pattern
;
371 bits
= fgp
^ ((fgp
^ *(FBFN(data
) *)((long)address
372 + backdrop_offset
)) & bits
);
373 *address
= data
^ ((data
^ bits
) & mask
);
376 LCDFN(blockfunc_type
)* const LCDFN(blockfuncs_bgcolor
)[8] = {
377 flipblock
, bgblock
, fgblock
, solidblock
,
378 flipinvblock
, bginvblock
, fginvblock
, solidinvblock
381 LCDFN(blockfunc_type
)* const LCDFN(blockfuncs_backdrop
)[8] = {
382 flipblock
, bgimgblock
, fgblock
, solidimgblock
,
383 flipinvblock
, bgimginvblock
, fginvblock
, solidimginvblock
386 LCDFN(blockfunc_type
)* const *LCDFN(blockfuncs
) = LCDFN(blockfuncs_bgcolor
);
389 void LCDFN(set_backdrop
)(FBFN(data
) *bd
)
394 backdrop_offset
= (long)bd
- (long)LCDFN(framebuffer
);
395 LCDFN(pixelfuncs
) = LCDFN(pixelfuncs_backdrop
);
396 LCDFN(blockfuncs
) = LCDFN(blockfuncs_backdrop
);
401 LCDFN(pixelfuncs
) = LCDFN(pixelfuncs_bgcolor
);
402 LCDFN(blockfuncs
) = LCDFN(blockfuncs_bgcolor
);
406 FBFN(data
)* LCDFN(get_backdrop
)(void)
411 static inline void setblock(FBFN(data
) *address
, unsigned mask
, unsigned bits
)
413 unsigned data
= *address
;
416 *address
= data
^ (bits
& mask
);
419 /*** drawing functions ***/
421 /* Clear the whole display */
422 void LCDFN(clear_display
)(void)
424 if (default_vp
.drawmode
& DRMODE_INVERSEVID
)
426 memset(LCDFN(framebuffer
), patterns
[default_vp
.fg_pattern
& 3],
432 memcpy(LCDFN(framebuffer
), backdrop
, FBSIZE
);
434 memset(LCDFN(framebuffer
), patterns
[default_vp
.bg_pattern
& 3],
438 LCDFN(scroll_info
).lines
= 0;
441 /* Clear the current viewport */
442 void LCDFN(clear_viewport
)(void)
446 if (current_vp
== &default_vp
)
448 LCDFN(clear_display
)();
452 lastmode
= current_vp
->drawmode
;
454 /* Invert the INVERSEVID bit and set basic mode to SOLID */
455 current_vp
->drawmode
= (~lastmode
& DRMODE_INVERSEVID
) |
458 LCDFN(fillrect
)(0, 0, current_vp
->width
, current_vp
->height
);
460 current_vp
->drawmode
= lastmode
;
462 LCDFN(scroll_stop
)(current_vp
);
466 /* Set a single pixel */
467 void LCDFN(drawpixel
)(int x
, int y
)
469 if ( ((unsigned)x
< (unsigned)current_vp
->width
)
470 && ((unsigned)y
< (unsigned)current_vp
->height
)
471 #if defined(HAVE_VIEWPORT_CLIP)
472 && ((unsigned)x
< (unsigned)LCDM(WIDTH
))
473 && ((unsigned)y
< (unsigned)LCDM(HEIGHT
))
476 LCDFN(pixelfuncs
)[current_vp
->drawmode
](current_vp
->x
+x
, current_vp
->y
+y
);
480 void LCDFN(drawline
)(int x1
, int y1
, int x2
, int y2
)
488 LCDFN(pixelfunc_type
) *pfunc
= LCDFN(pixelfuncs
)[current_vp
->drawmode
];
490 deltax
= abs(x2
- x1
);
493 /* DEBUGF(LCDNAME "drawline() called for vertical line - optimisation.\n"); */
494 LCDFN(vline
)(x1
, y1
, y2
);
497 deltay
= abs(y2
- y1
);
500 /* DEBUGF(LCDNAME "drawline() called for horizontal line - optimisation.\n"); */
501 LCDFN(hline
)(x1
, x2
, y1
);
507 if (deltax
>= deltay
)
510 d
= 2 * deltay
- deltax
;
512 dinc2
= (deltay
- deltax
) * 2;
519 d
= 2 * deltax
- deltay
;
521 dinc2
= (deltax
- deltay
) * 2;
525 numpixels
++; /* include endpoints */
542 for (i
= 0; i
< numpixels
; i
++)
544 if ( ((unsigned)x
< (unsigned)current_vp
->width
)
545 && ((unsigned)y
< (unsigned)current_vp
->height
)
546 #if defined(HAVE_VIEWPORT_CLIP)
547 && ((unsigned)x
< (unsigned)LCDM(WIDTH
))
548 && ((unsigned)y
< (unsigned)LCDM(HEIGHT
))
551 pfunc(current_vp
->x
+ x
, current_vp
->y
+ y
);
568 /* Draw a horizontal line (optimised) */
569 void LCDFN(hline
)(int x1
, int x2
, int y
)
573 FBFN(data
) *dst
, *dst_end
;
575 LCDFN(blockfunc_type
) *bfunc
;
585 /******************** In viewport clipping **********************/
586 /* nothing to draw? */
587 if (((unsigned)y
>= (unsigned)current_vp
->height
) || (x1
>= current_vp
->width
)
593 if (x2
>= current_vp
->width
)
594 x2
= current_vp
->width
-1;
596 /* adjust x1 and y to viewport */
601 #if defined(HAVE_VIEWPORT_CLIP)
602 /********************* Viewport on screen clipping ********************/
603 /* nothing to draw? */
604 if (((unsigned)y
>= (unsigned) LCDM(HEIGHT
)) || (x1
>= LCDM(WIDTH
))
611 if (x2
>= LCDM(WIDTH
))
617 bfunc
= LCDFN(blockfuncs
)[current_vp
->drawmode
];
618 dst
= LCDFB(x1
,y
>>3);
619 mask
= 0x0101 << (y
& 7);
621 dst_end
= dst
+ width
;
623 bfunc(dst
++, mask
, 0xFFFFu
);
624 while (dst
< dst_end
);
627 /* Draw a vertical line (optimised) */
628 void LCDFN(vline
)(int x
, int y1
, int y2
)
632 unsigned mask
, mask_bottom
;
633 LCDFN(blockfunc_type
) *bfunc
;
643 /******************** In viewport clipping **********************/
644 /* nothing to draw? */
645 if (((unsigned)x
>= (unsigned)current_vp
->width
) || (y1
>= current_vp
->height
)
651 if (y2
>= current_vp
->height
)
652 y2
= current_vp
->height
-1;
654 /* adjust for viewport */
659 #if defined(HAVE_VIEWPORT_CLIP)
660 /********************* Viewport on screen clipping ********************/
661 /* nothing to draw? */
662 if (( (unsigned) x
>= (unsigned)LCDM(WIDTH
)) || (y1
>= LCDM(HEIGHT
))
669 if (y2
>= LCDM(HEIGHT
))
673 bfunc
= LCDFN(blockfuncs
)[current_vp
->drawmode
];
674 dst
= LCDFB(x
,y1
>>3);
676 mask
= (0xFFu
<< (y1
& 7)) & 0xFFu
;
678 mask_bottom
= 0xFFu
>> (~ny
& 7);
679 mask_bottom
|= mask_bottom
<< 8;
681 for (; ny
>= 8; ny
-= 8)
683 bfunc(dst
, mask
, 0xFFFFu
);
688 bfunc(dst
, mask
, 0xFFFFu
);
691 /* Draw a rectangular box */
692 void LCDFN(drawrect
)(int x
, int y
, int width
, int height
)
694 if ((width
<= 0) || (height
<= 0))
697 int x2
= x
+ width
- 1;
698 int y2
= y
+ height
- 1;
700 LCDFN(vline
)(x
, y
, y2
);
701 LCDFN(vline
)(x2
, y
, y2
);
702 LCDFN(hline
)(x
, x2
, y
);
703 LCDFN(hline
)(x
, x2
, y2
);
706 /* Fill a rectangular area */
707 void LCDFN(fillrect
)(int x
, int y
, int width
, int height
)
710 FBFN(data
) *dst
, *dst_end
;
711 unsigned mask
, mask_bottom
;
713 LCDFN(blockfunc_type
) *bfunc
;
714 bool fillopt
= false;
716 /******************** In viewport clipping **********************/
717 /* nothing to draw? */
718 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
)
719 || (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
732 if (x
+ width
> current_vp
->width
)
733 width
= current_vp
->width
- x
;
734 if (y
+ height
> current_vp
->height
)
735 height
= current_vp
->height
- y
;
737 /* adjust for viewport */
741 #if defined(HAVE_VIEWPORT_CLIP)
742 /********************* Viewport on screen clipping ********************/
743 /* nothing to draw? */
744 if ((x
>= LCDM(WIDTH
)) || (y
>= LCDM(HEIGHT
))
745 || (x
+ width
<= 0) || (y
+ height
<= 0))
748 /* clip image in viewport in screen */
759 if (x
+ width
> LCDM(WIDTH
))
760 width
= LCDM(WIDTH
) - x
;
761 if (y
+ height
> LCDM(HEIGHT
))
762 height
= LCDM(HEIGHT
) - y
;
766 if (current_vp
->drawmode
& DRMODE_INVERSEVID
)
768 if ((current_vp
->drawmode
& DRMODE_BG
) && !backdrop
)
776 if (current_vp
->drawmode
& DRMODE_FG
)
782 bfunc
= LCDFN(blockfuncs
)[current_vp
->drawmode
];
784 ny
= height
- 1 + (y
& 7);
785 mask
= (0xFFu
<< (y
& 7)) & 0xFFu
;
787 mask_bottom
= 0xFFu
>> (~ny
& 7);
788 mask_bottom
|= mask_bottom
<< 8;
790 for (; ny
>= 8; ny
-= 8)
792 if (fillopt
&& (mask
== 0xFFFFu
))
793 memset16(dst
, bits
, width
);
796 FBFN(data
) *dst_row
= dst
;
798 dst_end
= dst_row
+ width
;
800 bfunc(dst_row
++, mask
, 0xFFFFu
);
801 while (dst_row
< dst_end
);
809 if (fillopt
&& (mask
== 0xFFFFu
))
810 memset16(dst
, bits
, width
);
813 dst_end
= dst
+ width
;
815 bfunc(dst
++, mask
, 0xFFFFu
);
816 while (dst
< dst_end
);
820 /* About Rockbox' internal monochrome bitmap format:
822 * A bitmap contains one bit for every pixel that defines if that pixel is
823 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
825 * The bytes are stored in row-major order, with byte 0 being top left,
826 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
827 * 0..7, the second row defines pixel row 8..15 etc.
829 * This is similar to the internal lcd hw format. */
831 /* Draw a partial monochrome bitmap */
832 void ICODE_ATTR
LCDFN(mono_bitmap_part
)(const unsigned char *src
, int src_x
,
833 int src_y
, int stride
, int x
, int y
,
834 int width
, int height
)
837 FBFN(data
) *dst
, *dst_end
;
838 unsigned data
, mask
, mask_bottom
;
839 LCDFN(blockfunc_type
) *bfunc
;
841 /******************** Image in viewport clipping **********************/
842 /* nothing to draw? */
843 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
) ||
844 (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
859 if (x
+ width
> current_vp
->width
)
860 width
= current_vp
->width
- x
;
861 if (y
+ height
> current_vp
->height
)
862 height
= current_vp
->height
- y
;
864 /* adjust for viewport */
868 #if defined(HAVE_VIEWPORT_CLIP)
869 /********************* Viewport on screen clipping ********************/
870 /* nothing to draw? */
871 if ((x
>= LCDM(WIDTH
)) || (y
>= LCDM(HEIGHT
))
872 || (x
+ width
<= 0) || (y
+ height
<= 0))
875 /* clip image in viewport in screen */
888 if (x
+ width
> LCDM(WIDTH
))
889 width
= LCDM(WIDTH
) - x
;
890 if (y
+ height
> LCDM(HEIGHT
))
891 height
= LCDM(HEIGHT
) - y
;
894 src
+= stride
* (src_y
>> 3) + src_x
; /* move starting point */
899 ny
= height
- 1 + shift
+ src_y
;
901 bfunc
= LCDFN(blockfuncs
)[current_vp
->drawmode
];
902 mask
= 0xFFu
<< (shift
+ src_y
);
903 /* not byte-doubled here because shift+src_y can be > 7 */
904 mask_bottom
= 0xFFu
>> (~ny
& 7);
905 mask_bottom
|= mask_bottom
<< 8;
912 for (; ny
>= 8; ny
-= 8)
914 const unsigned char *src_row
= src
;
915 FBFN(data
) *dst_row
= dst
;
917 dst_end
= dst_row
+ width
;
921 bfunc(dst_row
++, mask
, data
| (data
<< 8));
923 while (dst_row
< dst_end
);
931 dst_end
= dst
+ width
;
935 bfunc(dst
++, mask
, data
| (data
<< 8));
937 while (dst
< dst_end
);
943 dst_end
= dst
+ width
;
946 const unsigned char *src_col
= src
++;
947 FBFN(data
) *dst_col
= dst
++;
948 unsigned mask_col
= mask
& 0xFFu
;
950 mask_col
|= mask_col
<< 8;
953 for (y
= ny
; y
>= 8; y
-= 8)
955 data
|= *src_col
<< shift
;
959 ddata
= data
& 0xFFu
;
960 bfunc(dst_col
, mask_col
, ddata
| (ddata
<< 8));
965 mask_col
= (mask
>> 8) & 0xFFu
;
966 mask_col
|= mask_col
<< 8;
970 dst_col
+= LCDM(WIDTH
);
973 data
|= *src_col
<< shift
;
974 mask_col
&= mask_bottom
;
975 ddata
= data
& 0xFFu
;
976 bfunc(dst_col
, mask_col
, ddata
| (ddata
<< 8));
978 while (dst
< dst_end
);
982 /* Draw a full monochrome bitmap */
983 void LCDFN(mono_bitmap
)(const unsigned char *src
, int x
, int y
, int width
,
986 LCDFN(mono_bitmap_part
)(src
, 0, 0, width
, x
, y
, width
, height
);
989 /* About Rockbox' internal native bitmap format:
991 * A bitmap contains one bit in each byte of a pair of bytes for every pixel.
992 * 00 = white, 01 = light grey, 10 = dark grey, 11 = black. Bits within a byte
993 * are arranged vertically, LSB at top.
994 * The pairs of bytes are stored as shorts, in row-major order, with word 0
995 * being top left, word 1 2nd from left etc. The first row of words defines
996 * pixel rows 0..7, the second row defines pixel row 8..15 etc.
998 * This is the same as the internal lcd hw format. */
1000 /* Draw a partial native bitmap */
1001 void ICODE_ATTR
LCDFN(bitmap_part
)(const FBFN(data
) *src
, int src_x
,
1002 int src_y
, int stride
, int x
, int y
,
1003 int width
, int height
)
1006 FBFN(data
) *dst
, *dst_end
;
1007 unsigned mask
, mask_bottom
;
1009 /******************** Image in viewport clipping **********************/
1010 /* nothing to draw? */
1011 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
)
1012 || (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
1027 if (x
+ width
> current_vp
->width
)
1028 width
= current_vp
->width
- x
;
1029 if (y
+ height
> current_vp
->height
)
1030 height
= current_vp
->height
- y
;
1032 /* adjust for viewport */
1036 #if defined(HAVE_VIEWPORT_CLIP)
1037 /********************* Viewport on screen clipping ********************/
1038 /* nothing to draw? */
1039 if ((x
>= LCDM(WIDTH
)) || (y
>= LCDM(HEIGHT
))
1040 || (x
+ width
<= 0) || (y
+ height
<= 0))
1043 /* clip image in viewport in screen */
1056 if (x
+ width
> LCDM(WIDTH
))
1057 width
= LCDM(WIDTH
) - x
;
1058 if (y
+ height
> LCDM(HEIGHT
))
1059 height
= LCDM(HEIGHT
) - y
;
1062 src
+= stride
* (src_y
>> 3) + src_x
; /* move starting point */
1065 dst
= LCDFB(x
,y
>>3);
1067 ny
= height
- 1 + shift
+ src_y
;
1069 mask
= 0xFFu
<< (shift
+ src_y
);
1070 /* not byte-doubled here because shift+src_y can be > 7 */
1071 mask_bottom
= 0xFFu
>> (~ny
& 7);
1072 mask_bottom
|= mask_bottom
<< 8;
1079 for (; ny
>= 8; ny
-= 8)
1081 if (mask
== 0xFFFFu
)
1082 memcpy(dst
, src
, width
* sizeof(FBFN(data
)));
1085 const FBFN(data
) *src_row
= src
;
1086 FBFN(data
) *dst_row
= dst
;
1088 dst_end
= dst_row
+ width
;
1090 setblock(dst_row
++, mask
, *src_row
++);
1091 while (dst_row
< dst_end
);
1097 mask
&= mask_bottom
;
1099 if (mask
== 0xFFFFu
)
1100 memcpy(dst
, src
, width
* sizeof(FBFN(data
)));
1103 dst_end
= dst
+ width
;
1105 setblock(dst
++, mask
, *src
++);
1106 while (dst
< dst_end
);
1111 unsigned datamask
= (0xFFu
<< shift
) & 0xFFu
;
1113 datamask
|= datamask
<< 8;
1115 dst_end
= dst
+ width
;
1118 const FBFN(data
) *src_col
= src
++;
1119 FBFN(data
) *dst_col
= dst
++;
1120 unsigned mask_col
= mask
& 0xFFu
;
1121 unsigned data
, olddata
= 0;
1123 mask_col
|= mask_col
<< 8;
1125 for (y
= ny
; y
>= 8; y
-= 8)
1127 data
= *src_col
<< shift
;
1131 setblock(dst_col
, mask_col
,
1132 olddata
^((olddata
^ data
) & datamask
));
1137 mask_col
= (mask
>> 8) & 0xFFu
;
1138 mask_col
|= mask_col
<< 8;
1141 dst_col
+= LCDM(WIDTH
);
1142 olddata
= data
>> 8;
1144 data
= *src_col
<< shift
;
1145 setblock(dst_col
, mask_col
& mask_bottom
,
1146 olddata
^((olddata
^ data
) & datamask
));
1148 while (dst
< dst_end
);
1152 /* Draw a full native bitmap */
1153 void LCDFN(bitmap
)(const FBFN(data
) *src
, int x
, int y
, int width
, int height
)
1155 LCDFN(bitmap_part
)(src
, 0, 0, width
, x
, y
, width
, height
);
1158 #include "lcd-bitmap-common.c"