Fix unused-but-set warnings in helper functions.
[maemo-rb.git] / firmware / drivers / lcd-16bit.c
blobf7d3cf22d44559c3394e0074f31924cf4709f317
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
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 LCD_WIDTH
42 #define COL_INC 1
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);
65 dst += LCD_WIDTH;
67 while (dst < dst_end);
69 else
71 if (!lcd_backdrop)
75 memset16(dst, current_vp->bg_pattern, current_vp->width);
76 dst += LCD_WIDTH;
78 while (dst < dst_end);
80 else
84 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
85 current_vp->width * sizeof(fb_data));
86 dst += LCD_WIDTH;
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, width;
106 unsigned bits = 0;
107 enum fill_opt fillopt = OPT_NONE;
108 fb_data *dst, *dst_end;
110 /* direction flip */
111 if (x2 < x1)
113 x = x1;
114 x1 = x2;
115 x2 = x;
118 /******************** In viewport clipping **********************/
119 /* nothing to draw? */
120 if (((unsigned)y >= (unsigned)current_vp->height) ||
121 (x1 >= current_vp->width) ||
122 (x2 < 0))
123 return;
125 if (x1 < 0)
126 x1 = 0;
127 if (x2 >= current_vp->width)
128 x2 = current_vp->width-1;
130 /* Adjust x1 and y to viewport */
131 x1 += current_vp->x;
132 x2 += current_vp->x;
133 y += current_vp->y;
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)
139 || (x2 < 0))
140 return;
142 /* clipping */
143 if (x1 < 0)
144 x1 = 0;
145 if (x2 >= LCD_WIDTH)
146 x2 = LCD_WIDTH-1;
147 #endif
149 width = x2 - x1 + 1;
151 /* drawmode and optimisation */
152 if (current_vp->drawmode & DRMODE_INVERSEVID)
154 if (current_vp->drawmode & DRMODE_BG)
156 if (!lcd_backdrop)
158 fillopt = OPT_SET;
159 bits = current_vp->bg_pattern;
161 else
162 fillopt = OPT_COPY;
165 else
167 if (current_vp->drawmode & DRMODE_FG)
169 fillopt = OPT_SET;
170 bits = current_vp->fg_pattern;
173 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT)
174 return;
176 dst = LCDADDR(x1, y);
178 switch (fillopt)
180 case OPT_SET:
181 memset16(dst, bits, width);
182 break;
184 case OPT_COPY:
185 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
186 width * sizeof(fb_data));
187 break;
189 case OPT_NONE: /* DRMODE_COMPLEMENT */
190 dst_end = dst + width;
192 *dst = ~(*dst);
193 while (++dst < dst_end);
194 break;
198 /* Draw a vertical line (optimised) */
199 void lcd_vline(int x, int y1, int y2)
201 int y;
202 fb_data *dst, *dst_end;
203 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode];
205 /* direction flip */
206 if (y2 < y1)
208 y = y1;
209 y1 = y2;
210 y2 = y;
213 /******************** In viewport clipping **********************/
214 /* nothing to draw? */
215 if (((unsigned)x >= (unsigned)current_vp->width) ||
216 (y1 >= current_vp->height) ||
217 (y2 < 0))
218 return;
220 if (y1 < 0)
221 y1 = 0;
222 if (y2 >= current_vp->height)
223 y2 = current_vp->height-1;
225 /* adjust for viewport */
226 x += current_vp->x;
227 y1 += current_vp->y;
228 y2 += current_vp->y;
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)
234 || (y2 < 0))
235 return;
237 /* clipping */
238 if (y1 < 0)
239 y1 = 0;
240 if (y2 >= LCD_HEIGHT)
241 y2 = LCD_HEIGHT-1;
242 #endif
244 dst = LCDADDR(x , y1);
245 dst_end = dst + (y2 - y1) * LCD_WIDTH;
249 pfunc(dst);
250 dst += LCD_WIDTH;
252 while (dst <= dst_end);
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 + height * LCD_WIDTH;
341 fb_data *dst_row, *row_end;
343 switch (fillopt)
345 case OPT_SET:
346 memset16(dst, bits, width);
347 break;
349 case OPT_COPY:
350 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
351 width * sizeof(fb_data));
352 break;
354 case OPT_NONE: /* DRMODE_COMPLEMENT */
355 dst_row = dst;
356 row_end = dst_row + width;
358 *dst_row = ~(*dst_row);
359 while (++dst_row < row_end);
360 break;
362 dst += LCD_WIDTH;
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_y + src_x; /* move starting point */
429 dst = LCDADDR(x, y);
433 memcpy(dst, src, width * sizeof(fb_data));
434 src += stride;
435 dst += LCD_WIDTH;
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)
445 fb_data *dst;
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))
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_y + src_x; /* move starting point */
503 dst = LCDADDR(x, y);
505 #ifdef CPU_ARM
507 int w, px;
508 asm volatile (
509 ".rowstart: \n"
510 "mov %[w], %[width] \n" /* Load width for inner loop */
511 ".nextpixel: \n"
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)
527 : [width]"r"(width),
528 [sstp]"r"(stride - width),
529 [dstp]"r"(LCD_WIDTH - width),
530 [transcolor]"r"(TRANSPARENT_COLOR),
531 [fgcolor]"r"(REPLACEWITHFG_COLOR),
532 [fgpat]"r"(fg)
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)
547 data = fg;
548 *dst_row = data;
551 while (++dst_row < row_end);
552 src += stride;
553 dst += LCD_WIDTH;
555 while (--height > 0);
556 #endif