1
0
Fork 0
forked from len0rd/rockbox

Android: Rewrite lcd subsystem to use the SurfaceView API.

That enables drawing from outside the apps UI thread, i.e. from within the Rockbox native thread, without needing synchronization means, and adds determinism as to when the draw happens.
It simplifies the drawing routines and adds a convinient way of detecting whether drawing should happen or not (surfaceCreated/Destroyed).
It also restores max. fps on my phone which went down drastically with the gingerbread(CM7) update.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29333 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Thomas Martitz 2011-02-19 01:13:38 +00:00
parent 6cbb0e4229
commit 144df92bfb
6 changed files with 159 additions and 179 deletions

View file

@ -23,8 +23,6 @@ package org.rockbox;
import java.nio.ByteBuffer;
import org.rockbox.Helper.MediaButtonReceiver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@ -33,45 +31,72 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewConfiguration;
public class RockboxFramebuffer extends View
public class RockboxFramebuffer extends SurfaceView
implements SurfaceHolder.Callback
{
private Bitmap btm;
private Rect rect;
private ByteBuffer native_buf;
private MediaButtonReceiver media_monitor;
private final DisplayMetrics metrics;
private final ViewConfiguration view_config;
private ByteBuffer native_buf;
private Bitmap btm;
public RockboxFramebuffer(Context c, int lcd_width,
int lcd_height, ByteBuffer native_fb)
/* first stage init; needs to run from a thread that has a Looper
* setup stuff that needs a Context */
public RockboxFramebuffer(Context c)
{
super(c);
metrics = c.getResources().getDisplayMetrics();
view_config = ViewConfiguration.get(c);
getHolder().addCallback(this);
/* Needed so we can catch KeyEvents */
setFocusable(true);
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();
/* the service needs to know the about us */
((RockboxService)c).set_fb(this);
metrics = c.getResources().getDisplayMetrics();
view_config = ViewConfiguration.get(c);
/* don't draw until native is ready (2nd stage) */
setEnabled(false);
}
public void onDraw(Canvas c)
/* second stage init; called from Rockbox with information about the
* display framebuffer */
@SuppressWarnings("unused")
private void java_lcd_init(int lcd_width, int lcd_height, ByteBuffer native_fb)
{
/* can't copy a partial buffer :( */
btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565);
native_buf = native_fb;
setEnabled(true);
}
@SuppressWarnings("unused")
private void java_lcd_update()
{
SurfaceHolder holder = getHolder();
Canvas c = holder.lockCanvas(null);
btm.copyPixelsFromBuffer(native_buf);
c.getClipBounds(rect);
c.drawBitmap(btm, rect, rect, null);
post_update_done();
synchronized (holder)
{ /* draw */
c.drawBitmap(btm, 0.0f, 0.0f, null);
}
holder.unlockCanvasAndPost(c);
}
@SuppressWarnings("unused")
private void java_lcd_update_rect(int x, int y, int width, int height)
{
SurfaceHolder holder = getHolder();
Rect dirty = new Rect(x, y, x+width, y+height);
Canvas c = holder.lockCanvas(dirty);
/* can't copy a partial buffer,
* but it doesn't make a noticeable difference anyway */
btm.copyPixelsFromBuffer(native_buf);
synchronized (holder)
{ /* draw */
c.drawBitmap(btm, dirty, dirty, null);
}
holder.unlockCanvasAndPost(c);
}
@SuppressWarnings("unused")
@ -109,28 +134,6 @@ public class RockboxFramebuffer extends View
{
return buttonHandler(keyCode, false);
}
public void destroy()
{
set_lcd_active(0);
media_monitor.unregister();
}
@Override
protected void onWindowVisibilityChanged(int visibility)
{
super.onWindowVisibilityChanged(visibility);
switch (visibility) {
case VISIBLE:
set_lcd_active(1);
break;
case GONE:
case INVISIBLE:
set_lcd_active(0);
break;
}
}
@SuppressWarnings("unused")
private int getDpi()
@ -144,8 +147,12 @@ 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 static boolean buttonHandler(int keycode, boolean state);
public native void surfaceCreated(SurfaceHolder holder);
public native void surfaceDestroyed(SurfaceHolder holder);
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
}
}