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 ****************************************************************************/
31 extern jobject RockboxService_instance
;
33 static jobject RockboxFramebuffer_instance
;
34 static jmethodID java_lcd_update
;
35 static jmethodID java_lcd_update_rect
;
36 static jmethodID java_lcd_init
;
37 static jobject native_buffer
;
40 static int scroll_threshold
;
41 static bool display_on
;
43 /* this might actually be called before lcd_init_device() or even main(), so
44 * be sure to only access static storage initalized at library loading,
46 void connect_with_java(JNIEnv
* env
, jobject fb_instance
)
50 /* Update RockboxFramebuffer_instance */
51 if (!e
->IsSameObject(env
, RockboxFramebuffer_instance
, fb_instance
)) {
52 if (RockboxFramebuffer_instance
!= NULL
)
53 e
->DeleteGlobalRef(env
, RockboxFramebuffer_instance
);
55 RockboxFramebuffer_instance
= e
->NewGlobalRef(env
, fb_instance
);
58 static bool have_class
= false;
61 jclass fb_class
= e
->GetObjectClass(env
, fb_instance
);
62 /* cache update functions */
63 java_lcd_update
= e
->GetMethodID(env
, fb_class
,
66 java_lcd_update_rect
= e
->GetMethodID(env
, fb_class
,
67 "java_lcd_update_rect",
69 jmethodID get_dpi
= e
->GetMethodID(env
, fb_class
,
71 jmethodID thresh
= e
->GetMethodID(env
, fb_class
,
72 "getScrollThreshold", "()I");
73 /* these don't change with new instances so call them now */
74 dpi
= e
->CallIntMethod(env
, fb_instance
, get_dpi
);
75 scroll_threshold
= e
->CallIntMethod(env
, fb_instance
, thresh
);
77 java_lcd_init
= e
->GetMethodID(env
, fb_class
,
79 "(IILjava/nio/ByteBuffer;)V");
81 jobject buffer
= e
->NewDirectByteBuffer(env
,
83 (jlong
)sizeof(lcd_framebuffer
));
85 native_buffer
= e
->NewGlobalRef(env
, buffer
);
89 /* we need to setup parts for the java object every time */
90 (*env
)->CallVoidMethod(env
, fb_instance
, java_lcd_init
,
91 (jint
)LCD_WIDTH
, (jint
)LCD_HEIGHT
, native_buffer
);
96 JNIEnv
*env_ptr
= getJavaEnvironment();
98 (*env_ptr
)->DeleteGlobalRef(env_ptr
, RockboxFramebuffer_instance
);
99 (*env_ptr
)->DeleteGlobalRef(env_ptr
, native_buffer
);
103 * Do nothing here and connect with the java object later (if it isn't already)
105 void lcd_init_device(void)
109 void lcd_update(void)
111 JNIEnv
*env_ptr
= getJavaEnvironment();
114 (*env_ptr
)->CallVoidMethod(env_ptr
, RockboxFramebuffer_instance
,
118 void lcd_update_rect(int x
, int y
, int width
, int height
)
120 JNIEnv
*env_ptr
= getJavaEnvironment();
123 (*env_ptr
)->CallVoidMethod(env_ptr
, RockboxFramebuffer_instance
,
124 java_lcd_update_rect
, x
, y
, width
, height
);
128 * this is called when the surface is created, which called is everytime
129 * the activity is brought in front and the RockboxFramebuffer gains focus
131 * Note this is considered interrupt context
133 JNIEXPORT
void JNICALL
134 Java_org_rockbox_RockboxFramebuffer_surfaceCreated(JNIEnv
*env
, jobject
this,
135 jobject surfaceholder
)
138 /* possibly a new instance - reconnect */
139 connect_with_java(env
, this);
142 send_event(LCD_EVENT_ACTIVATION
, NULL
);
143 /* Force an update, since the newly created surface is initially black
144 * waiting for the next normal update results in a longish black screen */
145 queue_post(&button_queue
, BUTTON_FORCE_REDRAW
, 0);
149 * the surface is destroyed everytime the RockboxFramebuffer loses focus and
152 JNIEXPORT
void JNICALL
153 Java_org_rockbox_RockboxFramebuffer_surfaceDestroyed(JNIEnv
*e
, jobject
this,
154 jobject surfaceholder
)
156 (void)e
; (void)this; (void)surfaceholder
;
161 bool lcd_active(void)
166 int lcd_get_dpi(void)
171 int touchscreen_get_scroll_threshold(void)
173 return scroll_threshold
;
176 /* below is a plain copy from lcd-sdl.c */
179 * |R| |1.000000 -0.000001 1.402000| |Y'|
180 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
181 * |B| |1.000000 1.772000 0.000000| |Pr|
182 * Scaled, normalized, rounded and tweaked to yield RGB 565:
183 * |R| |74 0 101| |Y' - 16| >> 9
184 * |G| = |74 -24 -51| |Cb - 128| >> 8
185 * |B| |74 128 0| |Cr - 128| >> 9
193 static inline int clamp(int val
, int min
, int max
)
202 void lcd_yuv_set_options(unsigned options
)
207 /* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
209 void lcd_blit_yuv(unsigned char * const src
[3],
210 int src_x
, int src_y
, int stride
,
211 int x
, int y
, int width
, int height
)
213 const unsigned char *ysrc
, *usrc
, *vsrc
;
215 fb_data
*dst
, *row_end
;
218 /* width and height must be >= 2 and an even number */
220 linecounter
= height
>> 1;
222 #if LCD_WIDTH >= LCD_HEIGHT
223 dst
= &lcd_framebuffer
[y
][x
];
224 row_end
= dst
+ width
;
226 dst
= &lcd_framebuffer
[x
][LCD_WIDTH
- y
- 1];
227 row_end
= dst
+ LCD_WIDTH
* width
;
231 ysrc
= src
[0] + z
+ src_x
;
232 usrc
= src
[1] + (z
>> 2) + (src_x
>> 1);
233 vsrc
= src
[2] + (usrc
- src
[1]);
235 /* stride => amount to jump from end of last row to start of next */
238 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
244 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
246 y
= YFAC
*(*ysrc
++ - 16);
251 guv
= GUFAC
*cb
+ GVFAC
*cr
;
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
273 y
= YFAC
*(*ysrc
++ - 16);
278 if ((unsigned)(r
| g
| b
) > 64*256-1)
280 r
= clamp(r
, 0, 64*256-1);
281 g
= clamp(g
, 0, 64*256-1);
282 b
= clamp(b
, 0, 64*256-1);
285 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
287 #if LCD_WIDTH >= LCD_HEIGHT
293 while (dst
< row_end
);
299 #if LCD_WIDTH >= LCD_HEIGHT
300 row_end
+= LCD_WIDTH
;
301 dst
+= LCD_WIDTH
- width
;
304 dst
-= LCD_WIDTH
*width
+ 1;
309 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
311 y
= YFAC
*(*ysrc
++ - 16);
316 guv
= GUFAC
*cb
+ GVFAC
*cr
;
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
338 y
= YFAC
*(*ysrc
++ - 16);
343 if ((unsigned)(r
| g
| b
) > 64*256-1)
345 r
= clamp(r
, 0, 64*256-1);
346 g
= clamp(g
, 0, 64*256-1);
347 b
= clamp(b
, 0, 64*256-1);
350 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
352 #if LCD_WIDTH >= LCD_HEIGHT
358 while (dst
< row_end
);
364 #if LCD_WIDTH >= LCD_HEIGHT
365 row_end
+= LCD_WIDTH
;
366 dst
+= LCD_WIDTH
- width
;
369 dst
-= LCD_WIDTH
*width
+ 1;
372 while (--linecounter
> 0);
374 #if LCD_WIDTH >= LCD_HEIGHT
375 lcd_update_rect(x
, y
, width
, height
);
377 lcd_update_rect(LCD_WIDTH
- y
- height
, x
, height
, width
);