Implement a C version lcd-as-memframe.c and move it and the asm to firmware/asm.
[maemo-rb.git] / firmware / drivers / lcd-16bit-vert.c
blobf020d74757028cb5891ef31220f199b4098d4fe9
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
25 #include "config.h"
27 #include "cpu.h"
28 #include "lcd.h"
29 #include "kernel.h"
30 #include "thread.h"
31 #include <stdlib.h>
32 #include "string-extra.h" /* mem*() */
33 #include "file.h"
34 #include "debug.h"
35 #include "system.h"
36 #include "font.h"
37 #include "rbunicode.h"
38 #include "bidi.h"
39 #include "scroll_engine.h"
41 #define ROW_INC 1
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);
65 dst += LCD_HEIGHT;
67 while (dst < dst_end);
69 else
71 if (!lcd_backdrop)
75 memset16(dst, current_vp->bg_pattern, current_vp->height);
76 dst += LCD_HEIGHT;
78 while (dst < dst_end);
80 else
84 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
85 current_vp->height * sizeof(fb_data));
86 dst += LCD_HEIGHT;
88 while (dst < dst_end);
92 if (current_vp == &default_vp)
94 lcd_scroll_info.lines = 0;
96 else
98 lcd_scroll_stop(current_vp);
102 /* Draw a horizontal line (optimised) */
103 void lcd_hline(int x1, int x2, int y)
105 int x;
106 fb_data *dst, *dst_end;
107 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode];
109 /* direction flip */
110 if (x2 < x1)
112 x = x1;
113 x1 = x2;
114 x2 = x;
117 /******************** In viewport clipping **********************/
118 /* nothing to draw? */
119 if (((unsigned)y >= (unsigned)current_vp->height) ||
120 (x1 >= current_vp->width) ||
121 (x2 < 0))
122 return;
124 if (x1 < 0)
125 x1 = 0;
126 if (x2 >= current_vp->width)
127 x2 = current_vp->width-1;
129 /* Adjust x1 and y to viewport */
130 x1 += current_vp->x;
131 x2 += current_vp->x;
132 y += current_vp->y;
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)
138 || (x2 < 0))
139 return;
141 /* clipping */
142 if (x1 < 0)
143 x1 = 0;
144 if (x2 >= LCD_WIDTH)
145 x2 = LCD_WIDTH-1;
146 #endif
148 dst = LCDADDR(x1 , y );
149 dst_end = dst + (x2 - x1) * LCD_HEIGHT;
153 pfunc(dst);
154 dst += LCD_HEIGHT;
156 while (dst <= dst_end);
159 /* Draw a vertical line (optimised) */
160 void lcd_vline(int x, int y1, int y2)
162 int y, height;
163 unsigned bits = 0;
164 enum fill_opt fillopt = OPT_NONE;
165 fb_data *dst, *dst_end;
167 /* direction flip */
168 if (y2 < y1)
170 y = y1;
171 y1 = y2;
172 y2 = y;
175 /******************** In viewport clipping **********************/
176 /* nothing to draw? */
177 if (((unsigned)x >= (unsigned)current_vp->width) ||
178 (y1 >= current_vp->height) ||
179 (y2 < 0))
180 return;
182 if (y1 < 0)
183 y1 = 0;
184 if (y2 >= current_vp->height)
185 y2 = current_vp->height-1;
187 /* adjust for viewport */
188 x += current_vp->x;
189 y1 += current_vp->y;
190 y2 += current_vp->y;
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)
196 || (y2 < 0))
197 return;
199 /* clipping */
200 if (y1 < 0)
201 y1 = 0;
202 if (y2 >= LCD_HEIGHT)
203 y2 = LCD_HEIGHT-1;
204 #endif
206 height = y2 - y1 + 1;
208 /* drawmode and optimisation */
209 if (current_vp->drawmode & DRMODE_INVERSEVID)
211 if (current_vp->drawmode & DRMODE_BG)
213 if (!lcd_backdrop)
215 fillopt = OPT_SET;
216 bits = current_vp->bg_pattern;
218 else
219 fillopt = OPT_COPY;
222 else
224 if (current_vp->drawmode & DRMODE_FG)
226 fillopt = OPT_SET;
227 bits = current_vp->fg_pattern;
230 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT)
231 return;
233 dst = LCDADDR(x, y1);
235 switch (fillopt)
237 case OPT_SET:
238 memset16(dst, bits, height);
239 break;
241 case OPT_COPY:
242 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
243 height * sizeof(fb_data));
244 break;
246 case OPT_NONE: /* DRMODE_COMPLEMENT */
247 dst_end = dst + height;
249 *dst = ~(*dst);
250 while (++dst < dst_end);
251 break;
255 /* Fill a rectangular area */
256 void lcd_fillrect(int x, int y, int width, int height)
258 unsigned bits = 0;
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))
266 return;
268 if (x < 0)
270 width += x;
271 x = 0;
273 if (y < 0)
275 height += y;
276 y = 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 */
284 x += current_vp->x;
285 y += current_vp->y;
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))
292 return;
294 /* clip image in viewport in screen */
295 if (x < 0)
297 width += x;
298 x = 0;
300 if (y < 0)
302 height += y;
303 y = 0;
305 if (x + width > LCD_WIDTH)
306 width = LCD_WIDTH - x;
307 if (y + height > LCD_HEIGHT)
308 height = LCD_HEIGHT - y;
309 #endif
311 /* drawmode and optimisation */
312 if (current_vp->drawmode & DRMODE_INVERSEVID)
314 if (current_vp->drawmode & DRMODE_BG)
316 if (!lcd_backdrop)
318 fillopt = OPT_SET;
319 bits = current_vp->bg_pattern;
321 else
322 fillopt = OPT_COPY;
325 else
327 if (current_vp->drawmode & DRMODE_FG)
329 fillopt = OPT_SET;
330 bits = current_vp->fg_pattern;
333 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT)
334 return;
336 dst = LCDADDR(x, y);
337 dst_end = dst + width * LCD_HEIGHT;
341 fb_data *dst_col, *col_end;
343 switch (fillopt)
345 case OPT_SET:
346 memset16(dst, bits, height);
347 break;
349 case OPT_COPY:
350 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
351 height * sizeof(fb_data));
352 break;
354 case OPT_NONE: /* DRMODE_COMPLEMENT */
355 dst_col = dst;
356 col_end = dst_col + height;
358 *dst_col = ~(*dst_col);
359 while (++dst_col < col_end);
360 break;
362 dst+=LCD_HEIGHT;
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,
370 int height)
372 fb_data *dst;
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))
378 return;
380 if (x < 0)
382 width += x;
383 src_x -= x;
384 x = 0;
386 if (y < 0)
388 height += y;
389 src_y -= y;
390 y = 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 */
399 x += current_vp->x;
400 y += current_vp->y;
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))
407 return;
409 /* clip image in viewport in screen */
410 if (x < 0)
412 width += x;
413 src_x -= x;
414 x = 0;
416 if (y < 0)
418 height += y;
419 src_y -= y;
420 y = 0;
422 if (x + width > LCD_WIDTH)
423 width = LCD_WIDTH - x;
424 if (y + height > LCD_HEIGHT)
425 height = LCD_HEIGHT - y;
426 #endif
428 src += stride * src_x + src_y; /* move starting point */
429 dst = LCDADDR(x, y);
430 fb_data *dst_end = dst + width * LCD_HEIGHT;
434 memcpy(dst, src, height * sizeof(fb_data));
435 src += stride;
436 dst += LCD_HEIGHT;
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))
452 return;
454 if (x < 0)
456 width += x;
457 src_x -= x;
458 x = 0;
460 if (y < 0)
462 height += y;
463 src_y -= y;
464 y = 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 */
473 x += current_vp->x;
474 y += current_vp->y;
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))
481 return;
483 /* clip image in viewport in screen */
484 if (x < 0)
486 width += x;
487 src_x -= x;
488 x = 0;
490 if (y < 0)
492 height += y;
493 src_y -= y;
494 y = 0;
496 if (x + width > LCD_WIDTH)
497 width = LCD_WIDTH - x;
498 if (y + height > LCD_HEIGHT)
499 height = LCD_HEIGHT - y;
500 #endif
502 src += stride * src_x + src_y; /* move starting point */
503 dst = LCDADDR(x, y);
504 dst_end = dst + width * LCD_HEIGHT;
508 int i;
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)
514 dst[i] = src[i];
516 src += stride;
517 dst += LCD_HEIGHT;
519 while (dst < dst_end);