summaryrefslogtreecommitdiff
path: root/firmware/target/hosted/sdl/lcd-bitmap.c
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2010-05-15 21:02:47 +0000
committerThomas Martitz <kugel@rockbox.org>2010-05-15 21:02:47 +0000
commit3d0cee8abbaf764958743e8a7851eee94e60a913 (patch)
treea96b1ec825003a71643a7da4707c300f64824f82 /firmware/target/hosted/sdl/lcd-bitmap.c
parentdcf442e61f21fb2aef5ce7de0547f733557b156e (diff)
downloadrockbox-3d0cee8abbaf764958743e8a7851eee94e60a913.tar.gz
rockbox-3d0cee8abbaf764958743e8a7851eee94e60a913.zip
- Move uisimulator/sdl/*.[ch] into the target tree, under firmware/target/hosted/sdl, uisdl.c is split up across button-sdl.c and system-sdl.c.
- Refactor the program startup. main() is now in main.c like on target, and the implicit application thread will now act as our main thread (previously a separate one was created for this in thread initialization). This is part of Rockbox as an application and is the first step to make an application port from the uisimulator. In a further step the sim bits from the sdl build will be separated out. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26065 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/hosted/sdl/lcd-bitmap.c')
-rw-r--r--firmware/target/hosted/sdl/lcd-bitmap.c416
1 files changed, 416 insertions, 0 deletions
diff --git a/firmware/target/hosted/sdl/lcd-bitmap.c b/firmware/target/hosted/sdl/lcd-bitmap.c
new file mode 100644
index 0000000000..6dfbffff37
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-bitmap.c
@@ -0,0 +1,416 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Dan Everton
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "debug.h"
23#include "sim-ui-defines.h"
24#include "system.h"
25#include "lcd-sdl.h"
26#include "screendump.h"
27
28SDL_Surface* lcd_surface;
29
30#if LCD_DEPTH <= 8
31#ifdef HAVE_BACKLIGHT
32SDL_Color lcd_bl_color_dark = {RED_CMP(LCD_BL_DARKCOLOR),
33 GREEN_CMP(LCD_BL_DARKCOLOR),
34 BLUE_CMP(LCD_BL_DARKCOLOR), 0};
35SDL_Color lcd_bl_color_bright = {RED_CMP(LCD_BL_BRIGHTCOLOR),
36 GREEN_CMP(LCD_BL_BRIGHTCOLOR),
37 BLUE_CMP(LCD_BL_BRIGHTCOLOR), 0};
38#ifdef HAVE_LCD_SPLIT
39SDL_Color lcd_bl_color2_dark = {RED_CMP(LCD_BL_DARKCOLOR_2),
40 GREEN_CMP(LCD_BL_DARKCOLOR_2),
41 BLUE_CMP(LCD_BL_DARKCOLOR_2), 0};
42SDL_Color lcd_bl_color2_bright = {RED_CMP(LCD_BL_BRIGHTCOLOR_2),
43 GREEN_CMP(LCD_BL_BRIGHTCOLOR_2),
44 BLUE_CMP(LCD_BL_BRIGHTCOLOR_2), 0};
45#endif
46#endif /* HAVE_BACKLIGHT */
47SDL_Color lcd_color_dark = {RED_CMP(LCD_DARKCOLOR),
48 GREEN_CMP(LCD_DARKCOLOR),
49 BLUE_CMP(LCD_DARKCOLOR), 0};
50SDL_Color lcd_color_bright = {RED_CMP(LCD_BRIGHTCOLOR),
51 GREEN_CMP(LCD_BRIGHTCOLOR),
52 BLUE_CMP(LCD_BRIGHTCOLOR), 0};
53#ifdef HAVE_LCD_SPLIT
54SDL_Color lcd_color2_dark = {RED_CMP(LCD_DARKCOLOR_2),
55 GREEN_CMP(LCD_DARKCOLOR_2),
56 BLUE_CMP(LCD_DARKCOLOR_2), 0};
57SDL_Color lcd_color2_bright = {RED_CMP(LCD_BRIGHTCOLOR_2),
58 GREEN_CMP(LCD_BRIGHTCOLOR_2),
59 BLUE_CMP(LCD_BRIGHTCOLOR_2), 0};
60#endif
61
62#ifdef HAVE_LCD_SPLIT
63#define NUM_SHADES 128
64#else
65#define NUM_SHADES 129
66#endif
67
68#else /* LCD_DEPTH > 8 */
69
70#ifdef HAVE_TRANSFLECTIVE_LCD
71#define BACKLIGHT_OFF_ALPHA 85 /* 1/3 brightness */
72#else
73#define BACKLIGHT_OFF_ALPHA 0 /* pitch black */
74#endif
75
76#endif /* LCD_DEPTH */
77
78#if LCD_DEPTH < 8
79unsigned long (*lcd_ex_getpixel)(int, int) = NULL;
80#endif /* LCD_DEPTH < 8 */
81
82#if LCD_DEPTH == 2
83/* Only defined for positive, non-split LCD for now */
84static const unsigned char colorindex[4] = {128, 85, 43, 0};
85#endif
86
87static unsigned long get_lcd_pixel(int x, int y)
88{
89#if LCD_DEPTH == 1
90#ifdef HAVE_NEGATIVE_LCD
91 return (lcd_framebuffer[y/8][x] & (1 << (y & 7))) ? (NUM_SHADES-1) : 0;
92#else
93 return (lcd_framebuffer[y/8][x] & (1 << (y & 7))) ? 0 : (NUM_SHADES-1);
94#endif
95#elif LCD_DEPTH == 2
96#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
97 return colorindex[(lcd_framebuffer[y][x/4] >> (2 * (~x & 3))) & 3];
98#elif LCD_PIXELFORMAT == VERTICAL_PACKING
99 return colorindex[(lcd_framebuffer[y/4][x] >> (2 * (y & 3))) & 3];
100#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
101 unsigned bits = (lcd_framebuffer[y/8][x] >> (y & 7)) & 0x0101;
102 return colorindex[(bits | (bits >> 7)) & 3];
103#endif
104#elif LCD_DEPTH == 16
105#if LCD_PIXELFORMAT == RGB565SWAPPED
106 unsigned bits = lcd_framebuffer[y][x];
107 return (bits >> 8) | (bits << 8);
108#else
109#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
110 return *(&lcd_framebuffer[0][0]+LCD_HEIGHT*x+y);
111#else
112 return lcd_framebuffer[y][x];
113#endif
114#endif
115#endif
116}
117
118void lcd_update(void)
119{
120 /* update a full screen rect */
121 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
122}
123
124void lcd_update_rect(int x_start, int y_start, int width, int height)
125{
126 sdl_update_rect(lcd_surface, x_start, y_start, width, height,
127 LCD_WIDTH, LCD_HEIGHT, get_lcd_pixel);
128 sdl_gui_update(lcd_surface, x_start, y_start, width,
129 height + LCD_SPLIT_LINES, SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
130 background ? UI_LCD_POSX : 0, background? UI_LCD_POSY : 0);
131}
132
133#ifdef HAVE_BACKLIGHT
134void sim_backlight(int value)
135{
136#if LCD_DEPTH <= 8
137 if (value > 0) {
138 sdl_set_gradient(lcd_surface, &lcd_bl_color_dark,
139 &lcd_bl_color_bright, 0, NUM_SHADES);
140#ifdef HAVE_LCD_SPLIT
141 sdl_set_gradient(lcd_surface, &lcd_bl_color2_dark,
142 &lcd_bl_color2_bright, NUM_SHADES, NUM_SHADES);
143#endif
144 } else {
145 sdl_set_gradient(lcd_surface, &lcd_color_dark,
146 &lcd_color_bright, 0, NUM_SHADES);
147#ifdef HAVE_LCD_SPLIT
148 sdl_set_gradient(lcd_surface, &lcd_color2_dark,
149 &lcd_color2_bright, NUM_SHADES, NUM_SHADES);
150#endif
151 }
152#else /* LCD_DEPTH > 8 */
153 SDL_SetAlpha(lcd_surface, SDL_SRCALPHA, (value * 255) / 100);
154#endif /* LCD_DEPTH */
155
156 sdl_gui_update(lcd_surface, 0, 0, SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
157 SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
158 background ? UI_LCD_POSX : 0, background? UI_LCD_POSY : 0);
159}
160#endif /* HAVE_BACKLIGHT */
161
162/* initialise simulator lcd driver */
163void sim_lcd_init(void)
164{
165#if LCD_DEPTH == 16
166 lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
167 SIM_LCD_WIDTH * display_zoom,
168 SIM_LCD_HEIGHT * display_zoom,
169 LCD_DEPTH, 0, 0, 0, 0);
170#elif LCD_DEPTH <= 8
171 lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
172 SIM_LCD_WIDTH * display_zoom,
173 SIM_LCD_HEIGHT * display_zoom,
174 8, 0, 0, 0, 0);
175
176#ifdef HAVE_BACKLIGHT
177 sdl_set_gradient(lcd_surface, &lcd_bl_color_dark,
178 &lcd_bl_color_bright, 0, NUM_SHADES);
179#ifdef HAVE_LCD_SPLIT
180 sdl_set_gradient(lcd_surface, &lcd_bl_color2_dark,
181 &lcd_bl_color2_bright, NUM_SHADES, NUM_SHADES);
182#endif
183#else /* !HAVE_BACKLIGHT */
184 sdl_set_gradient(lcd_surface, &lcd_color_dark,
185 &lcd_color_bright, 0, NUM_SHADES);
186#ifdef HAVE_LCD_SPLIT
187 sdl_set_gradient(lcd_surface, &lcd_color2_dark,
188 &lcd_color2_bright, NUM_SHADES, NUM_SHADES);
189#endif
190#endif /* !HAVE_BACKLIGHT */
191#endif /* LCD_DEPTH */
192}
193
194#if LCD_DEPTH < 8
195void sim_lcd_ex_init(unsigned long (*getpixel)(int, int))
196{
197 lcd_ex_getpixel = getpixel;
198}
199
200void sim_lcd_ex_update_rect(int x_start, int y_start, int width, int height)
201{
202 if (lcd_ex_getpixel) {
203 sdl_update_rect(lcd_surface, x_start, y_start, width, height,
204 LCD_WIDTH, LCD_HEIGHT, lcd_ex_getpixel);
205 sdl_gui_update(lcd_surface, x_start, y_start, width,
206 height + LCD_SPLIT_LINES, SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
207 background ? UI_LCD_POSX : 0,
208 background ? UI_LCD_POSY : 0);
209 }
210}
211#endif
212
213#ifdef HAVE_LCD_COLOR
214/**
215 * |R| |1.000000 -0.000001 1.402000| |Y'|
216 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
217 * |B| |1.000000 1.772000 0.000000| |Pr|
218 * Scaled, normalized, rounded and tweaked to yield RGB 565:
219 * |R| |74 0 101| |Y' - 16| >> 9
220 * |G| = |74 -24 -51| |Cb - 128| >> 8
221 * |B| |74 128 0| |Cr - 128| >> 9
222 */
223#define YFAC (74)
224#define RVFAC (101)
225#define GUFAC (-24)
226#define GVFAC (-51)
227#define BUFAC (128)
228
229static inline int clamp(int val, int min, int max)
230{
231 if (val < min)
232 val = min;
233 else if (val > max)
234 val = max;
235 return val;
236}
237
238void lcd_yuv_set_options(unsigned options)
239{
240 (void)options;
241}
242
243/* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
244 in the core */
245void lcd_blit_yuv(unsigned char * const src[3],
246 int src_x, int src_y, int stride,
247 int x, int y, int width, int height)
248{
249 const unsigned char *ysrc, *usrc, *vsrc;
250 int linecounter;
251 fb_data *dst, *row_end;
252 long z;
253
254 /* width and height must be >= 2 and an even number */
255 width &= ~1;
256 linecounter = height >> 1;
257
258#if LCD_WIDTH >= LCD_HEIGHT
259 dst = &lcd_framebuffer[y][x];
260 row_end = dst + width;
261#else
262 dst = &lcd_framebuffer[x][LCD_WIDTH - y - 1];
263 row_end = dst + LCD_WIDTH * width;
264#endif
265
266 z = stride * src_y;
267 ysrc = src[0] + z + src_x;
268 usrc = src[1] + (z >> 2) + (src_x >> 1);
269 vsrc = src[2] + (usrc - src[1]);
270
271 /* stride => amount to jump from end of last row to start of next */
272 stride -= width;
273
274 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
275
276 do
277 {
278 do
279 {
280 int y, cb, cr, rv, guv, bu, r, g, b;
281
282 y = YFAC*(*ysrc++ - 16);
283 cb = *usrc++ - 128;
284 cr = *vsrc++ - 128;
285
286 rv = RVFAC*cr;
287 guv = GUFAC*cb + GVFAC*cr;
288 bu = BUFAC*cb;
289
290 r = y + rv;
291 g = y + guv;
292 b = y + bu;
293
294 if ((unsigned)(r | g | b) > 64*256-1)
295 {
296 r = clamp(r, 0, 64*256-1);
297 g = clamp(g, 0, 64*256-1);
298 b = clamp(b, 0, 64*256-1);
299 }
300
301 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
302
303#if LCD_WIDTH >= LCD_HEIGHT
304 dst++;
305#else
306 dst += LCD_WIDTH;
307#endif
308
309 y = YFAC*(*ysrc++ - 16);
310 r = y + rv;
311 g = y + guv;
312 b = y + bu;
313
314 if ((unsigned)(r | g | b) > 64*256-1)
315 {
316 r = clamp(r, 0, 64*256-1);
317 g = clamp(g, 0, 64*256-1);
318 b = clamp(b, 0, 64*256-1);
319 }
320
321 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
322
323#if LCD_WIDTH >= LCD_HEIGHT
324 dst++;
325#else
326 dst += LCD_WIDTH;
327#endif
328 }
329 while (dst < row_end);
330
331 ysrc += stride;
332 usrc -= width >> 1;
333 vsrc -= width >> 1;
334
335#if LCD_WIDTH >= LCD_HEIGHT
336 row_end += LCD_WIDTH;
337 dst += LCD_WIDTH - width;
338#else
339 row_end -= 1;
340 dst -= LCD_WIDTH*width + 1;
341#endif
342
343 do
344 {
345 int y, cb, cr, rv, guv, bu, r, g, b;
346
347 y = YFAC*(*ysrc++ - 16);
348 cb = *usrc++ - 128;
349 cr = *vsrc++ - 128;
350
351 rv = RVFAC*cr;
352 guv = GUFAC*cb + GVFAC*cr;
353 bu = BUFAC*cb;
354
355 r = y + rv;
356 g = y + guv;
357 b = y + bu;
358
359 if ((unsigned)(r | g | b) > 64*256-1)
360 {
361 r = clamp(r, 0, 64*256-1);
362 g = clamp(g, 0, 64*256-1);
363 b = clamp(b, 0, 64*256-1);
364 }
365
366 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
367
368#if LCD_WIDTH >= LCD_HEIGHT
369 dst++;
370#else
371 dst += LCD_WIDTH;
372#endif
373
374 y = YFAC*(*ysrc++ - 16);
375 r = y + rv;
376 g = y + guv;
377 b = y + bu;
378
379 if ((unsigned)(r | g | b) > 64*256-1)
380 {
381 r = clamp(r, 0, 64*256-1);
382 g = clamp(g, 0, 64*256-1);
383 b = clamp(b, 0, 64*256-1);
384 }
385
386 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
387
388#if LCD_WIDTH >= LCD_HEIGHT
389 dst++;
390#else
391 dst += LCD_WIDTH;
392#endif
393 }
394 while (dst < row_end);
395
396 ysrc += stride;
397 usrc += stride >> 1;
398 vsrc += stride >> 1;
399
400#if LCD_WIDTH >= LCD_HEIGHT
401 row_end += LCD_WIDTH;
402 dst += LCD_WIDTH - width;
403#else
404 row_end -= 1;
405 dst -= LCD_WIDTH*width + 1;
406#endif
407 }
408 while (--linecounter > 0);
409
410#if LCD_WIDTH >= LCD_HEIGHT
411 lcd_update_rect(x, y, width, height);
412#else
413 lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
414#endif
415}
416#endif /* HAVE_LCD_COLOR */