1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * LCD driver for horizontally-packed 2bpp greyscale display
12 * Based on code from the rockbox lcd's driver
14 * Copyright (c) 2006 Seven Le Mesle (sevlm@free.fr)
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22 * KIND, either express or implied.
24 ****************************************************************************/
36 #include "rbunicode.h"
38 #include "scroll_engine.h"
42 unsigned char lcd_static_framebuffer
[LCD_FBHEIGHT
][LCD_FBWIDTH
] IRAM_LCDFRAMEBUFFER
;
43 unsigned char *lcd_framebuffer
= &lcd_static_framebuffer
[0][0];
45 static const unsigned char pixmask
[4] ICONST_ATTR
= {
46 0xC0, 0x30, 0x0C, 0x03
49 static fb_data
* lcd_backdrop
= NULL
;
50 static long lcd_backdrop_offset IDATA_ATTR
= 0;
52 static struct viewport default_vp
=
58 .font
= FONT_SYSFIXED
,
59 .drawmode
= DRMODE_SOLID
,
60 .fg_pattern
= LCD_DEFAULT_FG
,
61 .bg_pattern
= LCD_DEFAULT_BG
64 static struct viewport
* current_vp IBSS_ATTR
;
65 static unsigned fg_pattern IBSS_ATTR
;
66 static unsigned bg_pattern IBSS_ATTR
;
71 /* Initialise the viewport */
72 lcd_set_viewport(NULL
);
75 /* Call device specific init */
82 void lcd_set_viewport(struct viewport
* vp
)
85 current_vp
= &default_vp
;
89 fg_pattern
= 0x55 * (~current_vp
->fg_pattern
& 3);
90 bg_pattern
= 0x55 * (~current_vp
->bg_pattern
& 3);
92 #if defined(SIMULATOR)
93 /* Force the viewport to be within bounds. If this happens it should
94 * be considered an error - the viewport will not draw as it might be
97 if((unsigned) current_vp
->x
> (unsigned) LCD_WIDTH
98 || (unsigned) current_vp
->y
> (unsigned) LCD_HEIGHT
99 || current_vp
->x
+ current_vp
->width
> LCD_WIDTH
100 || current_vp
->y
+ current_vp
->height
> LCD_HEIGHT
)
102 #if !defined(HAVE_VIEWPORT_CLIP)
107 "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n",
108 current_vp
->x
, current_vp
->y
,
109 current_vp
->width
, current_vp
->height
);
115 void lcd_update_viewport(void)
117 lcd_update_rect(current_vp
->x
, current_vp
->y
,
118 current_vp
->width
, current_vp
->height
);
121 void lcd_update_viewport_rect(int x
, int y
, int width
, int height
)
123 lcd_update_rect(current_vp
->x
+ x
, current_vp
->y
+ y
, width
, height
);
126 /*** parameter handling ***/
128 void lcd_set_drawmode(int mode
)
130 current_vp
->drawmode
= mode
& (DRMODE_SOLID
|DRMODE_INVERSEVID
);
133 int lcd_get_drawmode(void)
135 return current_vp
->drawmode
;
138 void lcd_set_foreground(unsigned brightness
)
140 current_vp
->fg_pattern
= brightness
;
141 fg_pattern
= 0x55 * (~brightness
& 3);
144 unsigned lcd_get_foreground(void)
146 return current_vp
->fg_pattern
;
149 void lcd_set_background(unsigned brightness
)
151 current_vp
->bg_pattern
= brightness
;
152 bg_pattern
= 0x55 * (~brightness
& 3);
155 unsigned lcd_get_background(void)
157 return current_vp
->bg_pattern
;
160 void lcd_set_drawinfo(int mode
, unsigned fg_brightness
, unsigned bg_brightness
)
162 lcd_set_drawmode(mode
);
163 lcd_set_foreground(fg_brightness
);
164 lcd_set_background(bg_brightness
);
167 int lcd_getwidth(void)
169 return current_vp
->width
;
172 int lcd_getheight(void)
174 return current_vp
->height
;
177 void lcd_setfont(int newfont
)
179 current_vp
->font
= newfont
;
182 int lcd_getfont(void)
184 return current_vp
->font
;
187 int lcd_getstringsize(const unsigned char *str
, int *w
, int *h
)
189 return font_getstringsize(str
, w
, h
, current_vp
->font
);
192 /*** low-level drawing functions ***/
194 static void setpixel(int x
, int y
)
196 unsigned mask
= pixmask
[x
& 3];
197 fb_data
*address
= FBADDR(x
>>2,y
);
198 unsigned data
= *address
;
200 *address
= data
^ ((data
^ fg_pattern
) & mask
);
203 static void clearpixel(int x
, int y
)
205 unsigned mask
= pixmask
[x
& 3];
206 fb_data
*address
= FBADDR(x
>>2,y
);
207 unsigned data
= *address
;
209 *address
= data
^ ((data
^ bg_pattern
) & mask
);
212 static void clearimgpixel(int x
, int y
)
214 unsigned mask
= pixmask
[x
& 3];
215 fb_data
*address
= FBADDR(x
>>2,y
);
216 unsigned data
= *address
;
218 *address
= data
^ ((data
^ *(address
+ lcd_backdrop_offset
)) & mask
);
221 static void flippixel(int x
, int y
)
223 unsigned mask
= pixmask
[x
& 3];
224 fb_data
*address
= FBADDR(x
>>2,y
);
229 static void nopixel(int x
, int y
)
235 lcd_pixelfunc_type
* const lcd_pixelfuncs_bgcolor
[8] = {
236 flippixel
, nopixel
, setpixel
, setpixel
,
237 nopixel
, clearpixel
, nopixel
, clearpixel
240 lcd_pixelfunc_type
* const lcd_pixelfuncs_backdrop
[8] = {
241 flippixel
, nopixel
, setpixel
, setpixel
,
242 nopixel
, clearimgpixel
, nopixel
, clearimgpixel
245 lcd_pixelfunc_type
* const * lcd_pixelfuncs
= lcd_pixelfuncs_bgcolor
;
248 /* 'mask' and 'bits' contain 2 bits per pixel */
249 static void ICODE_ATTR
flipblock(fb_data
*address
, unsigned mask
,
252 *address
^= bits
& mask
;
255 static void ICODE_ATTR
bgblock(fb_data
*address
, unsigned mask
,
258 unsigned data
= *address
;
260 *address
= data
^ ((data
^ bg_pattern
) & mask
& ~bits
);
263 static void ICODE_ATTR
bgimgblock(fb_data
*address
, unsigned mask
,
266 unsigned data
= *address
;
268 *address
= data
^ ((data
^ *(address
+ lcd_backdrop_offset
)) & mask
& ~bits
);
271 static void ICODE_ATTR
fgblock(fb_data
*address
, unsigned mask
,
274 unsigned data
= *address
;
276 *address
= data
^ ((data
^ fg_pattern
) & mask
& bits
);
279 static void ICODE_ATTR
solidblock(fb_data
*address
, unsigned mask
,
282 unsigned data
= *address
;
283 unsigned bgp
= bg_pattern
;
285 bits
= bgp
^ ((bgp
^ fg_pattern
) & bits
);
286 *address
= data
^ ((data
^ bits
) & mask
);
289 static void ICODE_ATTR
solidimgblock(fb_data
*address
, unsigned mask
,
292 unsigned data
= *address
;
293 unsigned bgp
= *(address
+ lcd_backdrop_offset
);
295 bits
= bgp
^ ((bgp
^ fg_pattern
) & bits
);
296 *address
= data
^ ((data
^ bits
) & mask
);
299 static void ICODE_ATTR
flipinvblock(fb_data
*address
, unsigned mask
,
302 *address
^= ~bits
& mask
;
305 static void ICODE_ATTR
bginvblock(fb_data
*address
, unsigned mask
,
308 unsigned data
= *address
;
310 *address
= data
^ ((data
^ bg_pattern
) & mask
& bits
);
313 static void ICODE_ATTR
bgimginvblock(fb_data
*address
, unsigned mask
,
316 unsigned data
= *address
;
318 *address
= data
^ ((data
^ *(address
+ lcd_backdrop_offset
)) & mask
& bits
);
321 static void ICODE_ATTR
fginvblock(fb_data
*address
, unsigned mask
,
324 unsigned data
= *address
;
326 *address
= data
^ ((data
^ fg_pattern
) & mask
& ~bits
);
329 static void ICODE_ATTR
solidinvblock(fb_data
*address
, unsigned mask
,
332 unsigned data
= *address
;
333 unsigned fgp
= fg_pattern
;
335 bits
= fgp
^ ((fgp
^ bg_pattern
) & bits
);
336 *address
= data
^ ((data
^ bits
) & mask
);
339 static void ICODE_ATTR
solidimginvblock(fb_data
*address
, unsigned mask
,
342 unsigned data
= *address
;
343 unsigned fgp
= fg_pattern
;
345 bits
= fgp
^ ((fgp
^ *(address
+ lcd_backdrop_offset
)) & bits
);
346 *address
= data
^ ((data
^ bits
) & mask
);
349 lcd_blockfunc_type
* const lcd_blockfuncs_bgcolor
[8] = {
350 flipblock
, bgblock
, fgblock
, solidblock
,
351 flipinvblock
, bginvblock
, fginvblock
, solidinvblock
354 lcd_blockfunc_type
* const lcd_blockfuncs_backdrop
[8] = {
355 flipblock
, bgimgblock
, fgblock
, solidimgblock
,
356 flipinvblock
, bgimginvblock
, fginvblock
, solidimginvblock
359 lcd_blockfunc_type
* const * lcd_blockfuncs
= lcd_blockfuncs_bgcolor
;
362 void lcd_set_backdrop(fb_data
* backdrop
)
364 lcd_backdrop
= backdrop
;
367 lcd_backdrop_offset
= (long)backdrop
- (long)lcd_framebuffer
;
368 lcd_pixelfuncs
= lcd_pixelfuncs_backdrop
;
369 lcd_blockfuncs
= lcd_blockfuncs_backdrop
;
373 lcd_backdrop_offset
= 0;
374 lcd_pixelfuncs
= lcd_pixelfuncs_bgcolor
;
375 lcd_blockfuncs
= lcd_blockfuncs_bgcolor
;
379 fb_data
* lcd_get_backdrop(void)
385 static inline void setblock(fb_data
*address
, unsigned mask
, unsigned bits
)
387 unsigned data
= *address
;
390 *address
= data
^ (bits
& mask
);
393 /*** drawing functions ***/
395 /* Clear the whole display */
396 void lcd_clear_display(void)
398 if (current_vp
->drawmode
& DRMODE_INVERSEVID
)
400 memset(lcd_framebuffer
, fg_pattern
, FRAMEBUFFER_SIZE
);
405 memcpy(lcd_framebuffer
, lcd_backdrop
, FRAMEBUFFER_SIZE
);
407 memset(lcd_framebuffer
, bg_pattern
, FRAMEBUFFER_SIZE
);
410 lcd_scroll_info
.lines
= 0;
413 /* Clear the current viewport */
414 void lcd_clear_viewport(void)
418 if (current_vp
== &default_vp
)
424 lastmode
= current_vp
->drawmode
;
426 /* Invert the INVERSEVID bit and set basic mode to SOLID */
427 current_vp
->drawmode
= (~lastmode
& DRMODE_INVERSEVID
) |
430 lcd_fillrect(0, 0, current_vp
->width
, current_vp
->height
);
432 current_vp
->drawmode
= lastmode
;
434 lcd_scroll_stop(current_vp
);
438 /* Set a single pixel */
439 void lcd_drawpixel(int x
, int y
)
441 if ( ((unsigned)x
< (unsigned)current_vp
->width
)
442 && ((unsigned)y
< (unsigned)current_vp
->height
)
443 #if defined(HAVE_VIEWPORT_CLIP)
444 && ((unsigned)x
< (unsigned)LCD_WIDTH
)
445 && ((unsigned)y
< (unsigned)LCD_HEIGHT
)
448 lcd_pixelfuncs
[current_vp
->drawmode
](current_vp
->x
+ x
, current_vp
->y
+ y
);
452 void lcd_drawline(int x1
, int y1
, int x2
, int y2
)
460 lcd_pixelfunc_type
*pfunc
= lcd_pixelfuncs
[current_vp
->drawmode
];
462 deltay
= abs(y2
- y1
);
465 /* DEBUGF("lcd_drawline() called for horizontal line - optimisation.\n"); */
466 lcd_hline(x1
, x2
, y1
);
469 deltax
= abs(x2
- x1
);
472 /* DEBUGF("lcd_drawline() called for vertical line - optimisation.\n"); */
473 lcd_vline(x1
, y1
, y2
);
479 if (deltax
>= deltay
)
482 d
= 2 * deltay
- deltax
;
484 dinc2
= (deltay
- deltax
) * 2;
491 d
= 2 * deltax
- deltay
;
493 dinc2
= (deltax
- deltay
) * 2;
497 numpixels
++; /* include endpoints */
514 for (i
= 0; i
< numpixels
; i
++)
516 if ( ((unsigned)x
< (unsigned)current_vp
->width
)
517 && ((unsigned)y
< (unsigned)current_vp
->height
)
518 #if defined(HAVE_VIEWPORT_CLIP)
519 && ((unsigned)x
< (unsigned)LCD_WIDTH
)
520 && ((unsigned)y
< (unsigned)LCD_HEIGHT
)
523 pfunc(current_vp
->x
+ x
, current_vp
->y
+ y
);
540 /* Draw a horizontal line (optimised) */
541 void lcd_hline(int x1
, int x2
, int y
)
545 unsigned mask
, mask_right
;
546 lcd_blockfunc_type
*bfunc
;
556 /******************** In viewport clipping **********************/
557 /* nothing to draw? */
558 if (((unsigned)y
>= (unsigned)current_vp
->height
) || (x1
>= current_vp
->width
)
564 if (x2
>= current_vp
->width
)
565 x2
= current_vp
->width
-1;
567 /* adjust to viewport */
572 #if defined(HAVE_VIEWPORT_CLIP)
573 /********************* Viewport on screen clipping ********************/
574 /* nothing to draw? */
575 if (((unsigned)y
>= (unsigned) LCD_HEIGHT
) || (x1
>= LCD_WIDTH
)
586 bfunc
= lcd_blockfuncs
[current_vp
->drawmode
];
587 dst
= FBADDR(x1
>>2,y
);
589 mask
= 0xFFu
>> (2 * (x1
& 3));
590 mask_right
= 0xFFu
<< (2 * (~nx
& 3));
592 for (; nx
>= 4; nx
-= 4)
594 bfunc(dst
++, mask
, 0xFFu
);
598 bfunc(dst
, mask
, 0xFFu
);
601 /* Draw a vertical line (optimised) */
602 void lcd_vline(int x
, int y1
, int y2
)
605 unsigned char *dst
, *dst_end
;
607 lcd_blockfunc_type
*bfunc
;
617 /******************** In viewport clipping **********************/
618 /* nothing to draw? */
619 if (((unsigned)x
>= (unsigned)current_vp
->width
) || (y1
>= current_vp
->height
)
625 if (y2
>= current_vp
->height
)
626 y2
= current_vp
->height
-1;
628 /* adjust for viewport */
633 #if defined(HAVE_VIEWPORT_CLIP)
634 /********************* Viewport on screen clipping ********************/
635 /* nothing to draw? */
636 if (( (unsigned) x
>= (unsigned)LCD_WIDTH
) || (y1
>= LCD_HEIGHT
)
643 if (y2
>= LCD_HEIGHT
)
647 bfunc
= lcd_blockfuncs
[current_vp
->drawmode
];
648 dst
= FBADDR(x
>>2,y1
);
649 mask
= pixmask
[x
& 3];
651 dst_end
= dst
+ (y2
- y1
) * LCD_FBWIDTH
;
654 bfunc(dst
, mask
, 0xFFu
);
657 while (dst
<= dst_end
);
660 /* Draw a rectangular box */
661 void lcd_drawrect(int x
, int y
, int width
, int height
)
663 if ((width
<= 0) || (height
<= 0))
666 int x2
= x
+ width
- 1;
667 int y2
= y
+ height
- 1;
670 lcd_vline(x2
, y
, y2
);
672 lcd_hline(x
, x2
, y2
);
675 /* Fill a rectangular area */
676 void lcd_fillrect(int x
, int y
, int width
, int height
)
679 unsigned char *dst
, *dst_end
;
680 unsigned mask
, mask_right
;
681 lcd_blockfunc_type
*bfunc
;
683 /******************** In viewport clipping **********************/
684 /* nothing to draw? */
685 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
) || (y
>= current_vp
->height
)
686 || (x
+ width
<= 0) || (y
+ height
<= 0))
699 if (x
+ width
> current_vp
->width
)
700 width
= current_vp
->width
- x
;
701 if (y
+ height
> current_vp
->height
)
702 height
= current_vp
->height
- y
;
704 /* adjust for viewport */
708 #if defined(HAVE_VIEWPORT_CLIP)
709 /********************* Viewport on screen clipping ********************/
710 /* nothing to draw? */
711 if ((x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
712 || (x
+ width
<= 0) || (y
+ height
<= 0))
715 /* clip image in viewport in screen */
726 if (x
+ width
> LCD_WIDTH
)
727 width
= LCD_WIDTH
- x
;
728 if (y
+ height
> LCD_HEIGHT
)
729 height
= LCD_HEIGHT
- y
;
732 bfunc
= lcd_blockfuncs
[current_vp
->drawmode
];
733 dst
= FBADDR(x
>>2,y
);
734 nx
= width
- 1 + (x
& 3);
735 mask
= 0xFFu
>> (2 * (x
& 3));
736 mask_right
= 0xFFu
<< (2 * (~nx
& 3));
738 for (; nx
>= 4; nx
-= 4)
740 unsigned char *dst_col
= dst
;
742 dst_end
= dst_col
+ height
* LCD_FBWIDTH
;
745 bfunc(dst_col
, mask
, 0xFFu
);
746 dst_col
+= LCD_FBWIDTH
;
748 while (dst_col
< dst_end
);
755 dst_end
= dst
+ height
* LCD_FBWIDTH
;
758 bfunc(dst
, mask
, 0xFFu
);
761 while (dst
< dst_end
);
764 /* About Rockbox' internal monochrome bitmap format:
766 * A bitmap contains one bit for every pixel that defines if that pixel is
767 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
769 * The bytes are stored in row-major order, with byte 0 being top left,
770 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
771 * 0..7, the second row defines pixel row 8..15 etc. */
773 /* Draw a partial monochrome bitmap */
774 void ICODE_ATTR
lcd_mono_bitmap_part(const unsigned char *src
, int src_x
,
775 int src_y
, int stride
, int x
, int y
,
776 int width
, int height
)
778 const unsigned char *src_end
;
779 fb_data
*dst
, *dst_end
;
780 unsigned dmask
= 0x100; /* bit 8 == sentinel */
782 int drmode
= current_vp
->drawmode
;
784 /******************** Image in viewport clipping **********************/
785 /* nothing to draw? */
786 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
) ||
787 (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
802 if (x
+ width
> current_vp
->width
)
803 width
= current_vp
->width
- x
;
804 if (y
+ height
> current_vp
->height
)
805 height
= current_vp
->height
- y
;
807 x
+= current_vp
->x
; /* adjust for viewport */
808 y
+= current_vp
->y
; /* adjust for viewport */
810 #if defined(HAVE_VIEWPORT_CLIP)
811 /********************* Viewport on screen clipping ********************/
812 /* nothing to draw? */
813 if ((x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
814 || (x
+ width
<= 0) || (y
+ height
<= 0))
817 /* clip image in viewport in screen */
830 if (x
+ width
> LCD_WIDTH
)
831 width
= LCD_WIDTH
- x
;
832 if (y
+ height
> LCD_HEIGHT
)
833 height
= LCD_HEIGHT
- y
;
836 src
+= stride
* (src_y
>> 3) + src_x
; /* move starting point */
838 src_end
= src
+ width
;
840 dst
= FBADDR(x
>> 2,y
);
841 dst_end
= dst
+ height
* LCD_FBWIDTH
;
842 dst_mask
= pixmask
[x
& 3];
844 if (drmode
& DRMODE_INVERSEVID
)
846 dmask
= 0x1ff; /* bit 8 == sentinel */
847 drmode
&= DRMODE_SOLID
; /* mask out inversevid */
852 const unsigned char *src_col
= src
++;
853 unsigned data
= (*src_col
^ dmask
) >> src_y
;
854 fb_data
*dst_col
= dst
;
858 #define UPDATE_SRC do { \
860 if (data == 0x001) { \
862 data = *src_col ^ dmask; \
868 case DRMODE_COMPLEMENT
:
872 *dst_col
^= dst_mask
;
874 dst_col
+= LCD_FBWIDTH
;
877 while (dst_col
< dst_end
);
883 bo
= lcd_backdrop_offset
;
888 unsigned block
= *dst_col
;
890 ^ ((block
^ *(dst_col
+ bo
)) & dst_mask
);
892 dst_col
+= LCD_FBWIDTH
;
895 while (dst_col
< dst_end
);
904 unsigned block
= *dst_col
;
905 *dst_col
= block
^ ((block
^ bg
) & dst_mask
);
907 dst_col
+= LCD_FBWIDTH
;
910 while (dst_col
< dst_end
);
920 unsigned block
= *dst_col
;
921 *dst_col
= block
^ ((block
^ fg
) & dst_mask
);
923 dst_col
+= LCD_FBWIDTH
;
926 while (dst_col
< dst_end
);
933 bo
= lcd_backdrop_offset
;
936 unsigned block
= *dst_col
;
937 *dst_col
= block
^ ((block
^ ((data
& 0x01) ?
938 fg
: *(dst_col
+ bo
))) & dst_mask
);
940 dst_col
+= LCD_FBWIDTH
;
943 while (dst_col
< dst_end
);
950 unsigned block
= *dst_col
;
951 *dst_col
= block
^ ((block
^ ((data
& 0x01) ?
952 fg
: bg
)) & dst_mask
);
954 dst_col
+= LCD_FBWIDTH
;
957 while (dst_col
< dst_end
);
968 while (src
< src_end
);
971 /* Draw a full monochrome bitmap */
972 void lcd_mono_bitmap(const unsigned char *src
, int x
, int y
, int width
, int height
)
974 lcd_mono_bitmap_part(src
, 0, 0, width
, x
, y
, width
, height
);
977 /* About Rockbox' internal native bitmap format:
979 * A bitmap contains two bits for every pixel. 00 = white, 01 = light grey,
980 * 10 = dark grey, 11 = black. Bits within a byte are arranged horizontally,
982 * The bytes are stored in row-major order, with byte 0 being top left,
983 * byte 1 2nd from left etc. Each row of bytes defines one pixel row.
985 * This is the same as the internal lcd hw format. */
987 /* Draw a partial native bitmap */
988 void ICODE_ATTR
lcd_bitmap_part(const unsigned char *src
, int src_x
,
989 int src_y
, int stride
, int x
, int y
,
990 int width
, int height
)
993 unsigned char *dst
, *dst_end
;
994 unsigned mask
, mask_right
;
996 /******************** Image in viewport clipping **********************/
997 /* nothing to draw? */
998 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
) ||
999 (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
1014 if (x
+ width
> current_vp
->width
)
1015 width
= current_vp
->width
- x
;
1016 if (y
+ height
> current_vp
->height
)
1017 height
= current_vp
->height
- y
;
1019 /* adjust for viewport */
1023 #if defined(HAVE_VIEWPORT_CLIP)
1024 /********************* Viewport on screen clipping ********************/
1025 /* nothing to draw? */
1026 if ((x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
1027 || (x
+ width
<= 0) || (y
+ height
<= 0))
1030 /* clip image in viewport in screen */
1043 if (x
+ width
> LCD_WIDTH
)
1044 width
= LCD_WIDTH
- x
;
1045 if (y
+ height
> LCD_HEIGHT
)
1046 height
= LCD_HEIGHT
- y
;
1049 stride
= (stride
+ 3) >> 2; /* convert to no. of bytes */
1051 src
+= stride
* src_y
+ (src_x
>> 2); /* move starting point */
1054 dst
= FBADDR(x
>>2,y
);
1056 nx
= width
- 1 + shift
+ src_x
;
1058 mask
= 0xFF00u
>> (2 * (shift
+ src_x
));
1059 mask_right
= 0xFFu
<< (2 * (~nx
& 3));
1062 dst_end
= dst
+ height
* LCD_FBWIDTH
;
1065 const unsigned char *src_row
= src
;
1066 unsigned char *dst_row
= dst
;
1067 unsigned mask_row
= mask
>> 8;
1070 for (x
= nx
; x
>= 4; x
-= 4)
1072 data
= (data
<< 8) | *src_row
++;
1074 if (mask_row
& 0xFF)
1076 setblock(dst_row
, mask_row
, data
>> shift
);
1084 data
= (data
<< 8) | *src_row
;
1085 setblock(dst_row
, mask_row
& mask_right
, data
>> shift
);
1090 while (dst
< dst_end
);
1093 /* Draw a full native bitmap */
1094 void lcd_bitmap(const unsigned char *src
, int x
, int y
, int width
, int height
)
1096 lcd_bitmap_part(src
, 0, 0, width
, x
, y
, width
, height
);
1099 #include "lcd-bitmap-common.c"