Android:
[kugel-rb.git] / firmware / target / hosted / android / lcd-android.c
blobc9bd0a12547317aac3bbe72d7b513a8ddce94123
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (c) 2010 Thomas Martitz
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 #include <jni.h>
24 #include <string.h>
25 #include "config.h"
26 #include "system.h"
27 #include "kernel.h"
28 #include "lcd.h"
29 #include "button.h"
31 extern JNIEnv *env_ptr;
32 extern jobject RockboxService_instance;
34 static jobject RockboxFramebuffer_instance;
35 static jmethodID java_lcd_update;
36 static jmethodID java_lcd_update_rect;
37 static jmethodID java_lcd_init;
38 static jobject native_buffer;
40 static int dpi;
41 static int scroll_threshold;
42 static bool display_on;
44 /* this might actually be called before lcd_init_device() or even main(), so
45 * be sure to only access static storage initalized at library loading,
46 * and not more */
47 void connect_with_java(JNIEnv* env, jobject fb_instance)
49 JNIEnv e = *env;
50 static bool have_class;
51 RockboxFramebuffer_instance = fb_instance;
52 if (!have_class)
54 jclass fb_class = e->GetObjectClass(env, fb_instance);
55 /* cache update functions */
56 java_lcd_update = e->GetMethodID(env, fb_class,
57 "java_lcd_update",
58 "()V");
59 java_lcd_update_rect = e->GetMethodID(env, fb_class,
60 "java_lcd_update_rect",
61 "(IIII)V");
62 jmethodID get_dpi = e->GetMethodID(env, fb_class,
63 "getDpi", "()I");
64 jmethodID thresh = e->GetMethodID(env, fb_class,
65 "getScrollThreshold", "()I");
66 /* these don't change with new instances so call them now */
67 dpi = e->CallIntMethod(env, fb_instance, get_dpi);
68 scroll_threshold = e->CallIntMethod(env, fb_instance, thresh);
70 java_lcd_init = e->GetMethodID(env, fb_class,
71 "java_lcd_init",
72 "(IILjava/nio/ByteBuffer;)V");
74 native_buffer = e->NewDirectByteBuffer(env,
75 lcd_framebuffer,
76 (jlong)sizeof(lcd_framebuffer));
77 have_class = true;
79 /* we need to setup parts for the java object every time */
80 (*env)->CallVoidMethod(env, fb_instance, java_lcd_init,
81 (jint)LCD_WIDTH, (jint)LCD_HEIGHT, native_buffer);
85 * Do nothing here and connect with the java object later (if it isn't already)
87 void lcd_init_device(void)
89 /* must not draw until surface is created */
90 display_on = false;
93 void lcd_update(void)
95 if (display_on)
96 (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance,
97 java_lcd_update);
100 void lcd_update_rect(int x, int y, int width, int height)
102 if (display_on)
103 (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance,
104 java_lcd_update_rect, x, y, width, height);
108 * this is called when the surface is created, which called is everytime
109 * the activity is brought in front and the RockboxFramebuffer gains focus
111 * Note this is considered interrupt context
113 JNIEXPORT void JNICALL
114 Java_org_rockbox_RockboxFramebuffer_surfaceCreated(JNIEnv *env, jobject this,
115 jobject surfaceholder)
117 (void)surfaceholder;
118 /* possibly a new instance - reconnect */
119 connect_with_java(env, this);
120 display_on = true;
122 send_event(LCD_EVENT_ACTIVATION, NULL);
123 /* Force an update, since the newly created surface is initially black
124 * waiting for the next normal update results in a longish black screen */
125 queue_post(&button_queue, BUTTON_FORCE_REDRAW, 0);
129 * the surface is destroyed everytime the RockboxFramebuffer loses focus and
130 * goes invisible
132 JNIEXPORT void JNICALL
133 Java_org_rockbox_RockboxFramebuffer_surfaceDestroyed(JNIEnv *e, jobject this,
134 jobject surfaceholder)
136 (void)e; (void)this; (void)surfaceholder;
138 display_on = false;
141 bool lcd_active(void)
143 return display_on;
146 int lcd_get_dpi(void)
148 return dpi;
151 int touchscreen_get_scroll_threshold(void)
153 return scroll_threshold;
156 /* below is a plain copy from lcd-sdl.c */
159 * |R| |1.000000 -0.000001 1.402000| |Y'|
160 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
161 * |B| |1.000000 1.772000 0.000000| |Pr|
162 * Scaled, normalized, rounded and tweaked to yield RGB 565:
163 * |R| |74 0 101| |Y' - 16| >> 9
164 * |G| = |74 -24 -51| |Cb - 128| >> 8
165 * |B| |74 128 0| |Cr - 128| >> 9
167 #define YFAC (74)
168 #define RVFAC (101)
169 #define GUFAC (-24)
170 #define GVFAC (-51)
171 #define BUFAC (128)
173 static inline int clamp(int val, int min, int max)
175 if (val < min)
176 val = min;
177 else if (val > max)
178 val = max;
179 return val;
182 void lcd_yuv_set_options(unsigned options)
184 (void)options;
187 /* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
188 in the core */
189 void lcd_blit_yuv(unsigned char * const src[3],
190 int src_x, int src_y, int stride,
191 int x, int y, int width, int height)
193 const unsigned char *ysrc, *usrc, *vsrc;
194 int linecounter;
195 fb_data *dst, *row_end;
196 long z;
198 /* width and height must be >= 2 and an even number */
199 width &= ~1;
200 linecounter = height >> 1;
202 #if LCD_WIDTH >= LCD_HEIGHT
203 dst = &lcd_framebuffer[y][x];
204 row_end = dst + width;
205 #else
206 dst = &lcd_framebuffer[x][LCD_WIDTH - y - 1];
207 row_end = dst + LCD_WIDTH * width;
208 #endif
210 z = stride * src_y;
211 ysrc = src[0] + z + src_x;
212 usrc = src[1] + (z >> 2) + (src_x >> 1);
213 vsrc = src[2] + (usrc - src[1]);
215 /* stride => amount to jump from end of last row to start of next */
216 stride -= width;
218 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
224 int y, cb, cr, rv, guv, bu, r, g, b;
226 y = YFAC*(*ysrc++ - 16);
227 cb = *usrc++ - 128;
228 cr = *vsrc++ - 128;
230 rv = RVFAC*cr;
231 guv = GUFAC*cb + GVFAC*cr;
232 bu = BUFAC*cb;
234 r = y + rv;
235 g = y + guv;
236 b = y + bu;
238 if ((unsigned)(r | g | b) > 64*256-1)
240 r = clamp(r, 0, 64*256-1);
241 g = clamp(g, 0, 64*256-1);
242 b = clamp(b, 0, 64*256-1);
245 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
247 #if LCD_WIDTH >= LCD_HEIGHT
248 dst++;
249 #else
250 dst += LCD_WIDTH;
251 #endif
253 y = YFAC*(*ysrc++ - 16);
254 r = y + rv;
255 g = y + guv;
256 b = y + bu;
258 if ((unsigned)(r | g | b) > 64*256-1)
260 r = clamp(r, 0, 64*256-1);
261 g = clamp(g, 0, 64*256-1);
262 b = clamp(b, 0, 64*256-1);
265 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
267 #if LCD_WIDTH >= LCD_HEIGHT
268 dst++;
269 #else
270 dst += LCD_WIDTH;
271 #endif
273 while (dst < row_end);
275 ysrc += stride;
276 usrc -= width >> 1;
277 vsrc -= width >> 1;
279 #if LCD_WIDTH >= LCD_HEIGHT
280 row_end += LCD_WIDTH;
281 dst += LCD_WIDTH - width;
282 #else
283 row_end -= 1;
284 dst -= LCD_WIDTH*width + 1;
285 #endif
289 int y, cb, cr, rv, guv, bu, r, g, b;
291 y = YFAC*(*ysrc++ - 16);
292 cb = *usrc++ - 128;
293 cr = *vsrc++ - 128;
295 rv = RVFAC*cr;
296 guv = GUFAC*cb + GVFAC*cr;
297 bu = BUFAC*cb;
299 r = y + rv;
300 g = y + guv;
301 b = y + bu;
303 if ((unsigned)(r | g | b) > 64*256-1)
305 r = clamp(r, 0, 64*256-1);
306 g = clamp(g, 0, 64*256-1);
307 b = clamp(b, 0, 64*256-1);
310 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
312 #if LCD_WIDTH >= LCD_HEIGHT
313 dst++;
314 #else
315 dst += LCD_WIDTH;
316 #endif
318 y = YFAC*(*ysrc++ - 16);
319 r = y + rv;
320 g = y + guv;
321 b = y + bu;
323 if ((unsigned)(r | g | b) > 64*256-1)
325 r = clamp(r, 0, 64*256-1);
326 g = clamp(g, 0, 64*256-1);
327 b = clamp(b, 0, 64*256-1);
330 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
332 #if LCD_WIDTH >= LCD_HEIGHT
333 dst++;
334 #else
335 dst += LCD_WIDTH;
336 #endif
338 while (dst < row_end);
340 ysrc += stride;
341 usrc += stride >> 1;
342 vsrc += stride >> 1;
344 #if LCD_WIDTH >= LCD_HEIGHT
345 row_end += LCD_WIDTH;
346 dst += LCD_WIDTH - width;
347 #else
348 row_end -= 1;
349 dst -= LCD_WIDTH*width + 1;
350 #endif
352 while (--linecounter > 0);
354 #if LCD_WIDTH >= LCD_HEIGHT
355 lcd_update_rect(x, y, width, height);
356 #else
357 lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
358 #endif