summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2010-12-02 23:50:50 +0000
committerThomas Martitz <kugel@rockbox.org>2010-12-02 23:50:50 +0000
commit55b58a3f30270ce8df7c1b51720bb777e7972c7f (patch)
tree46a3be432fd4e75b5604905338800e66a70d0ce5
parent1d425bf1e6c0346db02f03be496ecef749b49c22 (diff)
downloadrockbox-55b58a3f30270ce8df7c1b51720bb777e7972c7f.tar.gz
rockbox-55b58a3f30270ce8df7c1b51720bb777e7972c7f.zip
Android: Make lcd updates synchronous, doesn't make it faster but smoother (no updates are skipped) and guaranteed to be glitch free.
test_fps can also now report reasonable numbers: ~62 fps for both 1/1 and 1/4 updates (was 300-400 previously). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28728 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--android/src/org/rockbox/RockboxFramebuffer.java23
-rw-r--r--firmware/target/hosted/android/lcd-android.c45
2 files changed, 43 insertions, 25 deletions
diff --git a/android/src/org/rockbox/RockboxFramebuffer.java b/android/src/org/rockbox/RockboxFramebuffer.java
index 8c99725e7d..18415562f3 100644
--- a/android/src/org/rockbox/RockboxFramebuffer.java
+++ b/android/src/org/rockbox/RockboxFramebuffer.java
@@ -28,6 +28,7 @@ import org.rockbox.Helper.MediaButtonReceiver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
@@ -38,6 +39,7 @@ import android.view.ViewConfiguration;
public class RockboxFramebuffer extends View
{
private Bitmap btm;
+ private Rect rect;
private ByteBuffer native_buf;
private MediaButtonReceiver media_monitor;
private final DisplayMetrics metrics;
@@ -52,6 +54,7 @@ public class RockboxFramebuffer extends View
setFocusableInTouchMode(true);
setClickable(true);
btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565);
+ rect = new Rect();
native_buf = native_fb;
media_monitor = new MediaButtonReceiver(c);
media_monitor.register();
@@ -64,22 +67,11 @@ public class RockboxFramebuffer extends View
public void onDraw(Canvas c)
{
- c.drawBitmap(btm, 0.0f, 0.0f, null);
- }
-
- @SuppressWarnings("unused")
- private void java_lcd_update()
- {
- btm.copyPixelsFromBuffer(native_buf);
- postInvalidate();
- }
-
- @SuppressWarnings("unused")
- private void java_lcd_update_rect(int x, int y, int w, int h)
- {
- /* can't copy a partial buffer */
+ /* can't copy a partial buffer :( */
btm.copyPixelsFromBuffer(native_buf);
- postInvalidate(x, y, x+w, y+h);
+ c.getClipBounds(rect);
+ c.drawBitmap(btm, rect, rect, null);
+ post_update_done();
}
@SuppressWarnings("unused")
@@ -152,6 +144,7 @@ public class RockboxFramebuffer extends View
return view_config.getScaledTouchSlop();
}
+ private native void post_update_done();
private native void set_lcd_active(int active);
private native void touchHandler(boolean down, int x, int y);
private native boolean buttonHandler(int keycode, boolean state);
diff --git a/firmware/target/hosted/android/lcd-android.c b/firmware/target/hosted/android/lcd-android.c
index f4ef7b5e75..2bc6d04b9e 100644
--- a/firmware/target/hosted/android/lcd-android.c
+++ b/firmware/target/hosted/android/lcd-android.c
@@ -23,6 +23,7 @@
#include <jni.h>
#include "config.h"
#include "system.h"
+#include "kernel.h"
#include "lcd.h"
extern JNIEnv *env_ptr;
@@ -31,16 +32,18 @@ extern jobject RockboxService_instance;
static jclass RockboxFramebuffer_class;
static jobject RockboxFramebuffer_instance;
-static jmethodID java_lcd_update;
-static jmethodID java_lcd_update_rect;
+static jmethodID postInvalidate1;
+static jmethodID postInvalidate2;
static bool display_on;
static int dpi;
static int scroll_threshold;
+static struct wakeup lcd_wakeup;
void lcd_init_device(void)
{
JNIEnv e = *env_ptr;
+ wakeup_init(&lcd_wakeup);
RockboxFramebuffer_class = e->FindClass(env_ptr,
"org/rockbox/RockboxFramebuffer");
/* instantiate a RockboxFramebuffer instance
@@ -71,13 +74,13 @@ void lcd_init_device(void)
buf);
/* cache update functions */
- java_lcd_update = (*env_ptr)->GetMethodID(env_ptr,
+ postInvalidate1 = (*env_ptr)->GetMethodID(env_ptr,
RockboxFramebuffer_class,
- "java_lcd_update",
+ "postInvalidate",
"()V");
- java_lcd_update_rect = (*env_ptr)->GetMethodID(env_ptr,
+ postInvalidate2 = (*env_ptr)->GetMethodID(env_ptr,
RockboxFramebuffer_class,
- "java_lcd_update_rect",
+ "postInvalidate",
"(IIII)V");
jmethodID get_dpi = e->GetMethodID(env_ptr,
@@ -96,22 +99,44 @@ void lcd_init_device(void)
display_on = true;
}
+/* the update mechanism is asynchronous since
+ * onDraw() must be called from the UI thread
+ *
+ * The Rockbox thread calling lcd_update() has to wait
+ * for the update to complete, so that it's synchronous,
+ * and we need to notify it (we could wait in the java layer, but
+ * that'd block the other Rockbox threads too)
+ *
+ * That should give more smoonth animations
+ */
void lcd_update(void)
{
/* tell the system we're ready for drawing */
if (display_on)
- (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, java_lcd_update);
+ {
+ (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, postInvalidate1);
+ wakeup_wait(&lcd_wakeup, TIMEOUT_BLOCK);
+ }
}
-void lcd_update_rect(int x, int y, int height, int width)
+void lcd_update_rect(int x, int y, int width, int height)
{
if (display_on)
{
- (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, java_lcd_update_rect,
- x, y, height, width);
+ (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, postInvalidate2,
+ (jint)x, (jint)y, (jint)x+width, (jint)y+height);
+ wakeup_wait(&lcd_wakeup, TIMEOUT_BLOCK);
}
}
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxFramebuffer_post_1update_1done(JNIEnv *e, jobject this)
+{
+ (void)e;
+ (void)this;
+ wakeup_signal(&lcd_wakeup);
+}
+
bool lcd_active(void)
{
return display_on;