diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-12-02 23:50:50 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-12-02 23:50:50 +0000 |
commit | 55b58a3f30270ce8df7c1b51720bb777e7972c7f (patch) | |
tree | 46a3be432fd4e75b5604905338800e66a70d0ce5 | |
parent | 1d425bf1e6c0346db02f03be496ecef749b49c22 (diff) | |
download | rockbox-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.java | 23 | ||||
-rw-r--r-- | firmware/target/hosted/android/lcd-android.c | 45 |
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; |