1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 by Dave Chapman
11 * Copyright (C) 2009 by Karl Kurbjun
13 * Rockbox driver for 16-bit colour LCDs
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
32 #include "string-extra.h" /* mem*() */
37 #include "rbunicode.h"
39 #include "scroll_engine.h"
41 #define ROW_INC LCD_WIDTH
44 #define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)])
46 #include "lcd-16bit-common.c"
48 #include "lcd-bitmap-common.c"
50 /*** drawing functions ***/
52 /* Clear the current viewport */
53 void lcd_clear_viewport(void)
55 fb_data
*dst
, *dst_end
;
57 dst
= LCDADDR(current_vp
->x
, current_vp
->y
);
58 dst_end
= dst
+ current_vp
->height
* LCD_WIDTH
;
60 if (current_vp
->drawmode
& DRMODE_INVERSEVID
)
64 memset16(dst
, current_vp
->fg_pattern
, current_vp
->width
);
67 while (dst
< dst_end
);
75 memset16(dst
, current_vp
->bg_pattern
, current_vp
->width
);
78 while (dst
< dst_end
);
84 memcpy(dst
, (void *)((long)dst
+ lcd_backdrop_offset
),
85 current_vp
->width
* sizeof(fb_data
));
88 while (dst
< dst_end
);
92 if (current_vp
== &default_vp
)
94 lcd_scroll_info
.lines
= 0;
98 lcd_scroll_stop(current_vp
);
102 /* Draw a horizontal line (optimised) */
103 void lcd_hline(int x1
, int x2
, int y
)
107 enum fill_opt fillopt
= OPT_NONE
;
108 fb_data
*dst
, *dst_end
;
118 /******************** In viewport clipping **********************/
119 /* nothing to draw? */
120 if (((unsigned)y
>= (unsigned)current_vp
->height
) ||
121 (x1
>= current_vp
->width
) ||
127 if (x2
>= current_vp
->width
)
128 x2
= current_vp
->width
-1;
130 /* Adjust x1 and y to viewport */
135 #if defined(HAVE_VIEWPORT_CLIP)
136 /********************* Viewport on screen clipping ********************/
137 /* nothing to draw? */
138 if (((unsigned)y
>= (unsigned) LCD_HEIGHT
) || (x1
>= LCD_WIDTH
)
151 /* drawmode and optimisation */
152 if (current_vp
->drawmode
& DRMODE_INVERSEVID
)
154 if (current_vp
->drawmode
& DRMODE_BG
)
159 bits
= current_vp
->bg_pattern
;
167 if (current_vp
->drawmode
& DRMODE_FG
)
170 bits
= current_vp
->fg_pattern
;
173 if (fillopt
== OPT_NONE
&& current_vp
->drawmode
!= DRMODE_COMPLEMENT
)
176 dst
= LCDADDR(x1
, y
);
181 memset16(dst
, bits
, width
);
185 memcpy(dst
, (void *)((long)dst
+ lcd_backdrop_offset
),
186 width
* sizeof(fb_data
));
189 case OPT_NONE
: /* DRMODE_COMPLEMENT */
190 dst_end
= dst
+ width
;
193 while (++dst
< dst_end
);
198 /* Draw a vertical line (optimised) */
199 void lcd_vline(int x
, int y1
, int y2
)
202 fb_data
*dst
, *dst_end
;
203 lcd_fastpixelfunc_type
*pfunc
= lcd_fastpixelfuncs
[current_vp
->drawmode
];
213 /******************** In viewport clipping **********************/
214 /* nothing to draw? */
215 if (((unsigned)x
>= (unsigned)current_vp
->width
) ||
216 (y1
>= current_vp
->height
) ||
222 if (y2
>= current_vp
->height
)
223 y2
= current_vp
->height
-1;
225 /* adjust for viewport */
230 #if defined(HAVE_VIEWPORT_CLIP)
231 /********************* Viewport on screen clipping ********************/
232 /* nothing to draw? */
233 if (( (unsigned) x
>= (unsigned)LCD_WIDTH
) || (y1
>= LCD_HEIGHT
)
240 if (y2
>= LCD_HEIGHT
)
244 dst
= LCDADDR(x
, y1
);
245 dst_end
= dst
+ (y2
- y1
) * LCD_WIDTH
;
252 while (dst
<= dst_end
);
255 /* Fill a rectangular area */
256 void lcd_fillrect(int x
, int y
, int width
, int height
)
259 enum fill_opt fillopt
= OPT_NONE
;
260 fb_data
*dst
, *dst_end
;
262 /******************** In viewport clipping **********************/
263 /* nothing to draw? */
264 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
) ||
265 (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
278 if (x
+ width
> current_vp
->width
)
279 width
= current_vp
->width
- x
;
280 if (y
+ height
> current_vp
->height
)
281 height
= current_vp
->height
- y
;
283 /* adjust for viewport */
287 #if defined(HAVE_VIEWPORT_CLIP)
288 /********************* Viewport on screen clipping ********************/
289 /* nothing to draw? */
290 if ((x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
291 || (x
+ width
<= 0) || (y
+ height
<= 0))
294 /* clip image in viewport in screen */
305 if (x
+ width
> LCD_WIDTH
)
306 width
= LCD_WIDTH
- x
;
307 if (y
+ height
> LCD_HEIGHT
)
308 height
= LCD_HEIGHT
- y
;
311 /* drawmode and optimisation */
312 if (current_vp
->drawmode
& DRMODE_INVERSEVID
)
314 if (current_vp
->drawmode
& DRMODE_BG
)
319 bits
= current_vp
->bg_pattern
;
327 if (current_vp
->drawmode
& DRMODE_FG
)
330 bits
= current_vp
->fg_pattern
;
333 if (fillopt
== OPT_NONE
&& current_vp
->drawmode
!= DRMODE_COMPLEMENT
)
337 dst_end
= dst
+ height
* LCD_WIDTH
;
341 fb_data
*dst_row
, *row_end
;
346 memset16(dst
, bits
, width
);
350 memcpy(dst
, (void *)((long)dst
+ lcd_backdrop_offset
),
351 width
* sizeof(fb_data
));
354 case OPT_NONE
: /* DRMODE_COMPLEMENT */
356 row_end
= dst_row
+ width
;
358 *dst_row
= ~(*dst_row
);
359 while (++dst_row
< row_end
);
364 while (dst
< dst_end
);
367 /* Draw a partial native bitmap */
368 void ICODE_ATTR
lcd_bitmap_part(const fb_data
*src
, int src_x
, int src_y
,
369 int stride
, int x
, int y
, int width
,
374 /******************** Image in viewport clipping **********************/
375 /* nothing to draw? */
376 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
) ||
377 (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
393 if (x
+ width
> current_vp
->width
)
394 width
= current_vp
->width
- x
;
395 if (y
+ height
> current_vp
->height
)
396 height
= current_vp
->height
- y
;
398 /* adjust for viewport */
402 #if defined(HAVE_VIEWPORT_CLIP)
403 /********************* Viewport on screen clipping ********************/
404 /* nothing to draw? */
405 if ((x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
406 || (x
+ width
<= 0) || (y
+ height
<= 0))
409 /* clip image in viewport in screen */
422 if (x
+ width
> LCD_WIDTH
)
423 width
= LCD_WIDTH
- x
;
424 if (y
+ height
> LCD_HEIGHT
)
425 height
= LCD_HEIGHT
- y
;
428 src
+= stride
* src_y
+ src_x
; /* move starting point */
433 memcpy(dst
, src
, width
* sizeof(fb_data
));
437 while (--height
> 0);
440 /* Draw a partial native bitmap with transparency and foreground colors */
441 void ICODE_ATTR
lcd_bitmap_transparent_part(const fb_data
*src
, int src_x
,
442 int src_y
, int stride
, int x
,
443 int y
, int width
, int height
)
446 unsigned fg
= current_vp
->fg_pattern
;
448 /******************** Image in viewport clipping **********************/
449 /* nothing to draw? */
450 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
) ||
451 (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
467 if (x
+ width
> current_vp
->width
)
468 width
= current_vp
->width
- x
;
469 if (y
+ height
> current_vp
->height
)
470 height
= current_vp
->height
- y
;
472 /* adjust for viewport */
476 #if defined(HAVE_VIEWPORT_CLIP)
477 /********************* Viewport on screen clipping ********************/
478 /* nothing to draw? */
479 if ((x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
480 || (x
+ width
<= 0) || (y
+ height
<= 0))
483 /* clip image in viewport in screen */
496 if (x
+ width
> LCD_WIDTH
)
497 width
= LCD_WIDTH
- x
;
498 if (y
+ height
> LCD_HEIGHT
)
499 height
= LCD_HEIGHT
- y
;
502 src
+= stride
* src_y
+ src_x
; /* move starting point */
510 "mov %[w], %[width] \n" /* Load width for inner loop */
512 "ldrh %[px], [%[s]], #2 \n" /* Load src pixel */
513 "add %[d], %[d], #2 \n" /* Uncoditionally increment dst */
514 /* done here for better pipelining */
515 "cmp %[px], %[fgcolor] \n" /* Compare to foreground color */
516 "streqh %[fgpat], [%[d], #-2] \n" /* Store foregroud if match */
517 "cmpne %[px], %[transcolor] \n" /* Compare to transparent color */
518 "strneh %[px], [%[d], #-2] \n" /* Store dst if not transparent */
519 "subs %[w], %[w], #1 \n" /* Width counter has run down? */
520 "bgt .nextpixel \n" /* More in this row? */
521 "add %[s], %[s], %[sstp], lsl #1 \n" /* Skip over to start of next line */
522 "add %[d], %[d], %[dstp], lsl #1 \n"
523 "subs %[h], %[h], #1 \n" /* Height counter has run down? */
524 "bgt .rowstart \n" /* More rows? */
525 : [w
]"=&r"(w
), [h
]"+&r"(height
), [px
]"=&r"(px
),
526 [s
]"+&r"(src
), [d
]"+&r"(dst
)
528 [sstp
]"r"(stride
- width
),
529 [dstp
]"r"(LCD_WIDTH
- width
),
530 [transcolor
]"r"(TRANSPARENT_COLOR
),
531 [fgcolor
]"r"(REPLACEWITHFG_COLOR
),
535 #else /* optimized C version */
538 const fb_data
*src_row
= src
;
539 fb_data
*dst_row
= dst
;
540 fb_data
*row_end
= dst_row
+ width
;
543 unsigned data
= *src_row
++;
544 if (data
!= TRANSPARENT_COLOR
)
546 if (data
== REPLACEWITHFG_COLOR
)
551 while (++dst_row
< row_end
);
555 while (--height
> 0);