forked from len0rd/rockbox
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
This commit is contained in:
parent
1d425bf1e6
commit
55b58a3f30
2 changed files with 43 additions and 25 deletions
|
|
@ -28,6 +28,7 @@ import org.rockbox.Helper.MediaButtonReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
|
@ -38,6 +39,7 @@ import android.view.ViewConfiguration;
|
||||||
public class RockboxFramebuffer extends View
|
public class RockboxFramebuffer extends View
|
||||||
{
|
{
|
||||||
private Bitmap btm;
|
private Bitmap btm;
|
||||||
|
private Rect rect;
|
||||||
private ByteBuffer native_buf;
|
private ByteBuffer native_buf;
|
||||||
private MediaButtonReceiver media_monitor;
|
private MediaButtonReceiver media_monitor;
|
||||||
private final DisplayMetrics metrics;
|
private final DisplayMetrics metrics;
|
||||||
|
|
@ -52,6 +54,7 @@ public class RockboxFramebuffer extends View
|
||||||
setFocusableInTouchMode(true);
|
setFocusableInTouchMode(true);
|
||||||
setClickable(true);
|
setClickable(true);
|
||||||
btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565);
|
btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565);
|
||||||
|
rect = new Rect();
|
||||||
native_buf = native_fb;
|
native_buf = native_fb;
|
||||||
media_monitor = new MediaButtonReceiver(c);
|
media_monitor = new MediaButtonReceiver(c);
|
||||||
media_monitor.register();
|
media_monitor.register();
|
||||||
|
|
@ -64,22 +67,11 @@ public class RockboxFramebuffer extends View
|
||||||
|
|
||||||
public void onDraw(Canvas c)
|
public void onDraw(Canvas c)
|
||||||
{
|
{
|
||||||
c.drawBitmap(btm, 0.0f, 0.0f, null);
|
/* can't copy a partial buffer :( */
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private void java_lcd_update()
|
|
||||||
{
|
|
||||||
btm.copyPixelsFromBuffer(native_buf);
|
btm.copyPixelsFromBuffer(native_buf);
|
||||||
postInvalidate();
|
c.getClipBounds(rect);
|
||||||
}
|
c.drawBitmap(btm, rect, rect, null);
|
||||||
|
post_update_done();
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private void java_lcd_update_rect(int x, int y, int w, int h)
|
|
||||||
{
|
|
||||||
/* can't copy a partial buffer */
|
|
||||||
btm.copyPixelsFromBuffer(native_buf);
|
|
||||||
postInvalidate(x, y, x+w, y+h);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
|
@ -152,6 +144,7 @@ public class RockboxFramebuffer extends View
|
||||||
return view_config.getScaledTouchSlop();
|
return view_config.getScaledTouchSlop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private native void post_update_done();
|
||||||
private native void set_lcd_active(int active);
|
private native void set_lcd_active(int active);
|
||||||
private native void touchHandler(boolean down, int x, int y);
|
private native void touchHandler(boolean down, int x, int y);
|
||||||
private native boolean buttonHandler(int keycode, boolean state);
|
private native boolean buttonHandler(int keycode, boolean state);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include "kernel.h"
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
|
|
||||||
extern JNIEnv *env_ptr;
|
extern JNIEnv *env_ptr;
|
||||||
|
|
@ -31,16 +32,18 @@ extern jobject RockboxService_instance;
|
||||||
|
|
||||||
static jclass RockboxFramebuffer_class;
|
static jclass RockboxFramebuffer_class;
|
||||||
static jobject RockboxFramebuffer_instance;
|
static jobject RockboxFramebuffer_instance;
|
||||||
static jmethodID java_lcd_update;
|
static jmethodID postInvalidate1;
|
||||||
static jmethodID java_lcd_update_rect;
|
static jmethodID postInvalidate2;
|
||||||
|
|
||||||
static bool display_on;
|
static bool display_on;
|
||||||
static int dpi;
|
static int dpi;
|
||||||
static int scroll_threshold;
|
static int scroll_threshold;
|
||||||
|
static struct wakeup lcd_wakeup;
|
||||||
|
|
||||||
void lcd_init_device(void)
|
void lcd_init_device(void)
|
||||||
{
|
{
|
||||||
JNIEnv e = *env_ptr;
|
JNIEnv e = *env_ptr;
|
||||||
|
wakeup_init(&lcd_wakeup);
|
||||||
RockboxFramebuffer_class = e->FindClass(env_ptr,
|
RockboxFramebuffer_class = e->FindClass(env_ptr,
|
||||||
"org/rockbox/RockboxFramebuffer");
|
"org/rockbox/RockboxFramebuffer");
|
||||||
/* instantiate a RockboxFramebuffer instance
|
/* instantiate a RockboxFramebuffer instance
|
||||||
|
|
@ -71,13 +74,13 @@ void lcd_init_device(void)
|
||||||
buf);
|
buf);
|
||||||
|
|
||||||
/* cache update functions */
|
/* cache update functions */
|
||||||
java_lcd_update = (*env_ptr)->GetMethodID(env_ptr,
|
postInvalidate1 = (*env_ptr)->GetMethodID(env_ptr,
|
||||||
RockboxFramebuffer_class,
|
RockboxFramebuffer_class,
|
||||||
"java_lcd_update",
|
"postInvalidate",
|
||||||
"()V");
|
"()V");
|
||||||
java_lcd_update_rect = (*env_ptr)->GetMethodID(env_ptr,
|
postInvalidate2 = (*env_ptr)->GetMethodID(env_ptr,
|
||||||
RockboxFramebuffer_class,
|
RockboxFramebuffer_class,
|
||||||
"java_lcd_update_rect",
|
"postInvalidate",
|
||||||
"(IIII)V");
|
"(IIII)V");
|
||||||
|
|
||||||
jmethodID get_dpi = e->GetMethodID(env_ptr,
|
jmethodID get_dpi = e->GetMethodID(env_ptr,
|
||||||
|
|
@ -96,22 +99,44 @@ void lcd_init_device(void)
|
||||||
display_on = true;
|
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)
|
void lcd_update(void)
|
||||||
{
|
{
|
||||||
/* tell the system we're ready for drawing */
|
/* tell the system we're ready for drawing */
|
||||||
if (display_on)
|
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)
|
if (display_on)
|
||||||
{
|
{
|
||||||
(*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, java_lcd_update_rect,
|
(*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, postInvalidate2,
|
||||||
x, y, height, width);
|
(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)
|
bool lcd_active(void)
|
||||||
{
|
{
|
||||||
return display_on;
|
return display_on;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue