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 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
;
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,
47 void connect_with_java(JNIEnv
* env
, jobject fb_instance
)
50 static bool have_class
;
51 RockboxFramebuffer_instance
= fb_instance
;
54 jclass fb_class
= e
->GetObjectClass(env
, fb_instance
);
55 /* cache update functions */
56 java_lcd_update
= e
->GetMethodID(env
, fb_class
,
59 java_lcd_update_rect
= e
->GetMethodID(env
, fb_class
,
60 "java_lcd_update_rect",
62 jmethodID get_dpi
= e
->GetMethodID(env
, fb_class
,
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
,
72 "(IILjava/nio/ByteBuffer;)V");
74 native_buffer
= e
->NewDirectByteBuffer(env
,
76 (jlong
)sizeof(lcd_framebuffer
));
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 */
96 (*env_ptr
)->CallVoidMethod(env_ptr
, RockboxFramebuffer_instance
,
100 void lcd_update_rect(int x
, int y
, int width
, int height
)
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
)
118 /* possibly a new instance - reconnect */
119 connect_with_java(env
, this);
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
132 JNIEXPORT
void JNICALL
133 Java_org_rockbox_RockboxFramebuffer_surfaceDestroyed(JNIEnv
*e
, jobject
this,
134 jobject surfaceholder
)
136 (void)e
; (void)this; (void)surfaceholder
;
141 bool lcd_active(void)
146 int lcd_get_dpi(void)
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
173 static inline int clamp(int val
, int min
, int max
)
182 void lcd_yuv_set_options(unsigned options
)
187 /* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
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
;
195 fb_data
*dst
, *row_end
;
198 /* width and height must be >= 2 and an even number */
200 linecounter
= height
>> 1;
202 #if LCD_WIDTH >= LCD_HEIGHT
203 dst
= &lcd_framebuffer
[y
][x
];
204 row_end
= dst
+ width
;
206 dst
= &lcd_framebuffer
[x
][LCD_WIDTH
- y
- 1];
207 row_end
= dst
+ LCD_WIDTH
* width
;
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 */
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);
231 guv
= GUFAC
*cb
+ GVFAC
*cr
;
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
253 y
= YFAC
*(*ysrc
++ - 16);
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 while (dst
< row_end
);
279 #if LCD_WIDTH >= LCD_HEIGHT
280 row_end
+= LCD_WIDTH
;
281 dst
+= LCD_WIDTH
- width
;
284 dst
-= LCD_WIDTH
*width
+ 1;
289 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
291 y
= YFAC
*(*ysrc
++ - 16);
296 guv
= GUFAC
*cb
+ GVFAC
*cr
;
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
318 y
= YFAC
*(*ysrc
++ - 16);
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 while (dst
< row_end
);
344 #if LCD_WIDTH >= LCD_HEIGHT
345 row_end
+= LCD_WIDTH
;
346 dst
+= LCD_WIDTH
- width
;
349 dst
-= LCD_WIDTH
*width
+ 1;
352 while (--linecounter
> 0);
354 #if LCD_WIDTH >= LCD_HEIGHT
355 lcd_update_rect(x
, y
, width
, height
);
357 lcd_update_rect(LCD_WIDTH
- y
- height
, x
, height
, width
);