1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
29 extern JNIEnv
*env_ptr
;
30 extern jclass RockboxService_class
;
31 extern jobject RockboxService_instance
;
33 static jclass RockboxFramebuffer_class
;
34 static jobject RockboxFramebuffer_instance
;
35 static jmethodID postInvalidate1
;
36 static jmethodID postInvalidate2
;
38 static bool display_on
;
40 static int scroll_threshold
;
41 static struct wakeup lcd_wakeup
;
42 static struct mutex lcd_mtx
;
44 void lcd_init_device(void)
47 wakeup_init(&lcd_wakeup
);
49 RockboxFramebuffer_class
= e
->FindClass(env_ptr
,
50 "org/rockbox/RockboxFramebuffer");
51 /* instantiate a RockboxFramebuffer instance
53 * Pass lcd width and height and our framebuffer so the java layer
54 * can create a Bitmap which directly maps to it
57 /* map the framebuffer to a ByteBuffer, this way lcd updates will
58 * be directly feched from the framebuffer */
59 jobject buf
= e
->NewDirectByteBuffer(env_ptr
,
61 (jlong
)sizeof(lcd_framebuffer
));
63 jmethodID constructor
= e
->GetMethodID(env_ptr
,
64 RockboxFramebuffer_class
,
66 "(Landroid/content/Context;" /* Service */
67 "II" /* lcd width/height */
68 "Ljava/nio/ByteBuffer;)V"); /* ByteBuffer */
70 RockboxFramebuffer_instance
= e
->NewObject(env_ptr
,
71 RockboxFramebuffer_class
,
73 RockboxService_instance
,
78 /* cache update functions */
79 postInvalidate1
= (*env_ptr
)->GetMethodID(env_ptr
,
80 RockboxFramebuffer_class
,
83 postInvalidate2
= (*env_ptr
)->GetMethodID(env_ptr
,
84 RockboxFramebuffer_class
,
88 jmethodID get_dpi
= e
->GetMethodID(env_ptr
,
89 RockboxFramebuffer_class
,
92 jmethodID get_scroll_threshold
93 = e
->GetMethodID(env_ptr
,
94 RockboxFramebuffer_class
,
95 "getScrollThreshold", "()I");
97 dpi
= e
->CallIntMethod(env_ptr
, RockboxFramebuffer_instance
,
99 scroll_threshold
= e
->CallIntMethod(env_ptr
, RockboxFramebuffer_instance
,
100 get_scroll_threshold
);
104 /* the update mechanism is asynchronous since
105 * onDraw() must be called from the UI thread
107 * The Rockbox thread calling lcd_update() has to wait
108 * for the update to complete, so that it's synchronous,
109 * and we need to notify it (we could wait in the java layer, but
110 * that'd block the other Rockbox threads too)
112 * That should give more smoonth animations
114 void lcd_update(void)
116 /* tell the system we're ready for drawing */
119 mutex_lock(&lcd_mtx
);
120 (*env_ptr
)->CallVoidMethod(env_ptr
, RockboxFramebuffer_instance
, postInvalidate1
);
121 wakeup_wait(&lcd_wakeup
, TIMEOUT_BLOCK
);
122 mutex_unlock(&lcd_mtx
);
126 void lcd_update_rect(int x
, int y
, int width
, int height
)
130 mutex_lock(&lcd_mtx
);
131 (*env_ptr
)->CallVoidMethod(env_ptr
, RockboxFramebuffer_instance
, postInvalidate2
,
132 (jint
)x
, (jint
)y
, (jint
)x
+width
, (jint
)y
+height
);
133 wakeup_wait(&lcd_wakeup
, TIMEOUT_BLOCK
);
134 mutex_unlock(&lcd_mtx
);
138 JNIEXPORT
void JNICALL
139 Java_org_rockbox_RockboxFramebuffer_post_1update_1done(JNIEnv
*e
, jobject
this)
143 wakeup_signal(&lcd_wakeup
);
146 bool lcd_active(void)
151 int lcd_get_dpi(void)
156 int touchscreen_get_scroll_threshold(void)
158 return scroll_threshold
;
162 * (un)block lcd updates.
164 * Notice: This is called from the activity thread, so take it
165 * as interrupt context and take care what the event callback does
166 * (it shouldn't block in particular
168 * the 1s are needed due to strange naming conventions...
170 JNIEXPORT
void JNICALL
171 Java_org_rockbox_RockboxFramebuffer_set_1lcd_1active(JNIEnv
*e
,
177 display_on
= active
!= 0;
179 send_event(LCD_EVENT_ACTIVATION
, NULL
);
181 /* below is a plain copy from lcd-sdl.c */
184 * |R| |1.000000 -0.000001 1.402000| |Y'|
185 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
186 * |B| |1.000000 1.772000 0.000000| |Pr|
187 * Scaled, normalized, rounded and tweaked to yield RGB 565:
188 * |R| |74 0 101| |Y' - 16| >> 9
189 * |G| = |74 -24 -51| |Cb - 128| >> 8
190 * |B| |74 128 0| |Cr - 128| >> 9
198 static inline int clamp(int val
, int min
, int max
)
207 void lcd_yuv_set_options(unsigned options
)
212 /* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
214 void lcd_blit_yuv(unsigned char * const src
[3],
215 int src_x
, int src_y
, int stride
,
216 int x
, int y
, int width
, int height
)
218 const unsigned char *ysrc
, *usrc
, *vsrc
;
220 fb_data
*dst
, *row_end
;
223 /* width and height must be >= 2 and an even number */
225 linecounter
= height
>> 1;
227 #if LCD_WIDTH >= LCD_HEIGHT
228 dst
= &lcd_framebuffer
[y
][x
];
229 row_end
= dst
+ width
;
231 dst
= &lcd_framebuffer
[x
][LCD_WIDTH
- y
- 1];
232 row_end
= dst
+ LCD_WIDTH
* width
;
236 ysrc
= src
[0] + z
+ src_x
;
237 usrc
= src
[1] + (z
>> 2) + (src_x
>> 1);
238 vsrc
= src
[2] + (usrc
- src
[1]);
240 /* stride => amount to jump from end of last row to start of next */
243 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
249 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
251 y
= YFAC
*(*ysrc
++ - 16);
256 guv
= GUFAC
*cb
+ GVFAC
*cr
;
263 if ((unsigned)(r
| g
| b
) > 64*256-1)
265 r
= clamp(r
, 0, 64*256-1);
266 g
= clamp(g
, 0, 64*256-1);
267 b
= clamp(b
, 0, 64*256-1);
270 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
272 #if LCD_WIDTH >= LCD_HEIGHT
278 y
= YFAC
*(*ysrc
++ - 16);
283 if ((unsigned)(r
| g
| b
) > 64*256-1)
285 r
= clamp(r
, 0, 64*256-1);
286 g
= clamp(g
, 0, 64*256-1);
287 b
= clamp(b
, 0, 64*256-1);
290 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
292 #if LCD_WIDTH >= LCD_HEIGHT
298 while (dst
< row_end
);
304 #if LCD_WIDTH >= LCD_HEIGHT
305 row_end
+= LCD_WIDTH
;
306 dst
+= LCD_WIDTH
- width
;
309 dst
-= LCD_WIDTH
*width
+ 1;
314 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
316 y
= YFAC
*(*ysrc
++ - 16);
321 guv
= GUFAC
*cb
+ GVFAC
*cr
;
328 if ((unsigned)(r
| g
| b
) > 64*256-1)
330 r
= clamp(r
, 0, 64*256-1);
331 g
= clamp(g
, 0, 64*256-1);
332 b
= clamp(b
, 0, 64*256-1);
335 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
337 #if LCD_WIDTH >= LCD_HEIGHT
343 y
= YFAC
*(*ysrc
++ - 16);
348 if ((unsigned)(r
| g
| b
) > 64*256-1)
350 r
= clamp(r
, 0, 64*256-1);
351 g
= clamp(g
, 0, 64*256-1);
352 b
= clamp(b
, 0, 64*256-1);
355 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
357 #if LCD_WIDTH >= LCD_HEIGHT
363 while (dst
< row_end
);
369 #if LCD_WIDTH >= LCD_HEIGHT
370 row_end
+= LCD_WIDTH
;
371 dst
+= LCD_WIDTH
- width
;
374 dst
-= LCD_WIDTH
*width
+ 1;
377 while (--linecounter
> 0);
379 #if LCD_WIDTH >= LCD_HEIGHT
380 lcd_update_rect(x
, y
, width
, height
);
382 lcd_update_rect(LCD_WIDTH
- y
- height
, x
, height
, width
);