Native-side proxy
Remove RemoteGLRenderer
Remove reflection-based control
Change-Id: If17c2bbb61c7141986d88c4763def77ed1074985
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 2cd1b6e..567f862 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -18,25 +18,26 @@
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
-import android.os.Looper;
import android.os.SystemClock;
import android.os.Trace;
-import android.util.Log;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
import java.io.PrintWriter;
-import java.lang.reflect.Method;
-import java.util.HashMap;
/**
* Hardware renderer that proxies the rendering to a render thread. Most calls
- * are synchronous, however a few such as draw() are posted async. The display list
- * is shared between the two threads and is guarded by a top level lock.
+ * are currently synchronous.
+ * TODO: Make draw() async.
+ * TODO: Figure out how to share the DisplayList between two threads (global lock?)
*
* The UI thread can block on the RenderThread, but RenderThread must never
* block on the UI thread.
*
+ * ThreadedRenderer creates an instance of RenderProxy. RenderProxy in turn creates
+ * and manages a CanvasContext on the RenderThread. The CanvasContext is fully managed
+ * by the lifecycle of the RenderProxy.
+ *
* Note that although currently the EGL context & surfaces are created & managed
* by the render thread, the goal is to move that into a shared structure that can
* be managed by both threads. EGLSurface creation & deletion should ideally be
@@ -48,49 +49,29 @@
public class ThreadedRenderer extends HardwareRenderer {
private static final String LOGTAG = "ThreadedRenderer";
- @SuppressWarnings("serial")
- static HashMap<String, Method> sMethodLut = new HashMap<String, Method>() {{
- Method[] methods = RemoteGLRenderer.class.getDeclaredMethods();
- for (Method m : methods) {
- m.setAccessible(true);
- put(m.getName() + ":" + m.getParameterTypes().length, m);
- }
- }};
- static boolean sNeedsInit = true;
+ private static final Rect NULL_RECT = new Rect(-1, -1, -1, -1);
- private RemoteGLRenderer mRemoteRenderer;
private int mWidth, mHeight;
- private RTJob mPreviousDraw;
+ private long mNativeProxy;
ThreadedRenderer(boolean translucent) {
- mRemoteRenderer = new RemoteGLRenderer(this, translucent);
- setEnabled(true);
- if (sNeedsInit) {
- sNeedsInit = false;
- postToRenderThread(new Runnable() {
- @Override
- public void run() {
- // Hack to allow GLRenderer to create a handler to post the EGL
- // destruction to, although it'll never run
- Looper.prepare();
- }
- });
- }
+ mNativeProxy = nCreateProxy(translucent);
+ setEnabled(mNativeProxy != 0);
}
@Override
void destroy(boolean full) {
- run("destroy", full);
+ nDestroyCanvas(mNativeProxy);
}
@Override
boolean initialize(Surface surface) throws OutOfResourcesException {
- return (Boolean) run("initialize", surface);
+ return nInitialize(mNativeProxy, surface);
}
@Override
void updateSurface(Surface surface) throws OutOfResourcesException {
- post("updateSurface", surface);
+ nUpdateSurface(mNativeProxy, surface);
}
@Override
@@ -100,12 +81,27 @@
@Override
void destroyHardwareResources(View view) {
- run("destroyHardwareResources", view);
+ // TODO: canvas.clearLayerUpdates()
+ destroyResources(view);
+ // TODO: GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
+ }
+
+ private static void destroyResources(View view) {
+ view.destroyHardwareResources();
+
+ if (view instanceof ViewGroup) {
+ ViewGroup group = (ViewGroup) view;
+
+ int count = group.getChildCount();
+ for (int i = 0; i < count; i++) {
+ destroyResources(group.getChildAt(i));
+ }
+ }
}
@Override
void invalidate(Surface surface) {
- post("invalidate", surface);
+ updateSurface(surface);
}
@Override
@@ -116,14 +112,15 @@
@Override
boolean safelyRun(Runnable action) {
- return (Boolean) run("safelyRun", action);
+ // TODO:
+ return false;
}
@Override
void setup(int width, int height) {
mWidth = width;
mHeight = height;
- post("setup", width, height);
+ nSetup(mNativeProxy, width, height);
}
@Override
@@ -149,7 +146,7 @@
@Override
boolean loadSystemProperties() {
- return (Boolean) run("loadSystemProperties");
+ return false;
}
@Override
@@ -174,20 +171,10 @@
*
* @hide */
public void repeatLastDraw() {
- if (mPreviousDraw == null) {
- throw new IllegalStateException("There isn't a previous draw");
- }
- synchronized (mPreviousDraw) {
- mPreviousDraw.completed = false;
- }
- mPreviousDraw.args[3] = null;
- postToRenderThread(mPreviousDraw);
}
@Override
void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
- requireCompletion(mPreviousDraw);
-
attachInfo.mIgnoreDirtyState = true;
attachInfo.mDrawingTime = SystemClock.uptimeMillis();
view.mPrivateFlags |= View.PFLAG_DRAWN;
@@ -202,8 +189,11 @@
view.mRecreateDisplayList = false;
- mPreviousDraw = post("drawDisplayList", displayList, attachInfo,
- callbacks, dirty);
+ if (dirty == null) {
+ dirty = NULL_RECT;
+ }
+ nDrawDisplayList(mNativeProxy, displayList.getNativeDisplayList(),
+ dirty.left, dirty.top, dirty.right, dirty.bottom);
}
@Override
@@ -228,85 +218,40 @@
@Override
void detachFunctor(int functor) {
- run("detachFunctor", functor);
+ nDetachFunctor(mNativeProxy, functor);
}
@Override
- boolean attachFunctor(AttachInfo attachInfo, int functor) {
- return (Boolean) run("attachFunctor", attachInfo, functor);
+ void attachFunctor(AttachInfo attachInfo, int functor) {
+ nAttachFunctor(mNativeProxy, functor);
}
@Override
void setName(String name) {
- post("setName", name);
}
- private static void requireCompletion(RTJob job) {
- if (job != null) {
- synchronized (job) {
- if (!job.completed) {
- try {
- job.wait();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
- }
- }
-
- private RTJob post(String method, Object... args) {
- RTJob job = new RTJob();
- job.method = sMethodLut.get(method + ":" + args.length);
- job.args = args;
- job.target = mRemoteRenderer;
- if (job.method == null) {
- throw new NullPointerException("Couldn't find method: " + method);
- }
- postToRenderThread(job);
- return job;
- }
-
- private Object run(String method, Object... args) {
- RTJob job = new RTJob();
- job.method = sMethodLut.get(method + ":" + args.length);
- job.args = args;
- job.target = mRemoteRenderer;
- if (job.method == null) {
- throw new NullPointerException("Couldn't find method: " + method);
- }
- synchronized (job) {
- postToRenderThread(job);
- try {
- job.wait();
- return job.ret;
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
- static class RTJob implements Runnable {
- Method method;
- Object[] args;
- Object target;
- Object ret;
- boolean completed = false;
-
- @Override
- public void run() {
- try {
- ret = method.invoke(target, args);
- synchronized (this) {
- completed = true;
- notify();
- }
- } catch (Exception e) {
- Log.e(LOGTAG, "Failed to invoke: " + method.getName(), e);
- }
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ nDeleteProxy(mNativeProxy);
+ } finally {
+ super.finalize();
}
}
/** @hide */
public static native void postToRenderThread(Runnable runnable);
+
+ private static native long nCreateProxy(boolean translucent);
+ private static native void nDeleteProxy(long nativeProxy);
+
+ private static native boolean nInitialize(long nativeProxy, Surface window);
+ private static native void nUpdateSurface(long nativeProxy, Surface window);
+ private static native void nSetup(long nativeProxy, int width, int height);
+ private static native void nDrawDisplayList(long nativeProxy, long displayList,
+ int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
+ private static native void nDestroyCanvas(long nativeProxy);
+
+ private static native void nAttachFunctor(long nativeProxy, long functor);
+ private static native void nDetachFunctor(long nativeProxy, long functor);
}