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 LCDNAME "lcd_"
49 FBFN(data
) LCDFN(framebuffer
)[LCDM(FBHEIGHT
)][LCDM(FBWIDTH
)] IRAM_LCDFRAMEBUFFER
;
51 static const FBFN(data
) patterns
[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
53 static FBFN(data
) *backdrop
= NULL
;
54 static long backdrop_offset IDATA_ATTR
= 0;
56 static struct viewport default_vp
=
61 .height
= LCDM(HEIGHT
),
62 .font
= FONT_SYSFIXED
,
63 .drawmode
= DRMODE_SOLID
,
64 .fg_pattern
= LCDM(DEFAULT_FG
),
65 .bg_pattern
= LCDM(DEFAULT_BG
)
68 static struct viewport
* current_vp IBSS_ATTR
;
70 static unsigned fg_pattern IBSS_ATTR
;
71 static unsigned bg_pattern IBSS_ATTR
;
75 void LCDFN(set_viewport
)(struct viewport
* vp
)
78 current_vp
= &default_vp
;
82 fg_pattern
= patterns
[current_vp
->fg_pattern
& 3];
83 bg_pattern
= patterns
[current_vp
->bg_pattern
& 3];
85 #if defined(SIMULATOR)
86 /* Force the viewport to be within bounds. If this happens it should
87 * be considered an error - the viewport will not draw as it might be
90 if((unsigned) current_vp
->x
> (unsigned) LCDM(WIDTH
)
91 || (unsigned) current_vp
->y
> (unsigned) LCDM(HEIGHT
)
92 || current_vp
->x
+ current_vp
->width
> LCDM(WIDTH
)
93 || current_vp
->y
+ current_vp
->height
> LCDM(HEIGHT
))
95 #if !defined(HAVE_VIEWPORT_CLIP)
100 "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n",
101 current_vp
->x
, current_vp
->y
,
102 current_vp
->width
, current_vp
->height
);
108 void LCDFN(update_viewport
)(void)
110 LCDFN(update_rect
)(current_vp
->x
, current_vp
->y
,
111 current_vp
->width
, current_vp
->height
);
114 void LCDFN(update_viewport_rect
)(int x
, int y
, int width
, int height
)
116 LCDFN(update_rect
)(current_vp
->x
+ x
, current_vp
->y
+ y
, width
, height
);
120 void LCDFN(init
)(void)
122 LCDFN(set_viewport
)(NULL
);
123 LCDFN(clear_display
)();
124 LCDFN(init_device
)();
130 /*** parameter handling ***/
132 #if !defined(MAIN_LCD) && defined(HAVE_LCD_COLOR)
133 /* When compiling for remote LCD and the main LCD is colour. */
134 unsigned lcd_remote_color_to_native(unsigned color
)
136 unsigned r
= (color
& 0xf800) >> 10;
137 unsigned g
= (color
& 0x07e0) >> 5;
138 unsigned b
= (color
& 0x001f) << 2;
141 * |Y'| = |0.299000 0.587000 0.114000| |G|
144 return (5*r
+ 9*g
+ b
) >> 8;
148 void LCDFN(set_drawmode
)(int mode
)
150 current_vp
->drawmode
= mode
& (DRMODE_SOLID
|DRMODE_INVERSEVID
);
153 int LCDFN(get_drawmode
)(void)
155 return current_vp
->drawmode
;
158 void LCDFN(set_foreground
)(unsigned brightness
)
160 current_vp
->fg_pattern
= brightness
;
161 fg_pattern
= patterns
[brightness
& 3];
164 unsigned LCDFN(get_foreground
)(void)
166 return current_vp
->fg_pattern
;
169 void LCDFN(set_background
)(unsigned brightness
)
171 current_vp
->bg_pattern
= brightness
;
172 bg_pattern
= patterns
[brightness
& 3];
175 unsigned LCDFN(get_background
)(void)
177 return current_vp
->bg_pattern
;
180 void LCDFN(set_drawinfo
)(int mode
, unsigned fg_brightness
,
181 unsigned bg_brightness
)
183 LCDFN(set_drawmode
)(mode
);
184 LCDFN(set_foreground
)(fg_brightness
);
185 LCDFN(set_background
)(bg_brightness
);
188 int LCDFN(getwidth
)(void)
190 return current_vp
->width
;
193 int LCDFN(getheight
)(void)
195 return current_vp
->height
;
197 void LCDFN(setfont
)(int newfont
)
199 current_vp
->font
= newfont
;
202 int LCDFN(getfont
)(void)
204 return current_vp
->font
;
207 int LCDFN(getstringsize
)(const unsigned char *str
, int *w
, int *h
)
209 return font_getstringsize(str
, w
, h
, current_vp
->font
);
212 /*** low-level drawing functions ***/
214 static void setpixel(int x
, int y
)
216 unsigned mask
= 0x0101 << (y
& 7);
217 FBFN(data
) *address
= &LCDFN(framebuffer
)[y
>>3][x
];
218 unsigned data
= *address
;
220 *address
= data
^ ((data
^ fg_pattern
) & mask
);
223 static void clearpixel(int x
, int y
)
225 unsigned mask
= 0x0101 << (y
& 7);
226 FBFN(data
) *address
= &LCDFN(framebuffer
)[y
>>3][x
];
227 unsigned data
= *address
;
229 *address
= data
^ ((data
^ bg_pattern
) & mask
);
232 static void clearimgpixel(int x
, int y
)
234 unsigned mask
= 0x0101 << (y
& 7);
235 FBFN(data
) *address
= &LCDFN(framebuffer
)[y
>>3][x
];
236 unsigned data
= *address
;
238 *address
= data
^ ((data
^ *(FBFN(data
) *)((long)address
239 + backdrop_offset
)) & mask
);
242 static void flippixel(int x
, int y
)
244 unsigned mask
= 0x0101 << (y
& 7);
245 FBFN(data
) *address
= &LCDFN(framebuffer
)[y
>>3][x
];
250 static void nopixel(int x
, int y
)
256 LCDFN(pixelfunc_type
)* const LCDFN(pixelfuncs_bgcolor
)[8] = {
257 flippixel
, nopixel
, setpixel
, setpixel
,
258 nopixel
, clearpixel
, nopixel
, clearpixel
261 LCDFN(pixelfunc_type
)* const LCDFN(pixelfuncs_backdrop
)[8] = {
262 flippixel
, nopixel
, setpixel
, setpixel
,
263 nopixel
, clearimgpixel
, nopixel
, clearimgpixel
266 LCDFN(pixelfunc_type
)* const *LCDFN(pixelfuncs
) = LCDFN(pixelfuncs_bgcolor
);
268 /* 'mask' and 'bits' contain 2 bits per pixel */
269 static void ICODE_ATTR
flipblock(FBFN(data
) *address
, unsigned mask
,
272 *address
^= bits
& mask
;
275 static void ICODE_ATTR
bgblock(FBFN(data
) *address
, unsigned mask
,
278 unsigned data
= *address
;
280 *address
= data
^ ((data
^ bg_pattern
) & mask
& ~bits
);
283 static void ICODE_ATTR
bgimgblock(FBFN(data
) *address
, unsigned mask
,
286 unsigned data
= *address
;
288 *address
= data
^ ((data
^ *(FBFN(data
) *)((long)address
289 + backdrop_offset
)) & mask
& ~bits
);
292 static void ICODE_ATTR
fgblock(FBFN(data
) *address
, unsigned mask
,
295 unsigned data
= *address
;
297 *address
= data
^ ((data
^ fg_pattern
) & mask
& bits
);
300 static void ICODE_ATTR
solidblock(FBFN(data
) *address
, unsigned mask
,
303 unsigned data
= *address
;
304 unsigned bgp
= bg_pattern
;
306 bits
= bgp
^ ((bgp
^ fg_pattern
) & bits
);
307 *address
= data
^ ((data
^ bits
) & mask
);
310 static void ICODE_ATTR
solidimgblock(FBFN(data
) *address
, unsigned mask
,
313 unsigned data
= *address
;
314 unsigned bgp
= *(FBFN(data
) *)((long)address
+ backdrop_offset
);
316 bits
= bgp
^ ((bgp
^ fg_pattern
) & bits
);
317 *address
= data
^ ((data
^ bits
) & mask
);
320 static void ICODE_ATTR
flipinvblock(FBFN(data
) *address
, unsigned mask
,
323 *address
^= ~bits
& mask
;
326 static void ICODE_ATTR
bginvblock(FBFN(data
) *address
, unsigned mask
,
329 unsigned data
= *address
;
331 *address
= data
^ ((data
^ bg_pattern
) & mask
& bits
);
334 static void ICODE_ATTR
bgimginvblock(FBFN(data
) *address
, unsigned mask
,
337 unsigned data
= *address
;
339 *address
= data
^ ((data
^ *(FBFN(data
) *)((long)address
340 + backdrop_offset
)) & mask
& bits
);
343 static void ICODE_ATTR
fginvblock(FBFN(data
) *address
, unsigned mask
,
346 unsigned data
= *address
;
348 *address
= data
^ ((data
^ fg_pattern
) & mask
& ~bits
);
351 static void ICODE_ATTR
solidinvblock(FBFN(data
) *address
, unsigned mask
,
354 unsigned data
= *address
;
355 unsigned fgp
= fg_pattern
;
357 bits
= fgp
^ ((fgp
^ bg_pattern
) & bits
);
358 *address
= data
^ ((data
^ bits
) & mask
);
361 static void ICODE_ATTR
solidimginvblock(FBFN(data
) *address
, unsigned mask
,
364 unsigned data
= *address
;
365 unsigned fgp
= fg_pattern
;
367 bits
= fgp
^ ((fgp
^ *(FBFN(data
) *)((long)address
368 + backdrop_offset
)) & bits
);
369 *address
= data
^ ((data
^ bits
) & mask
);
372 LCDFN(blockfunc_type
)* const LCDFN(blockfuncs_bgcolor
)[8] = {
373 flipblock
, bgblock
, fgblock
, solidblock
,
374 flipinvblock
, bginvblock
, fginvblock
, solidinvblock
377 LCDFN(blockfunc_type
)* const LCDFN(blockfuncs_backdrop
)[8] = {
378 flipblock
, bgimgblock
, fgblock
, solidimgblock
,
379 flipinvblock
, bgimginvblock
, fginvblock
, solidimginvblock
382 LCDFN(blockfunc_type
)* const *LCDFN(blockfuncs
) = LCDFN(blockfuncs_bgcolor
);
385 void LCDFN(set_backdrop
)(FBFN(data
) *bd
)
390 backdrop_offset
= (long)bd
- (long)LCDFN(framebuffer
);
391 LCDFN(pixelfuncs
) = LCDFN(pixelfuncs_backdrop
);
392 LCDFN(blockfuncs
) = LCDFN(blockfuncs_backdrop
);
397 LCDFN(pixelfuncs
) = LCDFN(pixelfuncs_bgcolor
);
398 LCDFN(blockfuncs
) = LCDFN(blockfuncs_bgcolor
);
402 FBFN(data
)* LCDFN(get_backdrop
)(void)
407 static inline void setblock(FBFN(data
) *address
, unsigned mask
, unsigned bits
)
409 unsigned data
= *address
;
412 *address
= data
^ (bits
& mask
);
415 /*** drawing functions ***/
417 /* Clear the whole display */
418 void LCDFN(clear_display
)(void)
420 if (default_vp
.drawmode
& DRMODE_INVERSEVID
)
422 memset(LCDFN(framebuffer
), patterns
[default_vp
.fg_pattern
& 3],
423 sizeof LCDFN(framebuffer
));
428 memcpy(LCDFN(framebuffer
), backdrop
, sizeof LCDFN(framebuffer
));
430 memset(LCDFN(framebuffer
), patterns
[default_vp
.bg_pattern
& 3],
431 sizeof LCDFN(framebuffer
));
434 LCDFN(scroll_info
).lines
= 0;
437 /* Clear the current viewport */
438 void LCDFN(clear_viewport
)(void)
442 if (current_vp
== &default_vp
)
444 LCDFN(clear_display
)();
448 lastmode
= current_vp
->drawmode
;
450 /* Invert the INVERSEVID bit and set basic mode to SOLID */
451 current_vp
->drawmode
= (~lastmode
& DRMODE_INVERSEVID
) |
454 LCDFN(fillrect
)(0, 0, current_vp
->width
, current_vp
->height
);
456 current_vp
->drawmode
= lastmode
;
458 LCDFN(scroll_stop
)(current_vp
);
462 /* Set a single pixel */
463 void LCDFN(drawpixel
)(int x
, int y
)
465 if ( ((unsigned)x
< (unsigned)current_vp
->width
)
466 && ((unsigned)y
< (unsigned)current_vp
->height
)
467 #if defined(HAVE_VIEWPORT_CLIP)
468 && ((unsigned)x
< (unsigned)LCDM(WIDTH
))
469 && ((unsigned)y
< (unsigned)LCDM(HEIGHT
))
472 LCDFN(pixelfuncs
)[current_vp
->drawmode
](current_vp
->x
+x
, current_vp
->y
+y
);
476 void LCDFN(drawline
)(int x1
, int y1
, int x2
, int y2
)
484 LCDFN(pixelfunc_type
) *pfunc
= LCDFN(pixelfuncs
)[current_vp
->drawmode
];
486 deltax
= abs(x2
- x1
);
489 /* DEBUGF(LCDNAME "drawline() called for vertical line - optimisation.\n"); */
490 LCDFN(vline
)(x1
, y1
, y2
);
493 deltay
= abs(y2
- y1
);
496 /* DEBUGF(LCDNAME "drawline() called for horizontal line - optimisation.\n"); */
497 LCDFN(hline
)(x1
, x2
, y1
);
503 if (deltax
>= deltay
)
506 d
= 2 * deltay
- deltax
;
508 dinc2
= (deltay
- deltax
) * 2;
515 d
= 2 * deltax
- deltay
;
517 dinc2
= (deltax
- deltay
) * 2;
521 numpixels
++; /* include endpoints */
538 for (i
= 0; i
< numpixels
; i
++)
540 if ( ((unsigned)x
< (unsigned)current_vp
->width
)
541 && ((unsigned)y
< (unsigned)current_vp
->height
)
542 #if defined(HAVE_VIEWPORT_CLIP)
543 && ((unsigned)x
< (unsigned)LCDM(WIDTH
))
544 && ((unsigned)y
< (unsigned)LCDM(HEIGHT
))
547 pfunc(current_vp
->x
+ x
, current_vp
->y
+ y
);
564 /* Draw a horizontal line (optimised) */
565 void LCDFN(hline
)(int x1
, int x2
, int y
)
569 FBFN(data
) *dst
, *dst_end
;
571 LCDFN(blockfunc_type
) *bfunc
;
581 /******************** In viewport clipping **********************/
582 /* nothing to draw? */
583 if (((unsigned)y
>= (unsigned)current_vp
->height
) || (x1
>= current_vp
->width
)
589 if (x2
>= current_vp
->width
)
590 x2
= current_vp
->width
-1;
592 /* adjust x1 and y to viewport */
597 #if defined(HAVE_VIEWPORT_CLIP)
598 /********************* Viewport on screen clipping ********************/
599 /* nothing to draw? */
600 if (((unsigned)y
>= (unsigned) LCDM(HEIGHT
)) || (x1
>= LCDM(WIDTH
))
607 if (x2
>= LCDM(WIDTH
))
613 bfunc
= LCDFN(blockfuncs
)[current_vp
->drawmode
];
614 dst
= &LCDFN(framebuffer
)[y
>>3][x1
];
615 mask
= 0x0101 << (y
& 7);
617 dst_end
= dst
+ width
;
619 bfunc(dst
++, mask
, 0xFFFFu
);
620 while (dst
< dst_end
);
623 /* Draw a vertical line (optimised) */
624 void LCDFN(vline
)(int x
, int y1
, int y2
)
628 unsigned mask
, mask_bottom
;
629 LCDFN(blockfunc_type
) *bfunc
;
639 /******************** In viewport clipping **********************/
640 /* nothing to draw? */
641 if (((unsigned)x
>= (unsigned)current_vp
->width
) || (y1
>= current_vp
->height
)
647 if (y2
>= current_vp
->height
)
648 y2
= current_vp
->height
-1;
650 /* adjust for viewport */
655 #if defined(HAVE_VIEWPORT_CLIP)
656 /********************* Viewport on screen clipping ********************/
657 /* nothing to draw? */
658 if (( (unsigned) x
>= (unsigned)LCDM(WIDTH
)) || (y1
>= LCDM(HEIGHT
))
665 if (y2
>= LCDM(HEIGHT
))
669 bfunc
= LCDFN(blockfuncs
)[current_vp
->drawmode
];
670 dst
= &LCDFN(framebuffer
)[y1
>>3][x
];
672 mask
= (0xFFu
<< (y1
& 7)) & 0xFFu
;
674 mask_bottom
= 0xFFu
>> (~ny
& 7);
675 mask_bottom
|= mask_bottom
<< 8;
677 for (; ny
>= 8; ny
-= 8)
679 bfunc(dst
, mask
, 0xFFFFu
);
684 bfunc(dst
, mask
, 0xFFFFu
);
687 /* Draw a rectangular box */
688 void LCDFN(drawrect
)(int x
, int y
, int width
, int height
)
690 if ((width
<= 0) || (height
<= 0))
693 int x2
= x
+ width
- 1;
694 int y2
= y
+ height
- 1;
696 LCDFN(vline
)(x
, y
, y2
);
697 LCDFN(vline
)(x2
, y
, y2
);
698 LCDFN(hline
)(x
, x2
, y
);
699 LCDFN(hline
)(x
, x2
, y2
);
702 /* Fill a rectangular area */
703 void LCDFN(fillrect
)(int x
, int y
, int width
, int height
)
706 FBFN(data
) *dst
, *dst_end
;
707 unsigned mask
, mask_bottom
;
709 LCDFN(blockfunc_type
) *bfunc
;
710 bool fillopt
= false;
712 /******************** In viewport clipping **********************/
713 /* nothing to draw? */
714 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
)
715 || (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
728 if (x
+ width
> current_vp
->width
)
729 width
= current_vp
->width
- x
;
730 if (y
+ height
> current_vp
->height
)
731 height
= current_vp
->height
- y
;
733 /* adjust for viewport */
737 #if defined(HAVE_VIEWPORT_CLIP)
738 /********************* Viewport on screen clipping ********************/
739 /* nothing to draw? */
740 if ((x
>= LCDM(WIDTH
)) || (y
>= LCDM(HEIGHT
))
741 || (x
+ width
<= 0) || (y
+ height
<= 0))
744 /* clip image in viewport in screen */
755 if (x
+ width
> LCDM(WIDTH
))
756 width
= LCDM(WIDTH
) - x
;
757 if (y
+ height
> LCDM(HEIGHT
))
758 height
= LCDM(HEIGHT
) - y
;
762 if (current_vp
->drawmode
& DRMODE_INVERSEVID
)
764 if ((current_vp
->drawmode
& DRMODE_BG
) && !backdrop
)
772 if (current_vp
->drawmode
& DRMODE_FG
)
778 bfunc
= LCDFN(blockfuncs
)[current_vp
->drawmode
];
779 dst
= &LCDFN(framebuffer
)[y
>>3][x
];
780 ny
= height
- 1 + (y
& 7);
781 mask
= (0xFFu
<< (y
& 7)) & 0xFFu
;
783 mask_bottom
= 0xFFu
>> (~ny
& 7);
784 mask_bottom
|= mask_bottom
<< 8;
786 for (; ny
>= 8; ny
-= 8)
788 if (fillopt
&& (mask
== 0xFFFFu
))
789 memset16(dst
, bits
, width
);
792 FBFN(data
) *dst_row
= dst
;
794 dst_end
= dst_row
+ width
;
796 bfunc(dst_row
++, mask
, 0xFFFFu
);
797 while (dst_row
< dst_end
);
805 if (fillopt
&& (mask
== 0xFFFFu
))
806 memset16(dst
, bits
, width
);
809 dst_end
= dst
+ width
;
811 bfunc(dst
++, mask
, 0xFFFFu
);
812 while (dst
< dst_end
);
816 /* About Rockbox' internal monochrome bitmap format:
818 * A bitmap contains one bit for every pixel that defines if that pixel is
819 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
821 * The bytes are stored in row-major order, with byte 0 being top left,
822 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
823 * 0..7, the second row defines pixel row 8..15 etc.
825 * This is similar to the internal lcd hw format. */
827 /* Draw a partial monochrome bitmap */
828 void ICODE_ATTR
LCDFN(mono_bitmap_part
)(const unsigned char *src
, int src_x
,
829 int src_y
, int stride
, int x
, int y
,
830 int width
, int height
)
833 FBFN(data
) *dst
, *dst_end
;
834 unsigned data
, mask
, mask_bottom
;
835 LCDFN(blockfunc_type
) *bfunc
;
837 /******************** Image in viewport clipping **********************/
838 /* nothing to draw? */
839 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
) ||
840 (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
855 if (x
+ width
> current_vp
->width
)
856 width
= current_vp
->width
- x
;
857 if (y
+ height
> current_vp
->height
)
858 height
= current_vp
->height
- y
;
860 /* adjust for viewport */
864 #if defined(HAVE_VIEWPORT_CLIP)
865 /********************* Viewport on screen clipping ********************/
866 /* nothing to draw? */
867 if ((x
>= LCDM(WIDTH
)) || (y
>= LCDM(HEIGHT
))
868 || (x
+ width
<= 0) || (y
+ height
<= 0))
871 /* clip image in viewport in screen */
884 if (x
+ width
> LCDM(WIDTH
))
885 width
= LCDM(WIDTH
) - x
;
886 if (y
+ height
> LCDM(HEIGHT
))
887 height
= LCDM(HEIGHT
) - y
;
890 src
+= stride
* (src_y
>> 3) + src_x
; /* move starting point */
893 dst
= &LCDFN(framebuffer
)[y
>>3][x
];
895 ny
= height
- 1 + shift
+ src_y
;
897 bfunc
= LCDFN(blockfuncs
)[current_vp
->drawmode
];
898 mask
= 0xFFu
<< (shift
+ src_y
);
899 /* not byte-doubled here because shift+src_y can be > 7 */
900 mask_bottom
= 0xFFu
>> (~ny
& 7);
901 mask_bottom
|= mask_bottom
<< 8;
908 for (; ny
>= 8; ny
-= 8)
910 const unsigned char *src_row
= src
;
911 FBFN(data
) *dst_row
= dst
;
913 dst_end
= dst_row
+ width
;
917 bfunc(dst_row
++, mask
, data
| (data
<< 8));
919 while (dst_row
< dst_end
);
927 dst_end
= dst
+ width
;
931 bfunc(dst
++, mask
, data
| (data
<< 8));
933 while (dst
< dst_end
);
939 dst_end
= dst
+ width
;
942 const unsigned char *src_col
= src
++;
943 FBFN(data
) *dst_col
= dst
++;
944 unsigned mask_col
= mask
& 0xFFu
;
946 mask_col
|= mask_col
<< 8;
949 for (y
= ny
; y
>= 8; y
-= 8)
951 data
|= *src_col
<< shift
;
955 ddata
= data
& 0xFFu
;
956 bfunc(dst_col
, mask_col
, ddata
| (ddata
<< 8));
961 mask_col
= (mask
>> 8) & 0xFFu
;
962 mask_col
|= mask_col
<< 8;
966 dst_col
+= LCDM(WIDTH
);
969 data
|= *src_col
<< shift
;
970 mask_col
&= mask_bottom
;
971 ddata
= data
& 0xFFu
;
972 bfunc(dst_col
, mask_col
, ddata
| (ddata
<< 8));
974 while (dst
< dst_end
);
978 /* Draw a full monochrome bitmap */
979 void LCDFN(mono_bitmap
)(const unsigned char *src
, int x
, int y
, int width
,
982 LCDFN(mono_bitmap_part
)(src
, 0, 0, width
, x
, y
, width
, height
);
985 /* About Rockbox' internal native bitmap format:
987 * A bitmap contains one bit in each byte of a pair of bytes for every pixel.
988 * 00 = white, 01 = light grey, 10 = dark grey, 11 = black. Bits within a byte
989 * are arranged vertically, LSB at top.
990 * The pairs of bytes are stored as shorts, in row-major order, with word 0
991 * being top left, word 1 2nd from left etc. The first row of words defines
992 * pixel rows 0..7, the second row defines pixel row 8..15 etc.
994 * This is the same as the internal lcd hw format. */
996 /* Draw a partial native bitmap */
997 void ICODE_ATTR
LCDFN(bitmap_part
)(const FBFN(data
) *src
, int src_x
,
998 int src_y
, int stride
, int x
, int y
,
999 int width
, int height
)
1002 FBFN(data
) *dst
, *dst_end
;
1003 unsigned mask
, mask_bottom
;
1005 /******************** Image in viewport clipping **********************/
1006 /* nothing to draw? */
1007 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
)
1008 || (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
1023 if (x
+ width
> current_vp
->width
)
1024 width
= current_vp
->width
- x
;
1025 if (y
+ height
> current_vp
->height
)
1026 height
= current_vp
->height
- y
;
1028 /* adjust for viewport */
1032 #if defined(HAVE_VIEWPORT_CLIP)
1033 /********************* Viewport on screen clipping ********************/
1034 /* nothing to draw? */
1035 if ((x
>= LCDM(WIDTH
)) || (y
>= LCDM(HEIGHT
))
1036 || (x
+ width
<= 0) || (y
+ height
<= 0))
1039 /* clip image in viewport in screen */
1052 if (x
+ width
> LCDM(WIDTH
))
1053 width
= LCDM(WIDTH
) - x
;
1054 if (y
+ height
> LCDM(HEIGHT
))
1055 height
= LCDM(HEIGHT
) - y
;
1058 src
+= stride
* (src_y
>> 3) + src_x
; /* move starting point */
1061 dst
= &LCDFN(framebuffer
)[y
>>3][x
];
1063 ny
= height
- 1 + shift
+ src_y
;
1065 mask
= 0xFFu
<< (shift
+ src_y
);
1066 /* not byte-doubled here because shift+src_y can be > 7 */
1067 mask_bottom
= 0xFFu
>> (~ny
& 7);
1068 mask_bottom
|= mask_bottom
<< 8;
1075 for (; ny
>= 8; ny
-= 8)
1077 if (mask
== 0xFFFFu
)
1078 memcpy(dst
, src
, width
* sizeof(FBFN(data
)));
1081 const FBFN(data
) *src_row
= src
;
1082 FBFN(data
) *dst_row
= dst
;
1084 dst_end
= dst_row
+ width
;
1086 setblock(dst_row
++, mask
, *src_row
++);
1087 while (dst_row
< dst_end
);
1093 mask
&= mask_bottom
;
1095 if (mask
== 0xFFFFu
)
1096 memcpy(dst
, src
, width
* sizeof(FBFN(data
)));
1099 dst_end
= dst
+ width
;
1101 setblock(dst
++, mask
, *src
++);
1102 while (dst
< dst_end
);
1107 unsigned datamask
= (0xFFu
<< shift
) & 0xFFu
;
1109 datamask
|= datamask
<< 8;
1111 dst_end
= dst
+ width
;
1114 const FBFN(data
) *src_col
= src
++;
1115 FBFN(data
) *dst_col
= dst
++;
1116 unsigned mask_col
= mask
& 0xFFu
;
1117 unsigned data
, olddata
= 0;
1119 mask_col
|= mask_col
<< 8;
1121 for (y
= ny
; y
>= 8; y
-= 8)
1123 data
= *src_col
<< shift
;
1127 setblock(dst_col
, mask_col
,
1128 olddata
^((olddata
^ data
) & datamask
));
1133 mask_col
= (mask
>> 8) & 0xFFu
;
1134 mask_col
|= mask_col
<< 8;
1137 dst_col
+= LCDM(WIDTH
);
1138 olddata
= data
>> 8;
1140 data
= *src_col
<< shift
;
1141 setblock(dst_col
, mask_col
& mask_bottom
,
1142 olddata
^((olddata
^ data
) & datamask
));
1144 while (dst
< dst_end
);
1148 /* Draw a full native bitmap */
1149 void LCDFN(bitmap
)(const FBFN(data
) *src
, int x
, int y
, int width
, int height
)
1151 LCDFN(bitmap_part
)(src
, 0, 0, width
, x
, y
, width
, height
);
1154 #include "lcd-bitmap-common.c"