Make backup dialog modal.
[maemo-rb.git] / firmware / drivers / lcd-16bit.c
blob4d4166a38431aa553cf26726dc0e2551046f56f8
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 #include "lcd-16bit-common.c"
45 #include "lcd-bitmap-common.c"
47 /*** drawing functions ***/
49 /* Draw a horizontal line (optimised) */
50 void lcd_hline(int x1, int x2, int y)
52 int x, width;
53 unsigned bits = 0;
54 enum fill_opt fillopt = OPT_NONE;
55 fb_data *dst, *dst_end;
57 /* direction flip */
58 if (x2 < x1)
60 x = x1;
61 x1 = x2;
62 x2 = x;
65 /******************** In viewport clipping **********************/
66 /* nothing to draw? */
67 if (((unsigned)y >= (unsigned)current_vp->height) ||
68 (x1 >= current_vp->width) ||
69 (x2 < 0))
70 return;
72 if (x1 < 0)
73 x1 = 0;
74 if (x2 >= current_vp->width)
75 x2 = current_vp->width-1;
77 /* Adjust x1 and y to viewport */
78 x1 += current_vp->x;
79 x2 += current_vp->x;
80 y += current_vp->y;
82 #if defined(HAVE_VIEWPORT_CLIP)
83 /********************* Viewport on screen clipping ********************/
84 /* nothing to draw? */
85 if (((unsigned)y >= (unsigned) LCD_HEIGHT) || (x1 >= LCD_WIDTH)
86 || (x2 < 0))
87 return;
89 /* clipping */
90 if (x1 < 0)
91 x1 = 0;
92 if (x2 >= LCD_WIDTH)
93 x2 = LCD_WIDTH-1;
94 #endif
96 width = x2 - x1 + 1;
98 /* drawmode and optimisation */
99 if (current_vp->drawmode & DRMODE_INVERSEVID)
101 if (current_vp->drawmode & DRMODE_BG)
103 if (!lcd_backdrop)
105 fillopt = OPT_SET;
106 bits = current_vp->bg_pattern;
108 else
109 fillopt = OPT_COPY;
112 else
114 if (current_vp->drawmode & DRMODE_FG)
116 fillopt = OPT_SET;
117 bits = current_vp->fg_pattern;
120 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT)
121 return;
123 dst = FBADDR(x1, y);
125 switch (fillopt)
127 case OPT_SET:
128 memset16(dst, bits, width);
129 break;
131 case OPT_COPY:
132 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
133 width * sizeof(fb_data));
134 break;
136 case OPT_NONE: /* DRMODE_COMPLEMENT */
137 dst_end = dst + width;
139 *dst = ~(*dst);
140 while (++dst < dst_end);
141 break;
145 /* Draw a vertical line (optimised) */
146 void lcd_vline(int x, int y1, int y2)
148 int y;
149 fb_data *dst, *dst_end;
150 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode];
152 /* direction flip */
153 if (y2 < y1)
155 y = y1;
156 y1 = y2;
157 y2 = y;
160 /******************** In viewport clipping **********************/
161 /* nothing to draw? */
162 if (((unsigned)x >= (unsigned)current_vp->width) ||
163 (y1 >= current_vp->height) ||
164 (y2 < 0))
165 return;
167 if (y1 < 0)
168 y1 = 0;
169 if (y2 >= current_vp->height)
170 y2 = current_vp->height-1;
172 /* adjust for viewport */
173 x += current_vp->x;
174 y1 += current_vp->y;
175 y2 += current_vp->y;
177 #if defined(HAVE_VIEWPORT_CLIP)
178 /********************* Viewport on screen clipping ********************/
179 /* nothing to draw? */
180 if (( (unsigned) x >= (unsigned)LCD_WIDTH) || (y1 >= LCD_HEIGHT)
181 || (y2 < 0))
182 return;
184 /* clipping */
185 if (y1 < 0)
186 y1 = 0;
187 if (y2 >= LCD_HEIGHT)
188 y2 = LCD_HEIGHT-1;
189 #endif
191 dst = FBADDR(x , y1);
192 dst_end = dst + (y2 - y1) * LCD_WIDTH;
196 pfunc(dst);
197 dst += LCD_WIDTH;
199 while (dst <= dst_end);
202 /* Draw a partial native bitmap */
203 void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
204 int stride, int x, int y, int width,
205 int height)
207 fb_data *dst;
209 /******************** Image in viewport clipping **********************/
210 /* nothing to draw? */
211 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
212 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
213 return;
215 if (x < 0)
217 width += x;
218 src_x -= x;
219 x = 0;
221 if (y < 0)
223 height += y;
224 src_y -= y;
225 y = 0;
228 if (x + width > current_vp->width)
229 width = current_vp->width - x;
230 if (y + height > current_vp->height)
231 height = current_vp->height - y;
233 /* adjust for viewport */
234 x += current_vp->x;
235 y += current_vp->y;
237 #if defined(HAVE_VIEWPORT_CLIP)
238 /********************* Viewport on screen clipping ********************/
239 /* nothing to draw? */
240 if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
241 || (x + width <= 0) || (y + height <= 0))
242 return;
244 /* clip image in viewport in screen */
245 if (x < 0)
247 width += x;
248 src_x -= x;
249 x = 0;
251 if (y < 0)
253 height += y;
254 src_y -= y;
255 y = 0;
257 if (x + width > LCD_WIDTH)
258 width = LCD_WIDTH - x;
259 if (y + height > LCD_HEIGHT)
260 height = LCD_HEIGHT - y;
261 #endif
263 src += stride * src_y + src_x; /* move starting point */
264 dst = FBADDR(x, y);
268 memcpy(dst, src, width * sizeof(fb_data));
269 src += stride;
270 dst += LCD_WIDTH;
272 while (--height > 0);
275 /* Draw a partial native bitmap with transparency and foreground colors */
276 void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
277 int src_y, int stride, int x,
278 int y, int width, int height)
280 fb_data *dst;
281 unsigned fg = current_vp->fg_pattern;
283 /******************** Image in viewport clipping **********************/
284 /* nothing to draw? */
285 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
286 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
287 return;
289 if (x < 0)
291 width += x;
292 src_x -= x;
293 x = 0;
295 if (y < 0)
297 height += y;
298 src_y -= y;
299 y = 0;
302 if (x + width > current_vp->width)
303 width = current_vp->width - x;
304 if (y + height > current_vp->height)
305 height = current_vp->height - y;
307 /* adjust for viewport */
308 x += current_vp->x;
309 y += current_vp->y;
311 #if defined(HAVE_VIEWPORT_CLIP)
312 /********************* Viewport on screen clipping ********************/
313 /* nothing to draw? */
314 if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
315 || (x + width <= 0) || (y + height <= 0))
316 return;
318 /* clip image in viewport in screen */
319 if (x < 0)
321 width += x;
322 src_x -= x;
323 x = 0;
325 if (y < 0)
327 height += y;
328 src_y -= y;
329 y = 0;
331 if (x + width > LCD_WIDTH)
332 width = LCD_WIDTH - x;
333 if (y + height > LCD_HEIGHT)
334 height = LCD_HEIGHT - y;
335 #endif
337 src += stride * src_y + src_x; /* move starting point */
338 dst = FBADDR(x, y);
340 #ifdef CPU_ARM
342 int w, px;
343 asm volatile (
344 ".rowstart: \n"
345 "mov %[w], %[width] \n" /* Load width for inner loop */
346 ".nextpixel: \n"
347 "ldrh %[px], [%[s]], #2 \n" /* Load src pixel */
348 "add %[d], %[d], #2 \n" /* Uncoditionally increment dst */
349 /* done here for better pipelining */
350 "cmp %[px], %[fgcolor] \n" /* Compare to foreground color */
351 "streqh %[fgpat], [%[d], #-2] \n" /* Store foregroud if match */
352 "cmpne %[px], %[transcolor] \n" /* Compare to transparent color */
353 "strneh %[px], [%[d], #-2] \n" /* Store dst if not transparent */
354 "subs %[w], %[w], #1 \n" /* Width counter has run down? */
355 "bgt .nextpixel \n" /* More in this row? */
356 "add %[s], %[s], %[sstp], lsl #1 \n" /* Skip over to start of next line */
357 "add %[d], %[d], %[dstp], lsl #1 \n"
358 "subs %[h], %[h], #1 \n" /* Height counter has run down? */
359 "bgt .rowstart \n" /* More rows? */
360 : [w]"=&r"(w), [h]"+&r"(height), [px]"=&r"(px),
361 [s]"+&r"(src), [d]"+&r"(dst)
362 : [width]"r"(width),
363 [sstp]"r"(stride - width),
364 [dstp]"r"(LCD_WIDTH - width),
365 [transcolor]"r"(TRANSPARENT_COLOR),
366 [fgcolor]"r"(REPLACEWITHFG_COLOR),
367 [fgpat]"r"(fg)
370 #else /* optimized C version */
373 const fb_data *src_row = src;
374 fb_data *dst_row = dst;
375 fb_data *row_end = dst_row + width;
378 unsigned data = *src_row++;
379 if (data != TRANSPARENT_COLOR)
381 if (data == REPLACEWITHFG_COLOR)
382 data = fg;
383 *dst_row = data;
386 while (++dst_row < row_end);
387 src += stride;
388 dst += LCD_WIDTH;
390 while (--height > 0);
391 #endif