summaryrefslogtreecommitdiff
path: root/firmware/target/hosted/android/lcd-android.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/hosted/android/lcd-android.c')
-rw-r--r--firmware/target/hosted/android/lcd-android.c140
1 files changed, 59 insertions, 81 deletions
diff --git a/firmware/target/hosted/android/lcd-android.c b/firmware/target/hosted/android/lcd-android.c
index 92e8f5b96f..f719329819 100644
--- a/firmware/target/hosted/android/lcd-android.c
+++ b/firmware/target/hosted/android/lcd-android.c
@@ -21,10 +21,12 @@
21 21
22 22
23#include <jni.h> 23#include <jni.h>
24#include <string.h>
24#include "config.h" 25#include "config.h"
25#include "system.h" 26#include "system.h"
26#include "kernel.h" 27#include "kernel.h"
27#include "lcd.h" 28#include "lcd.h"
29#include "button.h"
28 30
29extern JNIEnv *env_ptr; 31extern JNIEnv *env_ptr;
30extern jclass RockboxService_class; 32extern jclass RockboxService_class;
@@ -32,57 +34,48 @@ extern jobject RockboxService_instance;
32 34
33static jclass RockboxFramebuffer_class; 35static jclass RockboxFramebuffer_class;
34static jobject RockboxFramebuffer_instance; 36static jobject RockboxFramebuffer_instance;
35static jmethodID postInvalidate1; 37static jmethodID java_lcd_update;
36static jmethodID postInvalidate2; 38static jmethodID java_lcd_update_rect;
37 39
38static bool display_on;
39static int dpi; 40static int dpi;
40static int scroll_threshold; 41static int scroll_threshold;
41static struct wakeup lcd_wakeup; 42static bool display_on;
42static struct mutex lcd_mtx;
43 43
44void lcd_init_device(void) 44void lcd_init_device(void)
45{ 45{
46 JNIEnv e = *env_ptr; 46 JNIEnv e = *env_ptr;
47 wakeup_init(&lcd_wakeup); 47 /* get existing instance from the Service */
48 mutex_init(&lcd_mtx); 48 jmethodID get_fb = e->GetMethodID(env_ptr, RockboxService_class, "get_fb",
49 RockboxFramebuffer_class = e->FindClass(env_ptr, 49 "()Lorg/rockbox/RockboxFramebuffer;");
50 "org/rockbox/RockboxFramebuffer"); 50 RockboxFramebuffer_instance = e->CallObjectMethod(env_ptr,
51 /* instantiate a RockboxFramebuffer instance 51 RockboxService_instance,
52 * 52 get_fb);
53 * Pass lcd width and height and our framebuffer so the java layer 53 RockboxFramebuffer_class = (*env_ptr)->GetObjectClass(env_ptr,
54 * can create a Bitmap which directly maps to it 54 RockboxFramebuffer_instance);
55 **/ 55
56 56 /* Get init function and set up what's left from the constructor */
57 /* map the framebuffer to a ByteBuffer, this way lcd updates will 57 jmethodID java_lcd_init = (*env_ptr)->GetMethodID(env_ptr,
58 * be directly feched from the framebuffer */ 58 RockboxFramebuffer_class,
59 "java_lcd_init",
60 "(IILjava/nio/ByteBuffer;)V");
61
59 jobject buf = e->NewDirectByteBuffer(env_ptr, 62 jobject buf = e->NewDirectByteBuffer(env_ptr,
60 lcd_framebuffer, 63 lcd_framebuffer,
61 (jlong)sizeof(lcd_framebuffer)); 64 (jlong)sizeof(lcd_framebuffer));
62 65
63 jmethodID constructor = e->GetMethodID(env_ptr, 66 e->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, java_lcd_init,
64 RockboxFramebuffer_class,
65 "<init>",
66 "(Landroid/content/Context;" /* Service */
67 "II" /* lcd width/height */
68 "Ljava/nio/ByteBuffer;)V"); /* ByteBuffer */
69
70 RockboxFramebuffer_instance = e->NewObject(env_ptr,
71 RockboxFramebuffer_class,
72 constructor,
73 RockboxService_instance,
74 (jint)LCD_WIDTH, 67 (jint)LCD_WIDTH,
75 (jint)LCD_HEIGHT, 68 (jint)LCD_HEIGHT,
76 buf); 69 buf);
77 70
78 /* cache update functions */ 71 /* cache update functions */
79 postInvalidate1 = (*env_ptr)->GetMethodID(env_ptr, 72 java_lcd_update = (*env_ptr)->GetMethodID(env_ptr,
80 RockboxFramebuffer_class, 73 RockboxFramebuffer_class,
81 "postInvalidate", 74 "java_lcd_update",
82 "()V"); 75 "()V");
83 postInvalidate2 = (*env_ptr)->GetMethodID(env_ptr, 76 java_lcd_update_rect = (*env_ptr)->GetMethodID(env_ptr,
84 RockboxFramebuffer_class, 77 RockboxFramebuffer_class,
85 "postInvalidate", 78 "java_lcd_update_rect",
86 "(IIII)V"); 79 "(IIII)V");
87 80
88 jmethodID get_dpi = e->GetMethodID(env_ptr, 81 jmethodID get_dpi = e->GetMethodID(env_ptr,
@@ -98,49 +91,54 @@ void lcd_init_device(void)
98 get_dpi); 91 get_dpi);
99 scroll_threshold = e->CallIntMethod(env_ptr, RockboxFramebuffer_instance, 92 scroll_threshold = e->CallIntMethod(env_ptr, RockboxFramebuffer_instance,
100 get_scroll_threshold); 93 get_scroll_threshold);
101 display_on = true; 94 /* must not draw until surface is created */
95 display_on = false;
102} 96}
103 97
104/* the update mechanism is asynchronous since
105 * onDraw() must be called from the UI thread
106 *
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)
111 *
112 * That should give more smoonth animations
113 */
114void lcd_update(void) 98void lcd_update(void)
115{ 99{
116 /* tell the system we're ready for drawing */
117 if (display_on) 100 if (display_on)
118 { 101 (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance,
119 mutex_lock(&lcd_mtx); 102 java_lcd_update);
120 (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, postInvalidate1);
121 wakeup_wait(&lcd_wakeup, TIMEOUT_BLOCK);
122 mutex_unlock(&lcd_mtx);
123 }
124} 103}
125 104
126void lcd_update_rect(int x, int y, int width, int height) 105void lcd_update_rect(int x, int y, int width, int height)
127{ 106{
128 if (display_on) 107 if (display_on)
129 { 108 (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance,
130 mutex_lock(&lcd_mtx); 109 java_lcd_update_rect, x, y, width, height);
131 (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, postInvalidate2, 110}
132 (jint)x, (jint)y, (jint)x+width, (jint)y+height); 111
133 wakeup_wait(&lcd_wakeup, TIMEOUT_BLOCK); 112/*
134 mutex_unlock(&lcd_mtx); 113 * this is called when the surface is created, which called is everytime
135 } 114 * the activity is brought in front and the RockboxFramebuffer gains focus
115 *
116 * Note this is considered interrupt context
117 */
118JNIEXPORT void JNICALL
119Java_org_rockbox_RockboxFramebuffer_surfaceCreated(JNIEnv *e, jobject this,
120 jobject surfaceholder)
121{
122 (void)e; (void)this; (void)surfaceholder;
123
124 display_on = true;
125 send_event(LCD_EVENT_ACTIVATION, NULL);
126 /* Force an update, since the newly created surface is initially black
127 * waiting for the next normal update results in a longish black screen */
128 queue_post(&button_queue, BUTTON_FORCE_REDRAW, 0);
136} 129}
137 130
131/*
132 * the surface is destroyed everytime the RockboxFramebuffer loses focus and
133 * goes invisible
134 */
138JNIEXPORT void JNICALL 135JNIEXPORT void JNICALL
139Java_org_rockbox_RockboxFramebuffer_post_1update_1done(JNIEnv *e, jobject this) 136Java_org_rockbox_RockboxFramebuffer_surfaceDestroyed(JNIEnv *e, jobject this,
137 jobject surfaceholder)
140{ 138{
141 (void)e; 139 (void)e; (void)this; (void)surfaceholder;
142 (void)this; 140
143 wakeup_signal(&lcd_wakeup); 141 display_on = false;
144} 142}
145 143
146bool lcd_active(void) 144bool lcd_active(void)
@@ -158,26 +156,6 @@ int touchscreen_get_scroll_threshold(void)
158 return scroll_threshold; 156 return scroll_threshold;
159} 157}
160 158
161/*
162 * (un)block lcd updates.
163 *
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
167 *
168 * the 1s are needed due to strange naming conventions...
169 **/
170JNIEXPORT void JNICALL
171Java_org_rockbox_RockboxFramebuffer_set_1lcd_1active(JNIEnv *e,
172 jobject this,
173 jint active)
174{
175 (void)e;
176 (void)this;
177 display_on = active != 0;
178 if (active)
179 send_event(LCD_EVENT_ACTIVATION, NULL);
180}
181/* below is a plain copy from lcd-sdl.c */ 159/* below is a plain copy from lcd-sdl.c */
182 160
183/** 161/**