diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/SOURCES | 2 | ||||
-rw-r--r-- | firmware/asm/SOURCES | 4 | ||||
-rw-r--r-- | firmware/asm/lcd-as-memframe-24bit.c | 3 | ||||
-rw-r--r-- | firmware/asm/lcd-as-memframe.c | 8 | ||||
-rw-r--r-- | firmware/drivers/lcd-24bit.c | 1129 | ||||
-rw-r--r-- | firmware/drivers/lcd-color-common.c | 8 | ||||
-rw-r--r-- | firmware/export/config.h | 1 | ||||
-rw-r--r-- | firmware/export/config/samsungypr0.h | 2 | ||||
-rw-r--r-- | firmware/export/config/samsungypr1.h | 4 | ||||
-rw-r--r-- | firmware/export/config/sansae200v2.h | 4 | ||||
-rw-r--r-- | firmware/export/config/sdlapp.h | 4 | ||||
-rw-r--r-- | firmware/export/lcd.h | 85 | ||||
-rw-r--r-- | firmware/screendump.c | 14 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/lcd-bitmap.c | 4 |
14 files changed, 1255 insertions, 17 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index ef71a2b048..b8471dc37d 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -218,6 +218,8 @@ drivers/lcd-16bit-vert.c | |||
218 | #else | 218 | #else |
219 | drivers/lcd-16bit.c | 219 | drivers/lcd-16bit.c |
220 | #endif | 220 | #endif |
221 | #elif LCD_DEPTH == 24 | ||
222 | drivers/lcd-24bit.c | ||
221 | #endif /* LCD_DEPTH */ | 223 | #endif /* LCD_DEPTH */ |
222 | common/diacritic.c | 224 | common/diacritic.c |
223 | #endif /* HAVE_LCD_BITMAP */ | 225 | #endif /* HAVE_LCD_BITMAP */ |
diff --git a/firmware/asm/SOURCES b/firmware/asm/SOURCES index 0cd351efdd..d74d4d3c60 100644 --- a/firmware/asm/SOURCES +++ b/firmware/asm/SOURCES | |||
@@ -12,5 +12,9 @@ strlen.c | |||
12 | defined(COWON_D2) || defined(MINI2440) || defined(SAMSUNG_YPR0) || \ | 12 | defined(COWON_D2) || defined(MINI2440) || defined(SAMSUNG_YPR0) || \ |
13 | defined(SAMSUNG_YPR1) || (defined(MROBE_500) && !defined(LCD_USE_DMA))) && \ | 13 | defined(SAMSUNG_YPR1) || (defined(MROBE_500) && !defined(LCD_USE_DMA))) && \ |
14 | !defined(SIMULATOR) | 14 | !defined(SIMULATOR) |
15 | #if LCD_DEPTH == 24 | ||
16 | lcd-as-memframe-24bit.c | ||
17 | #else | ||
15 | lcd-as-memframe.c | 18 | lcd-as-memframe.c |
16 | #endif | 19 | #endif |
20 | #endif | ||
diff --git a/firmware/asm/lcd-as-memframe-24bit.c b/firmware/asm/lcd-as-memframe-24bit.c new file mode 100644 index 0000000000..2cca575799 --- /dev/null +++ b/firmware/asm/lcd-as-memframe-24bit.c | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* The ASM version of lcd-as-memframe.c isn't 24bit capable */ | ||
3 | #include "lcd-as-memframe.c" | ||
diff --git a/firmware/asm/lcd-as-memframe.c b/firmware/asm/lcd-as-memframe.c index 5f4917b721..032022d7ec 100644 --- a/firmware/asm/lcd-as-memframe.c +++ b/firmware/asm/lcd-as-memframe.c | |||
@@ -78,7 +78,7 @@ extern void lcd_write_yuv420_lines(fb_data *dst, | |||
78 | b = clamp(b, 0, 64*256-1); | 78 | b = clamp(b, 0, 64*256-1); |
79 | } | 79 | } |
80 | 80 | ||
81 | *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); | 81 | *dst = FB_RGBPACK(r >> 6, g >> 6, b >> 6); |
82 | 82 | ||
83 | #if LCD_WIDTH >= LCD_HEIGHT | 83 | #if LCD_WIDTH >= LCD_HEIGHT |
84 | dst++; | 84 | dst++; |
@@ -98,7 +98,7 @@ extern void lcd_write_yuv420_lines(fb_data *dst, | |||
98 | b = clamp(b, 0, 64*256-1); | 98 | b = clamp(b, 0, 64*256-1); |
99 | } | 99 | } |
100 | 100 | ||
101 | *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); | 101 | *dst = FB_RGBPACK(r >> 6, g >> 6, b >> 6); |
102 | 102 | ||
103 | #if LCD_WIDTH >= LCD_HEIGHT | 103 | #if LCD_WIDTH >= LCD_HEIGHT |
104 | dst++; | 104 | dst++; |
@@ -143,7 +143,7 @@ extern void lcd_write_yuv420_lines(fb_data *dst, | |||
143 | b = clamp(b, 0, 64*256-1); | 143 | b = clamp(b, 0, 64*256-1); |
144 | } | 144 | } |
145 | 145 | ||
146 | *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); | 146 | *dst = FB_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); |
147 | 147 | ||
148 | #if LCD_WIDTH >= LCD_HEIGHT | 148 | #if LCD_WIDTH >= LCD_HEIGHT |
149 | dst++; | 149 | dst++; |
@@ -163,7 +163,7 @@ extern void lcd_write_yuv420_lines(fb_data *dst, | |||
163 | b = clamp(b, 0, 64*256-1); | 163 | b = clamp(b, 0, 64*256-1); |
164 | } | 164 | } |
165 | 165 | ||
166 | *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); | 166 | *dst = FB_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); |
167 | 167 | ||
168 | #if LCD_WIDTH >= LCD_HEIGHT | 168 | #if LCD_WIDTH >= LCD_HEIGHT |
169 | dst++; | 169 | dst++; |
diff --git a/firmware/drivers/lcd-24bit.c b/firmware/drivers/lcd-24bit.c new file mode 100644 index 0000000000..f87d63aaa3 --- /dev/null +++ b/firmware/drivers/lcd-24bit.c | |||
@@ -0,0 +1,1129 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 by Dave Chapman | ||
11 | * Copyright (C) 2009 by Karl Kurbjun | ||
12 | * | ||
13 | * Rockbox driver for 16-bit colour LCDs | ||
14 | * | ||
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. | ||
19 | * | ||
20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
21 | * KIND, either express or implied. | ||
22 | * | ||
23 | ****************************************************************************/ | ||
24 | |||
25 | #include <stdio.h> | ||
26 | #include "config.h" | ||
27 | |||
28 | #include "cpu.h" | ||
29 | #include "lcd.h" | ||
30 | #include "kernel.h" | ||
31 | #include "thread.h" | ||
32 | #include <stdlib.h> | ||
33 | #include "string-extra.h" /* mem*() */ | ||
34 | #include "file.h" | ||
35 | #include "debug.h" | ||
36 | #include "system.h" | ||
37 | #include "font.h" | ||
38 | #include "rbunicode.h" | ||
39 | #include "bidi.h" | ||
40 | #include "scroll_engine.h" | ||
41 | |||
42 | #define ROW_INC LCD_WIDTH | ||
43 | #define COL_INC 1 | ||
44 | |||
45 | extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[]; | ||
46 | extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_bgcolor[]; | ||
47 | |||
48 | static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | ||
49 | const unsigned char *src, int src_x, | ||
50 | int src_y, int x, int y, | ||
51 | int width, int height, | ||
52 | int stride_image, int stride_src); | ||
53 | |||
54 | #include "lcd-color-common.c" | ||
55 | #include "lcd-bitmap-common.c" | ||
56 | |||
57 | |||
58 | /* Clear the current viewport */ | ||
59 | void lcd_clear_viewport(void) | ||
60 | { | ||
61 | fb_data *dst, *dst_end; | ||
62 | int x, y, width, height; | ||
63 | int len, step; | ||
64 | |||
65 | x = current_vp->x; | ||
66 | y = current_vp->y; | ||
67 | width = current_vp->width; | ||
68 | height = current_vp->height; | ||
69 | |||
70 | #if defined(HAVE_VIEWPORT_CLIP) | ||
71 | /********************* Viewport on screen clipping ********************/ | ||
72 | /* nothing to draw? */ | ||
73 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
74 | || (x + width <= 0) || (y + height <= 0)) | ||
75 | return; | ||
76 | |||
77 | /* clip image in viewport in screen */ | ||
78 | if (x < 0) | ||
79 | { | ||
80 | width += x; | ||
81 | x = 0; | ||
82 | } | ||
83 | if (y < 0) | ||
84 | { | ||
85 | height += y; | ||
86 | y = 0; | ||
87 | } | ||
88 | if (x + width > LCD_WIDTH) | ||
89 | width = LCD_WIDTH - x; | ||
90 | if (y + height > LCD_HEIGHT) | ||
91 | height = LCD_HEIGHT - y; | ||
92 | #endif | ||
93 | |||
94 | len = STRIDE_MAIN(width, height); | ||
95 | step = STRIDE_MAIN(ROW_INC, COL_INC); | ||
96 | |||
97 | dst = FBADDR(x, y); | ||
98 | dst_end = FBADDR(x + width - 1 , y + height - 1); | ||
99 | |||
100 | if (current_vp->drawmode & DRMODE_INVERSEVID) | ||
101 | { | ||
102 | fb_data px = FB_SCALARPACK(current_vp->fg_pattern); | ||
103 | do | ||
104 | { | ||
105 | fb_data *end = dst + len; | ||
106 | do { | ||
107 | *dst++ = px; | ||
108 | } while (dst < end); | ||
109 | dst += step - len; | ||
110 | } | ||
111 | while (dst <= dst_end); | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | if (!lcd_backdrop) | ||
116 | { | ||
117 | fb_data px = FB_SCALARPACK(current_vp->bg_pattern); | ||
118 | do | ||
119 | { | ||
120 | fb_data *end = dst + len; | ||
121 | do { | ||
122 | *dst++ = px; | ||
123 | } while (dst < end); | ||
124 | dst += step - len; | ||
125 | } | ||
126 | while (dst <= dst_end); | ||
127 | } | ||
128 | else | ||
129 | { | ||
130 | do | ||
131 | { | ||
132 | memcpy(dst, (void *)((long)dst + lcd_backdrop_offset), | ||
133 | len * sizeof(fb_data)); | ||
134 | dst += step; | ||
135 | } | ||
136 | while (dst <= dst_end); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | if (current_vp == &default_vp) | ||
141 | lcd_scroll_stop(); | ||
142 | else | ||
143 | lcd_scroll_stop_viewport(current_vp); | ||
144 | } | ||
145 | |||
146 | /*** low-level drawing functions ***/ | ||
147 | |||
148 | static void ICODE_ATTR setpixel(fb_data *address) | ||
149 | { | ||
150 | *address = FB_SCALARPACK(current_vp->fg_pattern); | ||
151 | } | ||
152 | |||
153 | static void ICODE_ATTR clearpixel(fb_data *address) | ||
154 | { | ||
155 | *address = FB_SCALARPACK(current_vp->bg_pattern); | ||
156 | } | ||
157 | |||
158 | static void ICODE_ATTR clearimgpixel(fb_data *address) | ||
159 | { | ||
160 | *address = *(fb_data *)((long)address + lcd_backdrop_offset); | ||
161 | } | ||
162 | |||
163 | static void ICODE_ATTR flippixel(fb_data *address) | ||
164 | { | ||
165 | unsigned px = FB_UNPACK_SCALAR_LCD(*address); | ||
166 | *address = FB_SCALARPACK(~px); | ||
167 | } | ||
168 | |||
169 | static void ICODE_ATTR nopixel(fb_data *address) | ||
170 | { | ||
171 | (void)address; | ||
172 | } | ||
173 | |||
174 | lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_bgcolor[8] = { | ||
175 | flippixel, nopixel, setpixel, setpixel, | ||
176 | nopixel, clearpixel, nopixel, clearpixel | ||
177 | }; | ||
178 | |||
179 | lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[8] = { | ||
180 | flippixel, nopixel, setpixel, setpixel, | ||
181 | nopixel, clearimgpixel, nopixel, clearimgpixel | ||
182 | }; | ||
183 | |||
184 | lcd_fastpixelfunc_type* const * lcd_fastpixelfuncs = lcd_fastpixelfuncs_bgcolor; | ||
185 | |||
186 | /* Fill a rectangular area */ | ||
187 | void lcd_fillrect(int x, int y, int width, int height) | ||
188 | { | ||
189 | enum fill_opt fillopt = OPT_NONE; | ||
190 | fb_data *dst, *dst_end; | ||
191 | int len, step; | ||
192 | fb_data bits = { 0 }; | ||
193 | |||
194 | /******************** In viewport clipping **********************/ | ||
195 | /* nothing to draw? */ | ||
196 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | ||
197 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | ||
198 | return; | ||
199 | |||
200 | if (x < 0) | ||
201 | { | ||
202 | width += x; | ||
203 | x = 0; | ||
204 | } | ||
205 | if (y < 0) | ||
206 | { | ||
207 | height += y; | ||
208 | y = 0; | ||
209 | } | ||
210 | if (x + width > current_vp->width) | ||
211 | width = current_vp->width - x; | ||
212 | if (y + height > current_vp->height) | ||
213 | height = current_vp->height - y; | ||
214 | |||
215 | /* adjust for viewport */ | ||
216 | x += current_vp->x; | ||
217 | y += current_vp->y; | ||
218 | |||
219 | #if defined(HAVE_VIEWPORT_CLIP) | ||
220 | /********************* Viewport on screen clipping ********************/ | ||
221 | /* nothing to draw? */ | ||
222 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
223 | || (x + width <= 0) || (y + height <= 0)) | ||
224 | return; | ||
225 | |||
226 | /* clip image in viewport in screen */ | ||
227 | if (x < 0) | ||
228 | { | ||
229 | width += x; | ||
230 | x = 0; | ||
231 | } | ||
232 | if (y < 0) | ||
233 | { | ||
234 | height += y; | ||
235 | y = 0; | ||
236 | } | ||
237 | if (x + width > LCD_WIDTH) | ||
238 | width = LCD_WIDTH - x; | ||
239 | if (y + height > LCD_HEIGHT) | ||
240 | height = LCD_HEIGHT - y; | ||
241 | #endif | ||
242 | |||
243 | /* drawmode and optimisation */ | ||
244 | if (current_vp->drawmode & DRMODE_INVERSEVID) | ||
245 | { | ||
246 | if (current_vp->drawmode & DRMODE_BG) | ||
247 | { | ||
248 | if (!lcd_backdrop) | ||
249 | { | ||
250 | fillopt = OPT_SET; | ||
251 | bits = FB_SCALARPACK(current_vp->bg_pattern); | ||
252 | } | ||
253 | else | ||
254 | fillopt = OPT_COPY; | ||
255 | } | ||
256 | } | ||
257 | else | ||
258 | { | ||
259 | if (current_vp->drawmode & DRMODE_FG) | ||
260 | { | ||
261 | fillopt = OPT_SET; | ||
262 | bits = FB_SCALARPACK(current_vp->fg_pattern); | ||
263 | } | ||
264 | } | ||
265 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) | ||
266 | return; | ||
267 | |||
268 | dst = FBADDR(x, y); | ||
269 | dst_end = FBADDR(x + width - 1, y + height - 1); | ||
270 | |||
271 | len = STRIDE_MAIN(width, height); | ||
272 | step = STRIDE_MAIN(ROW_INC, COL_INC); | ||
273 | |||
274 | do | ||
275 | { | ||
276 | switch (fillopt) | ||
277 | { | ||
278 | case OPT_SET: | ||
279 | { | ||
280 | fb_data *start = dst; | ||
281 | fb_data *end = start + len; | ||
282 | do { | ||
283 | *start = bits; | ||
284 | } while (++start < end); | ||
285 | break; | ||
286 | } | ||
287 | |||
288 | case OPT_COPY: | ||
289 | memcpy(dst, (void *)((long)dst + lcd_backdrop_offset), | ||
290 | len * sizeof(fb_data)); | ||
291 | break; | ||
292 | |||
293 | case OPT_NONE: /* DRMODE_COMPLEMENT */ | ||
294 | { | ||
295 | fb_data *start = dst; | ||
296 | fb_data *end = start + len; | ||
297 | do { | ||
298 | flippixel(start); | ||
299 | } while (++start < end); | ||
300 | break; | ||
301 | } | ||
302 | } | ||
303 | dst += step; | ||
304 | } | ||
305 | while (dst <= dst_end); | ||
306 | } | ||
307 | |||
308 | /* About Rockbox' internal monochrome bitmap format: | ||
309 | * | ||
310 | * A bitmap contains one bit for every pixel that defines if that pixel is | ||
311 | * black (1) or white (0). Bits within a byte are arranged vertically, LSB | ||
312 | * at top. | ||
313 | * The bytes are stored in row-major order, with byte 0 being top left, | ||
314 | * byte 1 2nd from left etc. The first row of bytes defines pixel rows | ||
315 | * 0..7, the second row defines pixel row 8..15 etc. | ||
316 | * | ||
317 | * This is the mono bitmap format used on all other targets so far; the | ||
318 | * pixel packing doesn't really matter on a 8bit+ target. */ | ||
319 | |||
320 | /* Draw a partial monochrome bitmap */ | ||
321 | |||
322 | void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | ||
323 | int src_y, int stride, int x, int y, | ||
324 | int width, int height) | ||
325 | { | ||
326 | const unsigned char *src_end; | ||
327 | fb_data *dst, *dst_col; | ||
328 | unsigned dmask = 0x100; /* bit 8 == sentinel */ | ||
329 | int drmode = current_vp->drawmode; | ||
330 | int row; | ||
331 | |||
332 | /******************** Image in viewport clipping **********************/ | ||
333 | /* nothing to draw? */ | ||
334 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | ||
335 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | ||
336 | return; | ||
337 | |||
338 | if (x < 0) | ||
339 | { | ||
340 | width += x; | ||
341 | src_x -= x; | ||
342 | x = 0; | ||
343 | } | ||
344 | if (y < 0) | ||
345 | { | ||
346 | height += y; | ||
347 | src_y -= y; | ||
348 | y = 0; | ||
349 | } | ||
350 | if (x + width > current_vp->width) | ||
351 | width = current_vp->width - x; | ||
352 | if (y + height > current_vp->height) | ||
353 | height = current_vp->height - y; | ||
354 | |||
355 | /* adjust for viewport */ | ||
356 | x += current_vp->x; | ||
357 | y += current_vp->y; | ||
358 | |||
359 | #if defined(HAVE_VIEWPORT_CLIP) | ||
360 | /********************* Viewport on screen clipping ********************/ | ||
361 | /* nothing to draw? */ | ||
362 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
363 | || (x + width <= 0) || (y + height <= 0)) | ||
364 | return; | ||
365 | |||
366 | /* clip image in viewport in screen */ | ||
367 | if (x < 0) | ||
368 | { | ||
369 | width += x; | ||
370 | src_x -= x; | ||
371 | x = 0; | ||
372 | } | ||
373 | if (y < 0) | ||
374 | { | ||
375 | height += y; | ||
376 | src_y -= y; | ||
377 | y = 0; | ||
378 | } | ||
379 | if (x + width > LCD_WIDTH) | ||
380 | width = LCD_WIDTH - x; | ||
381 | if (y + height > LCD_HEIGHT) | ||
382 | height = LCD_HEIGHT - y; | ||
383 | #endif | ||
384 | |||
385 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | ||
386 | src_y &= 7; | ||
387 | src_end = src + width; | ||
388 | dst_col = FBADDR(x, y); | ||
389 | |||
390 | |||
391 | if (drmode & DRMODE_INVERSEVID) | ||
392 | { | ||
393 | dmask = 0x1ff; /* bit 8 == sentinel */ | ||
394 | drmode &= DRMODE_SOLID; /* mask out inversevid */ | ||
395 | } | ||
396 | |||
397 | /* Use extra bit to avoid if () in the switch-cases below */ | ||
398 | if ((drmode & DRMODE_BG) && lcd_backdrop) | ||
399 | drmode |= DRMODE_INT_BD; | ||
400 | |||
401 | /* go through each column and update each pixel */ | ||
402 | do | ||
403 | { | ||
404 | const unsigned char *src_col = src++; | ||
405 | unsigned data = (*src_col ^ dmask) >> src_y; | ||
406 | fb_data fg, bg; | ||
407 | uintptr_t bo; | ||
408 | |||
409 | dst = dst_col; | ||
410 | dst_col += COL_INC; | ||
411 | row = height; | ||
412 | |||
413 | #define UPDATE_SRC do { \ | ||
414 | data >>= 1; \ | ||
415 | if (data == 0x001) { \ | ||
416 | src_col += stride; \ | ||
417 | data = *src_col ^ dmask; \ | ||
418 | } \ | ||
419 | } while (0) | ||
420 | |||
421 | switch (drmode) | ||
422 | { | ||
423 | case DRMODE_COMPLEMENT: | ||
424 | do | ||
425 | { | ||
426 | if (data & 0x01) | ||
427 | flippixel(dst); | ||
428 | |||
429 | dst += ROW_INC; | ||
430 | UPDATE_SRC; | ||
431 | } | ||
432 | while (--row); | ||
433 | break; | ||
434 | |||
435 | case DRMODE_BG|DRMODE_INT_BD: | ||
436 | bo = lcd_backdrop_offset; | ||
437 | do | ||
438 | { | ||
439 | if (!(data & 0x01)) | ||
440 | *dst = *(fb_data *)((long)dst + bo); | ||
441 | |||
442 | dst += ROW_INC; | ||
443 | UPDATE_SRC; | ||
444 | } | ||
445 | while (--row); | ||
446 | break; | ||
447 | |||
448 | case DRMODE_BG: | ||
449 | bg = FB_SCALARPACK(current_vp->bg_pattern); | ||
450 | do | ||
451 | { | ||
452 | if (!(data & 0x01)) | ||
453 | *dst = bg; | ||
454 | |||
455 | dst += ROW_INC; | ||
456 | UPDATE_SRC; | ||
457 | } | ||
458 | while (--row); | ||
459 | break; | ||
460 | |||
461 | case DRMODE_FG: | ||
462 | fg = FB_SCALARPACK(current_vp->fg_pattern); | ||
463 | do | ||
464 | { | ||
465 | if (data & 0x01) | ||
466 | *dst = fg; | ||
467 | |||
468 | dst += ROW_INC; | ||
469 | UPDATE_SRC; | ||
470 | } | ||
471 | while (--row); | ||
472 | break; | ||
473 | |||
474 | case DRMODE_SOLID|DRMODE_INT_BD: | ||
475 | fg = FB_SCALARPACK(current_vp->fg_pattern); | ||
476 | bo = lcd_backdrop_offset; | ||
477 | do | ||
478 | { | ||
479 | *dst = (data & 0x01) ? fg | ||
480 | : *(fb_data *)((long)dst + bo); | ||
481 | dst += ROW_INC; | ||
482 | UPDATE_SRC; | ||
483 | } | ||
484 | while (--row); | ||
485 | break; | ||
486 | |||
487 | case DRMODE_SOLID: | ||
488 | fg = FB_SCALARPACK(current_vp->fg_pattern); | ||
489 | bg = FB_SCALARPACK(current_vp->bg_pattern); | ||
490 | do | ||
491 | { | ||
492 | *dst = (data & 0x01) ? fg : bg; | ||
493 | dst += ROW_INC; | ||
494 | UPDATE_SRC; | ||
495 | } | ||
496 | while (--row); | ||
497 | break; | ||
498 | } | ||
499 | } | ||
500 | while (src < src_end); | ||
501 | } | ||
502 | /* Draw a full monochrome bitmap */ | ||
503 | void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int height) | ||
504 | { | ||
505 | lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height); | ||
506 | } | ||
507 | |||
508 | |||
509 | /* About Rockbox' internal alpha channel format (for ALPHA_COLOR_FONT_DEPTH == 2) | ||
510 | * | ||
511 | * For each pixel, 4bit of alpha information is stored in a byte-stream, | ||
512 | * so two pixels are packed into one byte. | ||
513 | * The lower nibble is the first pixel, the upper one the second. The stride is | ||
514 | * horizontal. E.g row0: pixel0: byte0[0:3], pixel1: byte0[4:7], pixel2: byte1[0:3],... | ||
515 | * The format is independant of the internal display orientation and color | ||
516 | * representation, as to support the same font files on all displays. | ||
517 | * The values go linear from 0 (fully opaque) to 15 (fully transparent) | ||
518 | * (note how this is the opposite of the alpha channel in the ARGB format). | ||
519 | * | ||
520 | * This might suggest that rows need to have an even number of pixels. | ||
521 | * However this is generally not the case. lcd_alpha_bitmap_part_mix() can deal | ||
522 | * with uneven colums (i.e. two rows can share one byte). And font files do | ||
523 | * exploit this. | ||
524 | * However, this is difficult to do for image files, especially bottom-up bitmaps, | ||
525 | * so lcd_bmp() do expect even rows. | ||
526 | */ | ||
527 | |||
528 | #define ALPHA_COLOR_FONT_DEPTH 2 | ||
529 | #define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH) | ||
530 | #define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1) | ||
531 | #define ALPHA_COLOR_PIXEL_PER_BYTE (8 >> ALPHA_COLOR_FONT_DEPTH) | ||
532 | #define ALPHA_COLOR_PIXEL_PER_WORD (32 >> ALPHA_COLOR_FONT_DEPTH) | ||
533 | |||
534 | /* This is based on SDL (src/video/SDL_RLEaccel.c) ALPHA_BLIT32_888() macro */ | ||
535 | static inline fb_data blend_two_colors(unsigned c1, unsigned c2, unsigned a) | ||
536 | { | ||
537 | unsigned s = c1; | ||
538 | unsigned d = c2; | ||
539 | unsigned s1 = s & 0xff00ff; | ||
540 | unsigned d1 = d & 0xff00ff; | ||
541 | a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1); | ||
542 | d1 = (d1 + ((s1 - d1) * a >> ALPHA_COLOR_LOOKUP_SHIFT)) & 0xff00ff; | ||
543 | s &= 0xff00; | ||
544 | d &= 0xff00; | ||
545 | d = (d + ((s - d) * a >> ALPHA_COLOR_LOOKUP_SHIFT)) & 0xff00; | ||
546 | |||
547 | return FB_SCALARPACK(d1 | d); | ||
548 | } | ||
549 | |||
550 | /* Blend an image with an alpha channel | ||
551 | * if image is NULL, drawing will happen according to the drawmode | ||
552 | * src is the alpha channel (4bit per pixel) */ | ||
553 | static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | ||
554 | const unsigned char *src, int src_x, | ||
555 | int src_y, int x, int y, | ||
556 | int width, int height, | ||
557 | int stride_image, int stride_src) | ||
558 | { | ||
559 | fb_data *dst, *dst_row; | ||
560 | unsigned dmask = 0x00000000; | ||
561 | int drmode = current_vp->drawmode; | ||
562 | /* nothing to draw? */ | ||
563 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | ||
564 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | ||
565 | return; | ||
566 | |||
567 | /* clipping */ | ||
568 | if (x < 0) | ||
569 | { | ||
570 | width += x; | ||
571 | src_x -= x; | ||
572 | x = 0; | ||
573 | } | ||
574 | if (y < 0) | ||
575 | { | ||
576 | height += y; | ||
577 | src_y -= y; | ||
578 | y = 0; | ||
579 | } | ||
580 | if (x + width > current_vp->width) | ||
581 | width = current_vp->width - x; | ||
582 | if (y + height > current_vp->height) | ||
583 | height = current_vp->height - y; | ||
584 | |||
585 | /* adjust for viewport */ | ||
586 | x += current_vp->x; | ||
587 | y += current_vp->y; | ||
588 | |||
589 | #if defined(HAVE_VIEWPORT_CLIP) | ||
590 | /********************* Viewport on screen clipping ********************/ | ||
591 | /* nothing to draw? */ | ||
592 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
593 | || (x + width <= 0) || (y + height <= 0)) | ||
594 | return; | ||
595 | |||
596 | /* clip image in viewport in screen */ | ||
597 | if (x < 0) | ||
598 | { | ||
599 | width += x; | ||
600 | src_x -= x; | ||
601 | x = 0; | ||
602 | } | ||
603 | if (y < 0) | ||
604 | { | ||
605 | height += y; | ||
606 | src_y -= y; | ||
607 | y = 0; | ||
608 | } | ||
609 | if (x + width > LCD_WIDTH) | ||
610 | width = LCD_WIDTH - x; | ||
611 | if (y + height > LCD_HEIGHT) | ||
612 | height = LCD_HEIGHT - y; | ||
613 | #endif | ||
614 | |||
615 | /* the following drawmode combinations are possible: | ||
616 | * 1) COMPLEMENT: just negates the framebuffer contents | ||
617 | * 2) BG and BG+backdrop: draws _only_ background pixels with either | ||
618 | * the background color or the backdrop (if any). The backdrop | ||
619 | * is an image in native lcd format | ||
620 | * 3) FG and FG+image: draws _only_ foreground pixels with either | ||
621 | * the foreground color or an image buffer. The image is in | ||
622 | * native lcd format | ||
623 | * 4) SOLID, SOLID+backdrop, SOLID+image, SOLID+backdrop+image, i.e. all | ||
624 | * possible combinations of 2) and 3). Draws both, fore- and background, | ||
625 | * pixels. The rules of 2) and 3) apply. | ||
626 | * | ||
627 | * INVERSEVID swaps fore- and background pixels, i.e. background pixels | ||
628 | * become foreground ones and vice versa. | ||
629 | */ | ||
630 | if (drmode & DRMODE_INVERSEVID) | ||
631 | { | ||
632 | dmask = 0xffffffff; | ||
633 | drmode &= DRMODE_SOLID; /* mask out inversevid */ | ||
634 | } | ||
635 | |||
636 | /* Use extra bits to avoid if () in the switch-cases below */ | ||
637 | if (image != NULL) | ||
638 | drmode |= DRMODE_INT_IMG; | ||
639 | |||
640 | if ((drmode & DRMODE_BG) && lcd_backdrop) | ||
641 | drmode |= DRMODE_INT_BD; | ||
642 | |||
643 | dst_row = FBADDR(x, y); | ||
644 | |||
645 | int col, row = height; | ||
646 | unsigned data, pixels; | ||
647 | unsigned skip_end = (stride_src - width); | ||
648 | unsigned skip_start = src_y * stride_src + src_x; | ||
649 | unsigned skip_start_image = STRIDE_MAIN(src_y * stride_image + src_x, | ||
650 | src_x * stride_image + src_y); | ||
651 | |||
652 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
653 | uint32_t *src_w = (uint32_t *)((uintptr_t)src & ~3); | ||
654 | skip_start += ALPHA_COLOR_PIXEL_PER_BYTE * ((uintptr_t)src & 3); | ||
655 | src_w += skip_start / ALPHA_COLOR_PIXEL_PER_WORD; | ||
656 | data = letoh32(*src_w++) ^ dmask; | ||
657 | pixels = skip_start % ALPHA_COLOR_PIXEL_PER_WORD; | ||
658 | #else | ||
659 | src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE; | ||
660 | data = *src ^ dmask; | ||
661 | pixels = skip_start % ALPHA_COLOR_PIXEL_PER_BYTE; | ||
662 | #endif | ||
663 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
664 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
665 | pixels = 8 - pixels; | ||
666 | #endif | ||
667 | |||
668 | /* image is only accessed in DRMODE_INT_IMG cases, i.e. when non-NULL. | ||
669 | * Therefore NULL accesses are impossible and we can increment | ||
670 | * unconditionally (applies for stride at the end of the loop as well) */ | ||
671 | image += skip_start_image; | ||
672 | /* go through the rows and update each pixel */ | ||
673 | do | ||
674 | { | ||
675 | /* saving current_vp->fg/bg_pattern and lcd_backdrop_offset into these | ||
676 | * temp vars just before the loop helps gcc to opimize the loop better | ||
677 | * (testing showed ~15% speedup) */ | ||
678 | unsigned fg, bg; | ||
679 | ptrdiff_t bo, img_offset; | ||
680 | col = width; | ||
681 | dst = dst_row; | ||
682 | dst_row += ROW_INC; | ||
683 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
684 | #define UPDATE_SRC_ALPHA do { \ | ||
685 | if (--pixels) \ | ||
686 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
687 | else \ | ||
688 | { \ | ||
689 | data = letoh32(*src_w++) ^ dmask; \ | ||
690 | pixels = ALPHA_COLOR_PIXEL_PER_WORD; \ | ||
691 | } \ | ||
692 | } while (0) | ||
693 | #elif ALPHA_COLOR_PIXEL_PER_BYTE == 2 | ||
694 | #define UPDATE_SRC_ALPHA do { \ | ||
695 | if (pixels ^= 1) \ | ||
696 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
697 | else \ | ||
698 | data = *(++src) ^ dmask; \ | ||
699 | } while (0) | ||
700 | #else | ||
701 | #define UPDATE_SRC_ALPHA do { \ | ||
702 | if (pixels = (++pixels % ALPHA_COLOR_PIXEL_PER_BYTE)) \ | ||
703 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
704 | else \ | ||
705 | data = *(++src) ^ dmask; \ | ||
706 | } while (0) | ||
707 | #endif | ||
708 | |||
709 | switch (drmode) | ||
710 | { | ||
711 | case DRMODE_COMPLEMENT: | ||
712 | do | ||
713 | { | ||
714 | unsigned px = FB_UNPACK_SCALAR_LCD(*dst); | ||
715 | *dst = blend_two_colors(px, ~px, | ||
716 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
717 | dst += COL_INC; | ||
718 | UPDATE_SRC_ALPHA; | ||
719 | } | ||
720 | while (--col); | ||
721 | break; | ||
722 | case DRMODE_BG|DRMODE_INT_BD: | ||
723 | bo = lcd_backdrop_offset; | ||
724 | do | ||
725 | { | ||
726 | unsigned px = FB_UNPACK_SCALAR_LCD(*dst); | ||
727 | unsigned c = FB_UNPACK_SCALAR_LCD(*(fb_data *)((uintptr_t)dst + bo)); | ||
728 | *dst = blend_two_colors(c, px, data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
729 | dst += COL_INC; | ||
730 | image += STRIDE_MAIN(1, stride_image); | ||
731 | UPDATE_SRC_ALPHA; | ||
732 | } | ||
733 | while (--col); | ||
734 | break; | ||
735 | case DRMODE_BG: | ||
736 | bg = current_vp->bg_pattern; | ||
737 | do | ||
738 | { | ||
739 | unsigned px = FB_UNPACK_SCALAR_LCD(*dst); | ||
740 | *dst = blend_two_colors(bg, px, data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
741 | dst += COL_INC; | ||
742 | UPDATE_SRC_ALPHA; | ||
743 | } | ||
744 | while (--col); | ||
745 | break; | ||
746 | case DRMODE_FG|DRMODE_INT_IMG: | ||
747 | img_offset = image - dst; | ||
748 | do | ||
749 | { | ||
750 | unsigned px1 = FB_UNPACK_SCALAR_LCD(*dst); | ||
751 | unsigned px2 = FB_UNPACK_SCALAR_LCD(*(dst + img_offset)); | ||
752 | *dst = blend_two_colors(px1, px2, data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
753 | dst += COL_INC; | ||
754 | UPDATE_SRC_ALPHA; | ||
755 | } | ||
756 | while (--col); | ||
757 | break; | ||
758 | case DRMODE_FG: | ||
759 | fg = current_vp->fg_pattern; | ||
760 | do | ||
761 | { | ||
762 | unsigned px = FB_UNPACK_SCALAR_LCD(*dst); | ||
763 | *dst = blend_two_colors(px, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
764 | dst += COL_INC; | ||
765 | UPDATE_SRC_ALPHA; | ||
766 | } | ||
767 | while (--col); | ||
768 | break; | ||
769 | case DRMODE_SOLID|DRMODE_INT_BD: | ||
770 | bo = lcd_backdrop_offset; | ||
771 | fg = current_vp->fg_pattern; | ||
772 | do | ||
773 | { | ||
774 | unsigned c = FB_UNPACK_SCALAR_LCD(*(fb_data *)((uintptr_t)dst + bo)); | ||
775 | *dst = blend_two_colors(c, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
776 | dst += COL_INC; | ||
777 | UPDATE_SRC_ALPHA; | ||
778 | } | ||
779 | while (--col); | ||
780 | break; | ||
781 | case DRMODE_SOLID|DRMODE_INT_IMG: | ||
782 | bg = current_vp->bg_pattern; | ||
783 | img_offset = image - dst; | ||
784 | do | ||
785 | { | ||
786 | unsigned c = FB_UNPACK_SCALAR_LCD(*(dst + img_offset)); | ||
787 | *dst = blend_two_colors(bg, c, data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
788 | dst += COL_INC; | ||
789 | UPDATE_SRC_ALPHA; | ||
790 | } | ||
791 | while (--col); | ||
792 | break; | ||
793 | case DRMODE_SOLID|DRMODE_INT_BD|DRMODE_INT_IMG: | ||
794 | bo = lcd_backdrop_offset; | ||
795 | img_offset = image - dst; | ||
796 | do | ||
797 | { | ||
798 | unsigned px = FB_UNPACK_SCALAR_LCD(*(fb_data *)((uintptr_t)dst + bo)); | ||
799 | unsigned c = FB_UNPACK_SCALAR_LCD(*(dst + img_offset)); | ||
800 | *dst = blend_two_colors(px, c, data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
801 | dst += COL_INC; | ||
802 | UPDATE_SRC_ALPHA; | ||
803 | } | ||
804 | while (--col); | ||
805 | break; | ||
806 | case DRMODE_SOLID: | ||
807 | bg = current_vp->bg_pattern; | ||
808 | fg = current_vp->fg_pattern; | ||
809 | do | ||
810 | { | ||
811 | *dst = blend_two_colors(bg, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
812 | dst += COL_INC; | ||
813 | UPDATE_SRC_ALPHA; | ||
814 | } | ||
815 | while (--col); | ||
816 | break; | ||
817 | } | ||
818 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
819 | if (skip_end < pixels) | ||
820 | { | ||
821 | pixels -= skip_end; | ||
822 | data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; | ||
823 | } else { | ||
824 | pixels = skip_end - pixels; | ||
825 | src_w += pixels / ALPHA_COLOR_PIXEL_PER_WORD; | ||
826 | pixels %= ALPHA_COLOR_PIXEL_PER_WORD; | ||
827 | data = letoh32(*src_w++) ^ dmask; | ||
828 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
829 | pixels = 8 - pixels; | ||
830 | } | ||
831 | #else | ||
832 | if (skip_end) | ||
833 | { | ||
834 | pixels += skip_end; | ||
835 | if (pixels >= ALPHA_COLOR_PIXEL_PER_BYTE) | ||
836 | { | ||
837 | src += pixels / ALPHA_COLOR_PIXEL_PER_BYTE; | ||
838 | pixels %= ALPHA_COLOR_PIXEL_PER_BYTE; | ||
839 | data = *src ^ dmask; | ||
840 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
841 | } else | ||
842 | data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; | ||
843 | } | ||
844 | #endif | ||
845 | |||
846 | image += STRIDE_MAIN(stride_image,1); | ||
847 | } while (--row); | ||
848 | } | ||
849 | |||
850 | /*** drawing functions ***/ | ||
851 | |||
852 | /* Draw a horizontal line (optimised) */ | ||
853 | void lcd_hline(int x1, int x2, int y) | ||
854 | { | ||
855 | int x, width; | ||
856 | fb_data *dst, *dst_end; | ||
857 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; | ||
858 | |||
859 | /* direction flip */ | ||
860 | if (x2 < x1) | ||
861 | { | ||
862 | x = x1; | ||
863 | x1 = x2; | ||
864 | x2 = x; | ||
865 | } | ||
866 | |||
867 | /******************** In viewport clipping **********************/ | ||
868 | /* nothing to draw? */ | ||
869 | if (((unsigned)y >= (unsigned)current_vp->height) || | ||
870 | (x1 >= current_vp->width) || | ||
871 | (x2 < 0)) | ||
872 | return; | ||
873 | |||
874 | if (x1 < 0) | ||
875 | x1 = 0; | ||
876 | if (x2 >= current_vp->width) | ||
877 | x2 = current_vp->width-1; | ||
878 | |||
879 | /* Adjust x1 and y to viewport */ | ||
880 | x1 += current_vp->x; | ||
881 | x2 += current_vp->x; | ||
882 | y += current_vp->y; | ||
883 | |||
884 | #if defined(HAVE_VIEWPORT_CLIP) | ||
885 | /********************* Viewport on screen clipping ********************/ | ||
886 | /* nothing to draw? */ | ||
887 | if (((unsigned)y >= (unsigned) LCD_HEIGHT) || (x1 >= LCD_WIDTH) | ||
888 | || (x2 < 0)) | ||
889 | return; | ||
890 | |||
891 | /* clipping */ | ||
892 | if (x1 < 0) | ||
893 | x1 = 0; | ||
894 | if (x2 >= LCD_WIDTH) | ||
895 | x2 = LCD_WIDTH-1; | ||
896 | #endif | ||
897 | |||
898 | width = x2 - x1 + 1; | ||
899 | |||
900 | dst = FBADDR(x1 , y); | ||
901 | dst_end = dst + width; | ||
902 | do | ||
903 | { | ||
904 | pfunc(dst); | ||
905 | } | ||
906 | while (++dst < dst_end); | ||
907 | } | ||
908 | |||
909 | /* Draw a vertical line (optimised) */ | ||
910 | void lcd_vline(int x, int y1, int y2) | ||
911 | { | ||
912 | int y; | ||
913 | fb_data *dst, *dst_end; | ||
914 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; | ||
915 | |||
916 | /* direction flip */ | ||
917 | if (y2 < y1) | ||
918 | { | ||
919 | y = y1; | ||
920 | y1 = y2; | ||
921 | y2 = y; | ||
922 | } | ||
923 | |||
924 | /******************** In viewport clipping **********************/ | ||
925 | /* nothing to draw? */ | ||
926 | if (((unsigned)x >= (unsigned)current_vp->width) || | ||
927 | (y1 >= current_vp->height) || | ||
928 | (y2 < 0)) | ||
929 | return; | ||
930 | |||
931 | if (y1 < 0) | ||
932 | y1 = 0; | ||
933 | if (y2 >= current_vp->height) | ||
934 | y2 = current_vp->height-1; | ||
935 | |||
936 | /* adjust for viewport */ | ||
937 | x += current_vp->x; | ||
938 | y1 += current_vp->y; | ||
939 | y2 += current_vp->y; | ||
940 | |||
941 | #if defined(HAVE_VIEWPORT_CLIP) | ||
942 | /********************* Viewport on screen clipping ********************/ | ||
943 | /* nothing to draw? */ | ||
944 | if (( (unsigned) x >= (unsigned)LCD_WIDTH) || (y1 >= LCD_HEIGHT) | ||
945 | || (y2 < 0)) | ||
946 | return; | ||
947 | |||
948 | /* clipping */ | ||
949 | if (y1 < 0) | ||
950 | y1 = 0; | ||
951 | if (y2 >= LCD_HEIGHT) | ||
952 | y2 = LCD_HEIGHT-1; | ||
953 | #endif | ||
954 | |||
955 | dst = FBADDR(x , y1); | ||
956 | dst_end = dst + (y2 - y1) * LCD_WIDTH; | ||
957 | |||
958 | do | ||
959 | { | ||
960 | pfunc(dst); | ||
961 | dst += LCD_WIDTH; | ||
962 | } | ||
963 | while (dst <= dst_end); | ||
964 | } | ||
965 | |||
966 | /* Draw a partial native bitmap */ | ||
967 | void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | ||
968 | int stride, int x, int y, int width, | ||
969 | int height) | ||
970 | { | ||
971 | fb_data *dst; | ||
972 | |||
973 | /******************** Image in viewport clipping **********************/ | ||
974 | /* nothing to draw? */ | ||
975 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | ||
976 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | ||
977 | return; | ||
978 | |||
979 | if (x < 0) | ||
980 | { | ||
981 | width += x; | ||
982 | src_x -= x; | ||
983 | x = 0; | ||
984 | } | ||
985 | if (y < 0) | ||
986 | { | ||
987 | height += y; | ||
988 | src_y -= y; | ||
989 | y = 0; | ||
990 | } | ||
991 | |||
992 | if (x + width > current_vp->width) | ||
993 | width = current_vp->width - x; | ||
994 | if (y + height > current_vp->height) | ||
995 | height = current_vp->height - y; | ||
996 | |||
997 | /* adjust for viewport */ | ||
998 | x += current_vp->x; | ||
999 | y += current_vp->y; | ||
1000 | |||
1001 | #if defined(HAVE_VIEWPORT_CLIP) | ||
1002 | /********************* Viewport on screen clipping ********************/ | ||
1003 | /* nothing to draw? */ | ||
1004 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
1005 | || (x + width <= 0) || (y + height <= 0)) | ||
1006 | return; | ||
1007 | |||
1008 | /* clip image in viewport in screen */ | ||
1009 | if (x < 0) | ||
1010 | { | ||
1011 | width += x; | ||
1012 | src_x -= x; | ||
1013 | x = 0; | ||
1014 | } | ||
1015 | if (y < 0) | ||
1016 | { | ||
1017 | height += y; | ||
1018 | src_y -= y; | ||
1019 | y = 0; | ||
1020 | } | ||
1021 | if (x + width > LCD_WIDTH) | ||
1022 | width = LCD_WIDTH - x; | ||
1023 | if (y + height > LCD_HEIGHT) | ||
1024 | height = LCD_HEIGHT - y; | ||
1025 | #endif | ||
1026 | |||
1027 | src += stride * src_y + src_x; /* move starting point */ | ||
1028 | dst = FBADDR(x, y); | ||
1029 | |||
1030 | do | ||
1031 | { | ||
1032 | memcpy(dst, src, width * sizeof(fb_data)); | ||
1033 | src += stride; | ||
1034 | dst += LCD_WIDTH; | ||
1035 | } | ||
1036 | while (--height > 0); | ||
1037 | } | ||
1038 | |||
1039 | /* Draw a partial native bitmap with transparency and foreground colors */ | ||
1040 | void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, | ||
1041 | int src_y, int stride, int x, | ||
1042 | int y, int width, int height) | ||
1043 | { | ||
1044 | fb_data *dst; | ||
1045 | fb_data fg, transparent, replacewithfg; | ||
1046 | |||
1047 | /******************** Image in viewport clipping **********************/ | ||
1048 | /* nothing to draw? */ | ||
1049 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | ||
1050 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | ||
1051 | return; | ||
1052 | |||
1053 | if (x < 0) | ||
1054 | { | ||
1055 | width += x; | ||
1056 | src_x -= x; | ||
1057 | x = 0; | ||
1058 | } | ||
1059 | if (y < 0) | ||
1060 | { | ||
1061 | height += y; | ||
1062 | src_y -= y; | ||
1063 | y = 0; | ||
1064 | } | ||
1065 | |||
1066 | if (x + width > current_vp->width) | ||
1067 | width = current_vp->width - x; | ||
1068 | if (y + height > current_vp->height) | ||
1069 | height = current_vp->height - y; | ||
1070 | |||
1071 | /* adjust for viewport */ | ||
1072 | x += current_vp->x; | ||
1073 | y += current_vp->y; | ||
1074 | |||
1075 | #if defined(HAVE_VIEWPORT_CLIP) | ||
1076 | /********************* Viewport on screen clipping ********************/ | ||
1077 | /* nothing to draw? */ | ||
1078 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
1079 | || (x + width <= 0) || (y + height <= 0)) | ||
1080 | return; | ||
1081 | |||
1082 | /* clip image in viewport in screen */ | ||
1083 | if (x < 0) | ||
1084 | { | ||
1085 | width += x; | ||
1086 | src_x -= x; | ||
1087 | x = 0; | ||
1088 | } | ||
1089 | if (y < 0) | ||
1090 | { | ||
1091 | height += y; | ||
1092 | src_y -= y; | ||
1093 | y = 0; | ||
1094 | } | ||
1095 | if (x + width > LCD_WIDTH) | ||
1096 | width = LCD_WIDTH - x; | ||
1097 | if (y + height > LCD_HEIGHT) | ||
1098 | height = LCD_HEIGHT - y; | ||
1099 | #endif | ||
1100 | |||
1101 | src += stride * src_y + src_x; /* move starting point */ | ||
1102 | dst = FBADDR(x, y); | ||
1103 | |||
1104 | transparent = FB_SCALARPACK(TRANSPARENT_COLOR); | ||
1105 | replacewithfg = FB_SCALARPACK(REPLACEWITHFG_COLOR); | ||
1106 | fg = FB_SCALARPACK(current_vp->fg_pattern); | ||
1107 | #define CMP(c1, c2) (c1.r == c2.r && c1.g == c2.g && c1.b == c2.b) | ||
1108 | |||
1109 | do | ||
1110 | { | ||
1111 | const fb_data *src_row = src; | ||
1112 | fb_data *dst_row = dst; | ||
1113 | fb_data *row_end = dst_row + width; | ||
1114 | do | ||
1115 | { | ||
1116 | fb_data data = *src_row++; | ||
1117 | if (!CMP(data, transparent)) | ||
1118 | { | ||
1119 | if (CMP(data, replacewithfg)) | ||
1120 | data = fg; | ||
1121 | *dst_row = data; | ||
1122 | } | ||
1123 | } | ||
1124 | while (++dst_row < row_end); | ||
1125 | src += stride; | ||
1126 | dst += LCD_WIDTH; | ||
1127 | } | ||
1128 | while (--height > 0); | ||
1129 | } | ||
diff --git a/firmware/drivers/lcd-color-common.c b/firmware/drivers/lcd-color-common.c index e171f08465..b5b0f58eb3 100644 --- a/firmware/drivers/lcd-color-common.c +++ b/firmware/drivers/lcd-color-common.c | |||
@@ -422,7 +422,7 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
422 | b = clamp(b, 0, 64*256-1); | 422 | b = clamp(b, 0, 64*256-1); |
423 | } | 423 | } |
424 | 424 | ||
425 | *dst = FB_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); | 425 | *dst = FB_RGBPACK(r >> 6, g >> 6, b >> 6); |
426 | 426 | ||
427 | #if LCD_WIDTH >= LCD_HEIGHT | 427 | #if LCD_WIDTH >= LCD_HEIGHT |
428 | dst++; | 428 | dst++; |
@@ -442,7 +442,7 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
442 | b = clamp(b, 0, 64*256-1); | 442 | b = clamp(b, 0, 64*256-1); |
443 | } | 443 | } |
444 | 444 | ||
445 | *dst = FB_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); | 445 | *dst = FB_RGBPACK(r >> 6, g >> 6, b >> 6); |
446 | 446 | ||
447 | #if LCD_WIDTH >= LCD_HEIGHT | 447 | #if LCD_WIDTH >= LCD_HEIGHT |
448 | dst++; | 448 | dst++; |
@@ -487,7 +487,7 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
487 | b = clamp(b, 0, 64*256-1); | 487 | b = clamp(b, 0, 64*256-1); |
488 | } | 488 | } |
489 | 489 | ||
490 | *dst = FB_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); | 490 | *dst = FB_RGBPACK(r >> 6, g >> 6, b >> 6); |
491 | 491 | ||
492 | #if LCD_WIDTH >= LCD_HEIGHT | 492 | #if LCD_WIDTH >= LCD_HEIGHT |
493 | dst++; | 493 | dst++; |
@@ -507,7 +507,7 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
507 | b = clamp(b, 0, 64*256-1); | 507 | b = clamp(b, 0, 64*256-1); |
508 | } | 508 | } |
509 | 509 | ||
510 | *dst = FB_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); | 510 | *dst = FB_RGBPACK(r >> 6, g >> 6, b >> 6); |
511 | 511 | ||
512 | #if LCD_WIDTH >= LCD_HEIGHT | 512 | #if LCD_WIDTH >= LCD_HEIGHT |
513 | dst++; | 513 | dst++; |
diff --git a/firmware/export/config.h b/firmware/export/config.h index 9c1a8dbf57..5e4178cd4c 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h | |||
@@ -275,6 +275,7 @@ | |||
275 | #define VERTICAL_INTERLEAVED 4 | 275 | #define VERTICAL_INTERLEAVED 4 |
276 | #define RGB565 565 | 276 | #define RGB565 565 |
277 | #define RGB565SWAPPED 3553 | 277 | #define RGB565SWAPPED 3553 |
278 | #define RGB888 888 | ||
278 | 279 | ||
279 | /* LCD_STRIDEFORMAT */ | 280 | /* LCD_STRIDEFORMAT */ |
280 | #define VERTICAL_STRIDE 1 | 281 | #define VERTICAL_STRIDE 1 |
diff --git a/firmware/export/config/samsungypr0.h b/firmware/export/config/samsungypr0.h index 049caa01b6..0fce70e1fe 100644 --- a/firmware/export/config/samsungypr0.h +++ b/firmware/export/config/samsungypr0.h | |||
@@ -47,7 +47,7 @@ | |||
47 | /* sqrt(240^2 + 320^2) / 2.6 = 153.8 */ | 47 | /* sqrt(240^2 + 320^2) / 2.6 = 153.8 */ |
48 | #define LCD_DPI 154 | 48 | #define LCD_DPI 154 |
49 | 49 | ||
50 | #define LCD_DEPTH 16 | 50 | #define LCD_DEPTH 24 |
51 | /* Check that but should not matter */ | 51 | /* Check that but should not matter */ |
52 | #define LCD_PIXELFORMAT RGB565 | 52 | #define LCD_PIXELFORMAT RGB565 |
53 | 53 | ||
diff --git a/firmware/export/config/samsungypr1.h b/firmware/export/config/samsungypr1.h index 1aaf85dcb5..42b46e0699 100644 --- a/firmware/export/config/samsungypr1.h +++ b/firmware/export/config/samsungypr1.h | |||
@@ -53,11 +53,11 @@ | |||
53 | #define LCD_HEIGHT 240 | 53 | #define LCD_HEIGHT 240 |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | #define LCD_DEPTH 16 | 56 | #define LCD_DEPTH 24 |
57 | /* Calculated value, important for touch sensor */ | 57 | /* Calculated value, important for touch sensor */ |
58 | #define LCD_DPI 180 | 58 | #define LCD_DPI 180 |
59 | /* Check that but should not matter */ | 59 | /* Check that but should not matter */ |
60 | #define LCD_PIXELFORMAT RGB565 | 60 | #define LCD_PIXELFORMAT RGB888 |
61 | 61 | ||
62 | /* Capacitive touchscreen */ | 62 | /* Capacitive touchscreen */ |
63 | #define HAVE_TOUCHSCREEN | 63 | #define HAVE_TOUCHSCREEN |
diff --git a/firmware/export/config/sansae200v2.h b/firmware/export/config/sansae200v2.h index c703439e7f..e70b409d51 100644 --- a/firmware/export/config/sansae200v2.h +++ b/firmware/export/config/sansae200v2.h | |||
@@ -53,8 +53,8 @@ | |||
53 | #define LCD_HEIGHT 220 | 53 | #define LCD_HEIGHT 220 |
54 | /* sqrt(176^2 + 220^2) / 1.8 = 156.5 */ | 54 | /* sqrt(176^2 + 220^2) / 1.8 = 156.5 */ |
55 | #define LCD_DPI 157 | 55 | #define LCD_DPI 157 |
56 | #define LCD_DEPTH 16 /* 65536 colours */ | 56 | #define LCD_DEPTH 24 /* 65536 colours */ |
57 | #define LCD_PIXELFORMAT RGB565 /* rgb565 */ | 57 | #define LCD_PIXELFORMAT RGB888 /* rgb565 */ |
58 | 58 | ||
59 | #ifndef BOOTLOADER | 59 | #ifndef BOOTLOADER |
60 | /* define this if you have LCD enable function */ | 60 | /* define this if you have LCD enable function */ |
diff --git a/firmware/export/config/sdlapp.h b/firmware/export/config/sdlapp.h index cd973fcf73..626bd5c99f 100644 --- a/firmware/export/config/sdlapp.h +++ b/firmware/export/config/sdlapp.h | |||
@@ -44,8 +44,8 @@ | |||
44 | #define LCD_HEIGHT 480 | 44 | #define LCD_HEIGHT 480 |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #define LCD_DEPTH 16 | 47 | #define LCD_DEPTH 24 |
48 | #define LCD_PIXELFORMAT RGB565 | 48 | #define LCD_PIXELFORMAT RGB888 |
49 | 49 | ||
50 | /* define this to indicate your device's keypad */ | 50 | /* define this to indicate your device's keypad */ |
51 | #define HAVE_TOUCHSCREEN | 51 | #define HAVE_TOUCHSCREEN |
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index 673ce069af..cf6a16572a 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h | |||
@@ -127,7 +127,13 @@ typedef unsigned char fb_data; | |||
127 | #elif LCD_DEPTH <= 16 | 127 | #elif LCD_DEPTH <= 16 |
128 | typedef unsigned short fb_data; | 128 | typedef unsigned short fb_data; |
129 | #define FB_DATA_SZ 2 | 129 | #define FB_DATA_SZ 2 |
130 | #else /* LCD_DEPTH > 16 */ | 130 | #elif LCD_DEPTH <= 24 |
131 | struct _fb_pixel { | ||
132 | unsigned char b, g, r; | ||
133 | }; | ||
134 | typedef struct _fb_pixel fb_data; | ||
135 | #define FB_DATA_SZ 3 | ||
136 | #else /* LCD_DEPTH > 24 */ | ||
131 | typedef unsigned long fb_data; | 137 | typedef unsigned long fb_data; |
132 | #define FB_DATA_SZ 4 | 138 | #define FB_DATA_SZ 4 |
133 | #endif /* LCD_DEPTH */ | 139 | #endif /* LCD_DEPTH */ |
@@ -341,6 +347,31 @@ static inline unsigned lcd_color_to_native(unsigned color) | |||
341 | #define RGB_UNPACK_GREEN_LCD(x) _RGB_UNPACK_GREEN_LCD(x) | 347 | #define RGB_UNPACK_GREEN_LCD(x) _RGB_UNPACK_GREEN_LCD(x) |
342 | #define RGB_UNPACK_BLUE_LCD(x) _RGB_UNPACK_BLUE_LCD(x) | 348 | #define RGB_UNPACK_BLUE_LCD(x) _RGB_UNPACK_BLUE_LCD(x) |
343 | #endif /* RGB565* */ | 349 | #endif /* RGB565* */ |
350 | |||
351 | #elif LCD_PIXELFORMAT == RGB888 | ||
352 | #define LCD_MAX_RED 255 | ||
353 | #define LCD_MAX_GREEN 255 | ||
354 | #define LCD_MAX_BLUE 255 | ||
355 | #define LCD_RED_BITS 8 | ||
356 | #define LCD_GREEN_BITS 8 | ||
357 | #define LCD_BLUE_BITS 8 | ||
358 | |||
359 | /* pack/unpack native RGB values */ | ||
360 | #define _RGBPACK(r, g, b) ( r << 16 | g << 8 | b ) | ||
361 | #define _RGB_UNPACK_RED(x) ((x >> 16) & 0xff) | ||
362 | #define _RGB_UNPACK_GREEN(x) ((x >> 8) & 0xff) | ||
363 | #define _RGB_UNPACK_BLUE(x) ((x >> 0) & 0xff) | ||
364 | |||
365 | #define _LCD_UNSWAP_COLOR(x) (x) | ||
366 | #define LCD_RGBPACK(r, g, b) _RGBPACK((r), (g), (b)) | ||
367 | #define LCD_RGBPACK_LCD(r, g, b) _RGBPACK((r), (g), (b)) | ||
368 | #define RGB_UNPACK_RED(x) _RGB_UNPACK_RED(x) | ||
369 | #define RGB_UNPACK_GREEN(x) _RGB_UNPACK_GREEN(x) | ||
370 | #define RGB_UNPACK_BLUE(x) _RGB_UNPACK_BLUE(x) | ||
371 | #define RGB_UNPACK_RED_LCD(x) _RGB_UNPACK_RED(x) | ||
372 | #define RGB_UNPACK_GREEN_LCD(x) _RGB_UNPACK_GREEN(x) | ||
373 | #define RGB_UNPACK_BLUE_LCD(x) _RGB_UNPACK_BLUE(x) | ||
374 | |||
344 | #else | 375 | #else |
345 | /* other colour depths */ | 376 | /* other colour depths */ |
346 | #endif | 377 | #endif |
@@ -367,6 +398,58 @@ static inline unsigned lcd_color_to_native(unsigned color) | |||
367 | 398 | ||
368 | #endif /* HAVE_LCD_COLOR */ | 399 | #endif /* HAVE_LCD_COLOR */ |
369 | 400 | ||
401 | /* Framebuffer conversion macros: Convert from and to the native display data | ||
402 | * format (fb_data). | ||
403 | * | ||
404 | * FB_RGBPACK: Convert the three r,g,b values to fb_data. r,g,b are | ||
405 | * assumed to in 8-bit format. | ||
406 | * FB_RGBPACK_LCD Like FB_RGBPACK, except r,g,b shall be in display-native | ||
407 | * bit format (e.g. 5-bit r for RGB565) | ||
408 | * FB_UNPACK_RED Extract the red component of fb_data into 8-bit red value. | ||
409 | * FB_UNPACK_GREEN Like FB_UNPACK_RED, just for the green component. | ||
410 | * FB_UNPACK_BLIE Like FB_UNPACK_RED, just for the green component. | ||
411 | * FB_SCALARPACK Similar to FB_RGBPACK, except that the channels are already | ||
412 | * combined into a single scalar value. Again, 8-bit per channel. | ||
413 | * FB_SCALARPACK_LCD Like FB_SCALARPACK, except the channels shall be in | ||
414 | * display-native format (i.e. the scalar is 16bits on RGB565) | ||
415 | * FB_UNPACK_SCALAR_LCD Converts an fb_data to a scalar value in display-native | ||
416 | * format, so it's the reverse of FB_SCALARPACK_LCD | ||
417 | */ | ||
418 | #if LCD_DEPTH >= 24 | ||
419 | static inline fb_data scalar_to_fb(unsigned p) | ||
420 | { | ||
421 | union { fb_data st; unsigned sc; } convert; | ||
422 | convert.sc = p; return convert.st; | ||
423 | } | ||
424 | static inline unsigned fb_to_scalar(fb_data p) | ||
425 | { | ||
426 | union { fb_data st; unsigned sc; } convert; | ||
427 | convert.st = p; return convert.sc; | ||
428 | } | ||
429 | #define FB_RGBPACK(r_, g_, b_) ((fb_data){.r = r_, .g = g_, .b = b_}) | ||
430 | #define FB_RGBPACK_LCD(r_, g_, b_) FB_RGBPACK(r_, g_, b_) | ||
431 | #define FB_UNPACK_RED(fb) ((fb).r) | ||
432 | #define FB_UNPACK_GREEN(fb) ((fb).g) | ||
433 | #define FB_UNPACK_BLUE(fb) ((fb).b) | ||
434 | #define FB_SCALARPACK(c) scalar_to_fb(c) | ||
435 | #define FB_SCALARPACK_LCD(c) scalar_to_fb(c) | ||
436 | #define FB_UNPACK_SCALAR_LCD(fb) fb_to_scalar(fb) | ||
437 | #elif defined(HAVE_LCD_COLOR) | ||
438 | #define FB_RGBPACK(r_, g_, b_) LCD_RGBPACK(r_, g_, b_) | ||
439 | #define FB_RGBPACK_LCD(r_, g_, b_) LCD_RGBPACK_LCD(r_, g_, b_) | ||
440 | #define FB_UNPACK_RED(fb) RGB_UNPACK_RED(fb) | ||
441 | #define FB_UNPACK_GREEN(fb) RGB_UNPACK_GREEN(fb) | ||
442 | #define FB_UNPACK_BLUE(fb) RGB_UNPACK_BLUE(fb) | ||
443 | #define FB_SCALARPACK(c) LCD_RGBPACK(RGB_UNPACK_RED(c), RGB_UNPACK_GREEN(c), RGB_UNPACK_BLUE(c)) | ||
444 | #define FB_SCALARPACK_LCD(c) (c) | ||
445 | #define FB_UNPACK_SCALAR_LCD(fb) (fb) | ||
446 | #else | ||
447 | #define FB_SCALARPACK(c) (c) | ||
448 | #define FB_SCALARPACK_LCD(c) (c) | ||
449 | #define FB_UNPACK_SCALAR_LCD(fb) (fb) | ||
450 | #endif | ||
451 | |||
452 | |||
370 | /* Frame buffer dimensions */ | 453 | /* Frame buffer dimensions */ |
371 | #if LCD_DEPTH == 1 | 454 | #if LCD_DEPTH == 1 |
372 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | 455 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING |
diff --git a/firmware/screendump.c b/firmware/screendump.c index 28c37610af..2916cc1c9f 100644 --- a/firmware/screendump.c +++ b/firmware/screendump.c | |||
@@ -118,6 +118,9 @@ void screen_dump(void) | |||
118 | #elif LCD_DEPTH <= 16 | 118 | #elif LCD_DEPTH <= 16 |
119 | unsigned short *dst, *dst_end; | 119 | unsigned short *dst, *dst_end; |
120 | unsigned short linebuf[DUMP_BMP_LINESIZE/2]; | 120 | unsigned short linebuf[DUMP_BMP_LINESIZE/2]; |
121 | #else /* 24bit */ | ||
122 | unsigned char *dst, *dst_end; | ||
123 | unsigned char linebuf[DUMP_BMP_LINESIZE * 3]; | ||
121 | #endif | 124 | #endif |
122 | 125 | ||
123 | #if CONFIG_RTC | 126 | #if CONFIG_RTC |
@@ -227,6 +230,17 @@ void screen_dump(void) | |||
227 | #endif | 230 | #endif |
228 | } | 231 | } |
229 | while (dst < dst_end); | 232 | while (dst < dst_end); |
233 | #elif LCD_DEPTH == 24 | ||
234 | dst_end = dst + LCD_WIDTH*3; | ||
235 | src = FBADDR(0, y); | ||
236 | do | ||
237 | { | ||
238 | *dst++ = src->b; | ||
239 | *dst++ = src->g; | ||
240 | *dst++ = src->r; | ||
241 | ++src; | ||
242 | } | ||
243 | while (dst < dst_end); | ||
230 | 244 | ||
231 | #endif /* LCD_DEPTH */ | 245 | #endif /* LCD_DEPTH */ |
232 | write(fd, linebuf, DUMP_BMP_LINESIZE); | 246 | write(fd, linebuf, DUMP_BMP_LINESIZE); |
diff --git a/firmware/target/hosted/sdl/lcd-bitmap.c b/firmware/target/hosted/sdl/lcd-bitmap.c index 7e9bc297ef..5add2367a0 100644 --- a/firmware/target/hosted/sdl/lcd-bitmap.c +++ b/firmware/target/hosted/sdl/lcd-bitmap.c | |||
@@ -112,6 +112,8 @@ static unsigned long get_lcd_pixel(int x, int y) | |||
112 | #else | 112 | #else |
113 | return *FBADDR(x, y); | 113 | return *FBADDR(x, y); |
114 | #endif | 114 | #endif |
115 | #elif LCD_DEPTH == 24 | ||
116 | return FB_UNPACK_SCALAR_LCD(*FBADDR(x, y)); | ||
115 | #endif | 117 | #endif |
116 | } | 118 | } |
117 | 119 | ||
@@ -172,7 +174,7 @@ void sim_backlight(int value) | |||
172 | /* initialise simulator lcd driver */ | 174 | /* initialise simulator lcd driver */ |
173 | void lcd_init_device(void) | 175 | void lcd_init_device(void) |
174 | { | 176 | { |
175 | #if LCD_DEPTH == 16 | 177 | #if LCD_DEPTH >= 16 |
176 | lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, | 178 | lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, |
177 | SIM_LCD_WIDTH * display_zoom, | 179 | SIM_LCD_WIDTH * display_zoom, |
178 | SIM_LCD_HEIGHT * display_zoom, | 180 | SIM_LCD_HEIGHT * display_zoom, |