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 #include "lcd-16bit-common.c"
45 #include "lcd-bitmap-common.c"
47 /*** drawing functions ***/
49 /* Clear the current viewport */
50 void lcd_clear_viewport(void)
52 fb_data
*dst
, *dst_end
;
54 dst
= FBADDR(current_vp
->x
, current_vp
->y
);
55 dst_end
= dst
+ current_vp
->height
* LCD_WIDTH
;
57 if (current_vp
->drawmode
& DRMODE_INVERSEVID
)
61 memset16(dst
, current_vp
->fg_pattern
, current_vp
->width
);
64 while (dst
< dst_end
);
72 memset16(dst
, current_vp
->bg_pattern
, current_vp
->width
);
75 while (dst
< dst_end
);
81 memcpy(dst
, (void *)((long)dst
+ lcd_backdrop_offset
),
82 current_vp
->width
* sizeof(fb_data
));
85 while (dst
< dst_end
);
89 if (current_vp
== &default_vp
)
91 lcd_scroll_info
.lines
= 0;
95 lcd_scroll_stop(current_vp
);
99 /* Draw a horizontal line (optimised) */
100 void lcd_hline(int x1
, int x2
, int y
)
104 enum fill_opt fillopt
= OPT_NONE
;
105 fb_data
*dst
, *dst_end
;
115 /******************** In viewport clipping **********************/
116 /* nothing to draw? */
117 if (((unsigned)y
>= (unsigned)current_vp
->height
) ||
118 (x1
>= current_vp
->width
) ||
124 if (x2
>= current_vp
->width
)
125 x2
= current_vp
->width
-1;
127 /* Adjust x1 and y to viewport */
132 #if defined(HAVE_VIEWPORT_CLIP)
133 /********************* Viewport on screen clipping ********************/
134 /* nothing to draw? */
135 if (((unsigned)y
>= (unsigned) LCD_HEIGHT
) || (x1
>= LCD_WIDTH
)
148 /* drawmode and optimisation */
149 if (current_vp
->drawmode
& DRMODE_INVERSEVID
)
151 if (current_vp
->drawmode
& DRMODE_BG
)
156 bits
= current_vp
->bg_pattern
;
164 if (current_vp
->drawmode
& DRMODE_FG
)
167 bits
= current_vp
->fg_pattern
;
170 if (fillopt
== OPT_NONE
&& current_vp
->drawmode
!= DRMODE_COMPLEMENT
)
178 memset16(dst
, bits
, width
);
182 memcpy(dst
, (void *)((long)dst
+ lcd_backdrop_offset
),
183 width
* sizeof(fb_data
));
186 case OPT_NONE
: /* DRMODE_COMPLEMENT */
187 dst_end
= dst
+ width
;
190 while (++dst
< dst_end
);
195 /* Draw a vertical line (optimised) */
196 void lcd_vline(int x
, int y1
, int y2
)
199 fb_data
*dst
, *dst_end
;
200 lcd_fastpixelfunc_type
*pfunc
= lcd_fastpixelfuncs
[current_vp
->drawmode
];
210 /******************** In viewport clipping **********************/
211 /* nothing to draw? */
212 if (((unsigned)x
>= (unsigned)current_vp
->width
) ||
213 (y1
>= current_vp
->height
) ||
219 if (y2
>= current_vp
->height
)
220 y2
= current_vp
->height
-1;
222 /* adjust for viewport */
227 #if defined(HAVE_VIEWPORT_CLIP)
228 /********************* Viewport on screen clipping ********************/
229 /* nothing to draw? */
230 if (( (unsigned) x
>= (unsigned)LCD_WIDTH
) || (y1
>= LCD_HEIGHT
)
237 if (y2
>= LCD_HEIGHT
)
241 dst
= FBADDR(x
, y1
);
242 dst_end
= dst
+ (y2
- y1
) * LCD_WIDTH
;
249 while (dst
<= dst_end
);
252 /* Fill a rectangular area */
253 void lcd_fillrect(int x
, int y
, int width
, int height
)
256 enum fill_opt fillopt
= OPT_NONE
;
257 fb_data
*dst
, *dst_end
;
259 /******************** In viewport clipping **********************/
260 /* nothing to draw? */
261 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
) ||
262 (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
275 if (x
+ width
> current_vp
->width
)
276 width
= current_vp
->width
- x
;
277 if (y
+ height
> current_vp
->height
)
278 height
= current_vp
->height
- y
;
280 /* adjust for viewport */
284 #if defined(HAVE_VIEWPORT_CLIP)
285 /********************* Viewport on screen clipping ********************/
286 /* nothing to draw? */
287 if ((x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
288 || (x
+ width
<= 0) || (y
+ height
<= 0))
291 /* clip image in viewport in screen */
302 if (x
+ width
> LCD_WIDTH
)
303 width
= LCD_WIDTH
- x
;
304 if (y
+ height
> LCD_HEIGHT
)
305 height
= LCD_HEIGHT
- y
;
308 /* drawmode and optimisation */
309 if (current_vp
->drawmode
& DRMODE_INVERSEVID
)
311 if (current_vp
->drawmode
& DRMODE_BG
)
316 bits
= current_vp
->bg_pattern
;
324 if (current_vp
->drawmode
& DRMODE_FG
)
327 bits
= current_vp
->fg_pattern
;
330 if (fillopt
== OPT_NONE
&& current_vp
->drawmode
!= DRMODE_COMPLEMENT
)
334 dst_end
= dst
+ height
* LCD_WIDTH
;
338 fb_data
*dst_row
, *row_end
;
343 memset16(dst
, bits
, width
);
347 memcpy(dst
, (void *)((long)dst
+ lcd_backdrop_offset
),
348 width
* sizeof(fb_data
));
351 case OPT_NONE
: /* DRMODE_COMPLEMENT */
353 row_end
= dst_row
+ width
;
355 *dst_row
= ~(*dst_row
);
356 while (++dst_row
< row_end
);
361 while (dst
< dst_end
);
364 /* Draw a partial native bitmap */
365 void ICODE_ATTR
lcd_bitmap_part(const fb_data
*src
, int src_x
, int src_y
,
366 int stride
, int x
, int y
, int width
,
371 /******************** Image in viewport clipping **********************/
372 /* nothing to draw? */
373 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
) ||
374 (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
390 if (x
+ width
> current_vp
->width
)
391 width
= current_vp
->width
- x
;
392 if (y
+ height
> current_vp
->height
)
393 height
= current_vp
->height
- y
;
395 /* adjust for viewport */
399 #if defined(HAVE_VIEWPORT_CLIP)
400 /********************* Viewport on screen clipping ********************/
401 /* nothing to draw? */
402 if ((x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
403 || (x
+ width
<= 0) || (y
+ height
<= 0))
406 /* clip image in viewport in screen */
419 if (x
+ width
> LCD_WIDTH
)
420 width
= LCD_WIDTH
- x
;
421 if (y
+ height
> LCD_HEIGHT
)
422 height
= LCD_HEIGHT
- y
;
425 src
+= stride
* src_y
+ src_x
; /* move starting point */
430 memcpy(dst
, src
, width
* sizeof(fb_data
));
434 while (--height
> 0);
437 /* Draw a partial native bitmap with transparency and foreground colors */
438 void ICODE_ATTR
lcd_bitmap_transparent_part(const fb_data
*src
, int src_x
,
439 int src_y
, int stride
, int x
,
440 int y
, int width
, int height
)
443 unsigned fg
= current_vp
->fg_pattern
;
445 /******************** Image in viewport clipping **********************/
446 /* nothing to draw? */
447 if ((width
<= 0) || (height
<= 0) || (x
>= current_vp
->width
) ||
448 (y
>= current_vp
->height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
464 if (x
+ width
> current_vp
->width
)
465 width
= current_vp
->width
- x
;
466 if (y
+ height
> current_vp
->height
)
467 height
= current_vp
->height
- y
;
469 /* adjust for viewport */
473 #if defined(HAVE_VIEWPORT_CLIP)
474 /********************* Viewport on screen clipping ********************/
475 /* nothing to draw? */
476 if ((x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
477 || (x
+ width
<= 0) || (y
+ height
<= 0))
480 /* clip image in viewport in screen */
493 if (x
+ width
> LCD_WIDTH
)
494 width
= LCD_WIDTH
- x
;
495 if (y
+ height
> LCD_HEIGHT
)
496 height
= LCD_HEIGHT
- y
;
499 src
+= stride
* src_y
+ src_x
; /* move starting point */
507 "mov %[w], %[width] \n" /* Load width for inner loop */
509 "ldrh %[px], [%[s]], #2 \n" /* Load src pixel */
510 "add %[d], %[d], #2 \n" /* Uncoditionally increment dst */
511 /* done here for better pipelining */
512 "cmp %[px], %[fgcolor] \n" /* Compare to foreground color */
513 "streqh %[fgpat], [%[d], #-2] \n" /* Store foregroud if match */
514 "cmpne %[px], %[transcolor] \n" /* Compare to transparent color */
515 "strneh %[px], [%[d], #-2] \n" /* Store dst if not transparent */
516 "subs %[w], %[w], #1 \n" /* Width counter has run down? */
517 "bgt .nextpixel \n" /* More in this row? */
518 "add %[s], %[s], %[sstp], lsl #1 \n" /* Skip over to start of next line */
519 "add %[d], %[d], %[dstp], lsl #1 \n"
520 "subs %[h], %[h], #1 \n" /* Height counter has run down? */
521 "bgt .rowstart \n" /* More rows? */
522 : [w
]"=&r"(w
), [h
]"+&r"(height
), [px
]"=&r"(px
),
523 [s
]"+&r"(src
), [d
]"+&r"(dst
)
525 [sstp
]"r"(stride
- width
),
526 [dstp
]"r"(LCD_WIDTH
- width
),
527 [transcolor
]"r"(TRANSPARENT_COLOR
),
528 [fgcolor
]"r"(REPLACEWITHFG_COLOR
),
532 #else /* optimized C version */
535 const fb_data
*src_row
= src
;
536 fb_data
*dst_row
= dst
;
537 fb_data
*row_end
= dst_row
+ width
;
540 unsigned data
= *src_row
++;
541 if (data
!= TRANSPARENT_COLOR
)
543 if (data
== REPLACEWITHFG_COLOR
)
548 while (++dst_row
< row_end
);
552 while (--height
> 0);