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 with vertical strides
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"
42 #define COL_INC LCD_HEIGHT
44 #define LCDADDR(x, y) (&lcd_framebuffer[0][0] + LCD_HEIGHT*(x) + (y))
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
->width
* LCD_HEIGHT
;
60 if (current_vp
->drawmode
& DRMODE_INVERSEVID
)
64 memset16(dst
, current_vp
->fg_pattern
, current_vp
->height
);
67 while (dst
< dst_end
);
75 memset16(dst
, current_vp
->bg_pattern
, current_vp
->height
);
78 while (dst
< dst_end
);
84 memcpy(dst
, (void *)((long)dst
+ lcd_backdrop_offset
),
85 current_vp
->height
* 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
)
106 fb_data
*dst
, *dst_end
;
107 lcd_fastpixelfunc_type
*pfunc
= lcd_fastpixelfuncs
[current_vp
->drawmode
];
117 /******************** In viewport clipping **********************/
118 /* nothing to draw? */
119 if (((unsigned)y
>= (unsigned)current_vp
->height
) ||
120 (x1
>= current_vp
->width
) ||
126 if (x2
>= current_vp
->width
)
127 x2
= current_vp
->width
-1;
129 /* Adjust x1 and y to viewport */
134 #if defined(HAVE_VIEWPORT_CLIP)
135 /********************* Viewport on screen clipping ********************/
136 /* nothing to draw? */
137 if (((unsigned)y
>= (unsigned) LCD_HEIGHT
) || (x1
>= LCD_WIDTH
)
148 dst
= LCDADDR(x1
, y
);
149 dst_end
= dst
+ (x2
- x1
) * LCD_HEIGHT
;
156 while (dst
<= dst_end
);
159 /* Draw a vertical line (optimised) */
160 void lcd_vline(int x
, int y1
, int y2
)
164 enum fill_opt fillopt
= OPT_NONE
;
165 fb_data
*dst
, *dst_end
;
175 /******************** In viewport clipping **********************/
176 /* nothing to draw? */
177 if (((unsigned)x
>= (unsigned)current_vp
->width
) ||
178 (y1
>= current_vp
->height
) ||
184 if (y2
>= current_vp
->height
)
185 y2
= current_vp
->height
-1;
187 /* adjust for viewport */
192 #if defined(HAVE_VIEWPORT_CLIP)
193 /********************* Viewport on screen clipping ********************/
194 /* nothing to draw? */
195 if (( (unsigned) x
>= (unsigned)LCD_WIDTH
) || (y1
>= LCD_HEIGHT
)
202 if (y2
>= LCD_HEIGHT
)
206 height
= y2
- y1
+ 1;
208 /* drawmode and optimisation */
209 if (current_vp
->drawmode
& DRMODE_INVERSEVID
)
211 if (current_vp
->drawmode
& DRMODE_BG
)
216 bits
= current_vp
->bg_pattern
;
224 if (current_vp
->drawmode
& DRMODE_FG
)
227 bits
= current_vp
->fg_pattern
;
230 if (fillopt
== OPT_NONE
&& current_vp
->drawmode
!= DRMODE_COMPLEMENT
)
233 dst
= LCDADDR(x
, y1
);
238 memset16(dst
, bits
, height
);
242 memcpy(dst
, (void *)((long)dst
+ lcd_backdrop_offset
),
243 height
* sizeof(fb_data
));
246 case OPT_NONE
: /* DRMODE_COMPLEMENT */
247 dst_end
= dst
+ height
;
250 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
+ width
* LCD_HEIGHT
;
341 fb_data
*dst_col
, *col_end
;
346 memset16(dst
, bits
, height
);
350 memcpy(dst
, (void *)((long)dst
+ lcd_backdrop_offset
),
351 height
* sizeof(fb_data
));
354 case OPT_NONE
: /* DRMODE_COMPLEMENT */
356 col_end
= dst_col
+ height
;
358 *dst_col
= ~(*dst_col
);
359 while (++dst_col
< col_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_x
+ src_y
; /* move starting point */
430 fb_data
*dst_end
= dst
+ width
* LCD_HEIGHT
;
434 memcpy(dst
, src
, height
* sizeof(fb_data
));
438 while (dst
< dst_end
);
441 /* Draw a partial native bitmap */
442 void ICODE_ATTR
lcd_bitmap_transparent_part(const fb_data
*src
, int src_x
,
443 int src_y
, int stride
, int x
,
444 int y
, int width
, int height
)
446 fb_data
*dst
, *dst_end
;
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_x
+ src_y
; /* move starting point */
504 dst_end
= dst
+ width
* LCD_HEIGHT
;
509 for(i
= 0;i
< height
;i
++)
511 if (src
[i
] == REPLACEWITHFG_COLOR
)
512 dst
[i
] = current_vp
->fg_pattern
;
513 else if(src
[i
] != TRANSPARENT_COLOR
)
519 while (dst
< dst_end
);