summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2014-06-18 07:15:00 +0200
committerThomas Martitz <kugel@rockbox.org>2014-06-21 00:15:53 +0200
commita1842c04f9cb73210d4cacde61a9e4b115050765 (patch)
treea37af61ef9285b763a42cd33797e2f3d634fbf9f /firmware
parent0250be1d6799db7b5ddc99cb33f31bf9cff01ed2 (diff)
downloadrockbox-a1842c04f9cb73210d4cacde61a9e4b115050765.tar.gz
rockbox-a1842c04f9cb73210d4cacde61a9e4b115050765.zip
lcd-24bit: Introduce a 24-bit mid-level LCD driver
With LCD driver all calculation will be performed on RGB888 and the hardware/OS can display from our 24bit framebuffer. It is not yet as performance optimized as the existing drivers but should be good enough.The vast number of small changes is due to the fact that fb_data can be a struct type now, while most of the code expected a scalar type. lcd-as-memframe ASM code does not work with 24bit currently so the with 24bit it enforces the generic C code. All plugins are ported over. Except for rockpaint. It uses so much memory that it wouldnt fit into the 512k plugin buffer anymore (patches welcome). Change-Id: Ibb1964545028ce0d8ff9833ccc3ab66be3ee0754
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/asm/SOURCES4
-rw-r--r--firmware/asm/lcd-as-memframe-24bit.c3
-rw-r--r--firmware/asm/lcd-as-memframe.c8
-rw-r--r--firmware/drivers/lcd-24bit.c1129
-rw-r--r--firmware/drivers/lcd-color-common.c8
-rw-r--r--firmware/export/config.h1
-rw-r--r--firmware/export/config/samsungypr0.h2
-rw-r--r--firmware/export/config/samsungypr1.h4
-rw-r--r--firmware/export/config/sansae200v2.h4
-rw-r--r--firmware/export/config/sdlapp.h4
-rw-r--r--firmware/export/lcd.h85
-rw-r--r--firmware/screendump.c14
-rw-r--r--firmware/target/hosted/sdl/lcd-bitmap.c4
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
219drivers/lcd-16bit.c 219drivers/lcd-16bit.c
220#endif 220#endif
221#elif LCD_DEPTH == 24
222drivers/lcd-24bit.c
221#endif /* LCD_DEPTH */ 223#endif /* LCD_DEPTH */
222common/diacritic.c 224common/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
16lcd-as-memframe-24bit.c
17#else
15lcd-as-memframe.c 18lcd-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
45extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[];
46extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_bgcolor[];
47
48static 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 */
59void 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
148static void ICODE_ATTR setpixel(fb_data *address)
149{
150 *address = FB_SCALARPACK(current_vp->fg_pattern);
151}
152
153static void ICODE_ATTR clearpixel(fb_data *address)
154{
155 *address = FB_SCALARPACK(current_vp->bg_pattern);
156}
157
158static void ICODE_ATTR clearimgpixel(fb_data *address)
159{
160 *address = *(fb_data *)((long)address + lcd_backdrop_offset);
161}
162
163static void ICODE_ATTR flippixel(fb_data *address)
164{
165 unsigned px = FB_UNPACK_SCALAR_LCD(*address);
166 *address = FB_SCALARPACK(~px);
167}
168
169static void ICODE_ATTR nopixel(fb_data *address)
170{
171 (void)address;
172}
173
174lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_bgcolor[8] = {
175 flippixel, nopixel, setpixel, setpixel,
176 nopixel, clearpixel, nopixel, clearpixel
177};
178
179lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[8] = {
180 flippixel, nopixel, setpixel, setpixel,
181 nopixel, clearimgpixel, nopixel, clearimgpixel
182};
183
184lcd_fastpixelfunc_type* const * lcd_fastpixelfuncs = lcd_fastpixelfuncs_bgcolor;
185
186/* Fill a rectangular area */
187void 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
322void 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 */
503void 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 */
535static 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) */
553static 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) */
853void 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) */
910void 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 */
967void 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 */
1040void 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
128typedef unsigned short fb_data; 128typedef 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
131struct _fb_pixel {
132 unsigned char b, g, r;
133};
134typedef struct _fb_pixel fb_data;
135#define FB_DATA_SZ 3
136#else /* LCD_DEPTH > 24 */
131typedef unsigned long fb_data; 137typedef 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
419static 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}
424static 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 */
173void lcd_init_device(void) 175void 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,