summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2014-02-14 20:03:38 -0800
committerJohn Reck <jreck@google.com>2014-02-19 10:47:19 -0800
commit19b6bcfd83eb7fb92ebd06d2fec89e308311f1d0 (patch)
tree617b09881e87d86d03a7486f5c3f05242199210d /core/java/android
parent587f43d8725b11632b5d64a0a56a647207f01668 (diff)
Support HardwareLayers in RenderThread
Also has a few HardwareLayer lifecycle fixes Change-Id: I6308cb05f8f199eed72189ace768013a46815941
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityThread.java1
-rw-r--r--core/java/android/view/GLRenderer.java41
-rw-r--r--core/java/android/view/HardwareLayer.java32
-rw-r--r--core/java/android/view/HardwareRenderer.java16
-rw-r--r--core/java/android/view/TextureView.java26
-rw-r--r--core/java/android/view/ThreadedRenderer.java89
-rw-r--r--core/java/android/view/View.java24
-rw-r--r--core/java/android/view/ViewRootImpl.java23
8 files changed, 107 insertions, 145 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 30c1e622d346..3258585ad583 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3949,6 +3949,7 @@ public final class ActivityThread {
ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
// Cleanup hardware accelerated stuff
+ // TODO: Do we actually want to do this in response to all config changes?
WindowManagerGlobal.getInstance().trimLocalMemory();
freeTextLayoutCachesIfNeeded(configDiff);
diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java
index c1eb6b771c09..859468aa44ef 100644
--- a/core/java/android/view/GLRenderer.java
+++ b/core/java/android/view/GLRenderer.java
@@ -477,17 +477,21 @@ public class GLRenderer extends HardwareRenderer {
@Override
void flushLayerUpdates() {
- mGlCanvas.flushLayerUpdates();
+ if (validate()) {
+ mGlCanvas.flushLayerUpdates();
+ }
}
@Override
HardwareLayer createTextureLayer() {
+ validate();
return HardwareLayer.createTextureLayer(this);
}
@Override
public HardwareLayer createDisplayListLayer(int width, int height) {
- return HardwareLayer.createRenderLayer(this, width, height);
+ validate();
+ return HardwareLayer.createDisplayListLayer(this, width, height);
}
@Override
@@ -510,6 +514,9 @@ public class GLRenderer extends HardwareRenderer {
@Override
boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap) {
+ if (!validate()) {
+ throw new IllegalStateException("Could not acquire hardware rendering context");
+ }
layer.flushChanges();
return GLES20Canvas.nCopyLayer(layer.getLayer(), bitmap.mNativeBitmap);
}
@@ -538,35 +545,6 @@ public class GLRenderer extends HardwareRenderer {
}
@Override
- void destroyLayers(final View view) {
- if (view != null) {
- safelyRun(new Runnable() {
- @Override
- public void run() {
- if (mCanvas != null) {
- mCanvas.clearLayerUpdates();
- }
- destroyHardwareLayer(view);
- GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
- }
- });
- }
- }
-
- private static void destroyHardwareLayer(View view) {
- view.destroyLayer(true);
-
- if (view instanceof ViewGroup) {
- ViewGroup group = (ViewGroup) view;
-
- int count = group.getChildCount();
- for (int i = 0; i < count; i++) {
- destroyHardwareLayer(group.getChildAt(i));
- }
- }
- }
-
- @Override
void destroyHardwareResources(final View view) {
if (view != null) {
safelyRun(new Runnable() {
@@ -1069,7 +1047,6 @@ public class GLRenderer extends HardwareRenderer {
return true;
}
- @Override
boolean validate() {
return checkRenderContext() != SURFACE_STATE_ERROR;
}
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index 9bbcf7ce5963..958c0719543a 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -33,7 +33,7 @@ import android.graphics.SurfaceTexture;
*/
final class HardwareLayer {
private static final int LAYER_TYPE_TEXTURE = 1;
- private static final int LAYER_TYPE_RENDER = 2;
+ private static final int LAYER_TYPE_DISPLAY_LIST = 2;
private HardwareRenderer mRenderer;
private Finalizer mFinalizer;
@@ -99,6 +99,10 @@ final class HardwareLayer {
doDestroyLayerUpdater();
}
+ public long getDeferredLayerUpdater() {
+ return mFinalizer.mDeferredUpdater;
+ }
+
/**
* Destroys the deferred layer updater but not the backing layer. The
* backing layer is instead returned and is the caller's responsibility
@@ -120,7 +124,7 @@ final class HardwareLayer {
}
public DisplayList startRecording() {
- assertType(LAYER_TYPE_RENDER);
+ assertType(LAYER_TYPE_DISPLAY_LIST);
if (mDisplayList == null) {
mDisplayList = DisplayList.create("HardwareLayer");
@@ -172,9 +176,17 @@ final class HardwareLayer {
/**
* Indicates that this layer has lost its texture.
*/
- public void onTextureDestroyed() {
+ public void detachSurfaceTexture(final SurfaceTexture surface) {
assertType(LAYER_TYPE_TEXTURE);
- nOnTextureDestroyed(mFinalizer.mDeferredUpdater);
+ mRenderer.safelyRun(new Runnable() {
+ @Override
+ public void run() {
+ surface.detachFromGLContext();
+ // SurfaceTexture owns the texture name and detachFromGLContext
+ // should have deleted it
+ nOnTextureDestroyed(mFinalizer.mDeferredUpdater);
+ }
+ });
}
/**
@@ -226,12 +238,20 @@ final class HardwareLayer {
return new HardwareLayer(renderer, nCreateTextureLayer(), LAYER_TYPE_TEXTURE);
}
+ static HardwareLayer adoptTextureLayer(HardwareRenderer renderer, long layer) {
+ return new HardwareLayer(renderer, layer, LAYER_TYPE_TEXTURE);
+ }
+
/**
* This should only be used by HardwareRenderer! Do not call directly
*/
- static HardwareLayer createRenderLayer(HardwareRenderer renderer,
+ static HardwareLayer createDisplayListLayer(HardwareRenderer renderer,
int width, int height) {
- return new HardwareLayer(renderer, nCreateRenderLayer(width, height), LAYER_TYPE_RENDER);
+ return new HardwareLayer(renderer, nCreateRenderLayer(width, height), LAYER_TYPE_DISPLAY_LIST);
+ }
+
+ static HardwareLayer adoptDisplayListLayer(HardwareRenderer renderer, long layer) {
+ return new HardwareLayer(renderer, layer, LAYER_TYPE_DISPLAY_LIST);
}
/** This also creates the underlying layer */
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 93cc9d122ce4..7a943f0a136c 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -234,13 +234,6 @@ public abstract class HardwareRenderer {
abstract void updateSurface(Surface surface) throws OutOfResourcesException;
/**
- * Destroys the layers used by the specified view hierarchy.
- *
- * @param view The root of the view hierarchy
- */
- abstract void destroyLayers(View view);
-
- /**
* Destroys all hardware rendering resources associated with the specified
* view hierarchy.
*
@@ -257,15 +250,6 @@ public abstract class HardwareRenderer {
abstract void invalidate(Surface surface);
/**
- * This method should be invoked to ensure the hardware renderer is in
- * valid state (for instance, to ensure the correct EGL context is bound
- * to the current thread.)
- *
- * @return true if the renderer is now valid, false otherwise
- */
- abstract boolean validate();
-
- /**
* This method ensures the hardware renderer is in a valid state
* before executing the specified action.
*
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index e78940779fd3..ef0d80d73cde 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -231,26 +231,12 @@ public class TextureView extends View {
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- if (mLayer != null) {
- boolean success = executeHardwareAction(new Runnable() {
- @Override
- public void run() {
- destroySurface();
- }
- });
-
- if (!success) {
- Log.w(LOG_TAG, "TextureView was not able to destroy its surface: " + this);
- }
- }
+ destroySurface();
}
private void destroySurface() {
if (mLayer != null) {
- mSurface.detachFromGLContext();
- // SurfaceTexture owns the texture name and detachFromGLContext
- // should have deleted it
- mLayer.onTextureDestroyed();
+ mLayer.detachSurfaceTexture(mSurface);
boolean shouldRelease = true;
if (mListener != null) {
@@ -608,14 +594,6 @@ public class TextureView extends View {
*/
public Bitmap getBitmap(Bitmap bitmap) {
if (bitmap != null && isAvailable()) {
- AttachInfo info = mAttachInfo;
- if (info != null && info.mHardwareRenderer != null &&
- info.mHardwareRenderer.isEnabled()) {
- if (!info.mHardwareRenderer.validate()) {
- throw new IllegalStateException("Could not acquire hardware rendering context");
- }
- }
-
applyUpdate();
applyTransformMatrix();
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 1d7e5b296162..e8f5e45fb393 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -76,13 +76,7 @@ public class ThreadedRenderer extends HardwareRenderer {
}
@Override
- void destroyLayers(View view) {
- throw new NoSuchMethodError();
- }
-
- @Override
void destroyHardwareResources(View view) {
- // TODO: canvas.clearLayerUpdates()
destroyResources(view);
// TODO: GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
}
@@ -106,12 +100,6 @@ public class ThreadedRenderer extends HardwareRenderer {
}
@Override
- boolean validate() {
- // TODO Remove users of this API
- return false;
- }
-
- @Override
boolean safelyRun(Runnable action) {
nRunWithGlContext(mNativeProxy, action);
return true;
@@ -150,26 +138,6 @@ public class ThreadedRenderer extends HardwareRenderer {
return false;
}
- @Override
- void pushLayerUpdate(HardwareLayer layer) {
- throw new NoSuchMethodError();
- }
-
- @Override
- void onLayerCreated(HardwareLayer layer) {
- throw new NoSuchMethodError();
- }
-
- @Override
- void onLayerDestroyed(HardwareLayer layer) {
- throw new NoSuchMethodError();
- }
-
- @Override
- void flushLayerUpdates() {
- throw new NoSuchMethodError();
- }
-
/**
* TODO: Remove
* Temporary hack to allow RenderThreadTest prototype app to trigger
@@ -203,33 +171,63 @@ public class ThreadedRenderer extends HardwareRenderer {
}
@Override
- HardwareLayer createTextureLayer() {
- throw new NoSuchMethodError();
+ void detachFunctor(long functor) {
+ nDetachFunctor(mNativeProxy, functor);
+ }
+
+ @Override
+ void attachFunctor(AttachInfo attachInfo, long functor) {
+ nAttachFunctor(mNativeProxy, functor);
}
@Override
HardwareLayer createDisplayListLayer(int width, int height) {
- throw new NoSuchMethodError();
+ long layer = nCreateDisplayListLayer(mNativeProxy, width, height);
+ return HardwareLayer.adoptDisplayListLayer(this, layer);
}
@Override
- SurfaceTexture createSurfaceTexture(HardwareLayer layer) {
- throw new NoSuchMethodError();
+ HardwareLayer createTextureLayer() {
+ long layer = nCreateTextureLayer(mNativeProxy);
+ return HardwareLayer.adoptTextureLayer(this, layer);
}
@Override
- boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap) {
- throw new NoSuchMethodError();
+ SurfaceTexture createSurfaceTexture(final HardwareLayer layer) {
+ final SurfaceTexture[] ret = new SurfaceTexture[1];
+ nRunWithGlContext(mNativeProxy, new Runnable() {
+ @Override
+ public void run() {
+ ret[0] = layer.createSurfaceTexture();
+ }
+ });
+ return ret[0];
}
@Override
- void detachFunctor(long functor) {
- nDetachFunctor(mNativeProxy, functor);
+ boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
+ return nCopyLayerInto(mNativeProxy,
+ layer.getDeferredLayerUpdater(), bitmap.mNativeBitmap);
}
@Override
- void attachFunctor(AttachInfo attachInfo, long functor) {
- nAttachFunctor(mNativeProxy, functor);
+ void pushLayerUpdate(HardwareLayer layer) {
+ // TODO: Remove this, it's not needed outside of GLRenderer
+ }
+
+ @Override
+ void onLayerCreated(HardwareLayer layer) {
+ // TODO: Is this actually useful?
+ }
+
+ @Override
+ void flushLayerUpdates() {
+ // TODO: Figure out what this should do or remove it
+ }
+
+ @Override
+ void onLayerDestroyed(HardwareLayer layer) {
+ nDestroyLayer(mNativeProxy, layer.getDeferredLayerUpdater());
}
@Override
@@ -261,4 +259,9 @@ public class ThreadedRenderer extends HardwareRenderer {
private static native void nAttachFunctor(long nativeProxy, long functor);
private static native void nDetachFunctor(long nativeProxy, long functor);
+
+ private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
+ private static native long nCreateTextureLayer(long nativeProxy);
+ private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
+ private static native void nDestroyLayer(long nativeProxy, long layer);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 49dc5728cdb2..9e7046e65fe6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -13584,19 +13584,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
switch (mLayerType) {
case LAYER_TYPE_HARDWARE:
- if (attachInfo.mHardwareRenderer != null &&
- attachInfo.mHardwareRenderer.isEnabled() &&
- attachInfo.mHardwareRenderer.validate()) {
- getHardwareLayer();
- // TODO: We need a better way to handle this case
- // If views have registered pre-draw listeners they need
- // to be notified before we build the layer. Those listeners
- // may however rely on other events to happen first so we
- // cannot just invoke them here until they don't cancel the
- // current frame
- if (!attachInfo.mTreeObserver.hasOnPreDrawListeners()) {
- attachInfo.mViewRootImpl.dispatchFlushHardwareLayerUpdates();
- }
+ getHardwareLayer();
+ // TODO: We need a better way to handle this case
+ // If views have registered pre-draw listeners they need
+ // to be notified before we build the layer. Those listeners
+ // may however rely on other events to happen first so we
+ // cannot just invoke them here until they don't cancel the
+ // current frame
+ if (!attachInfo.mTreeObserver.hasOnPreDrawListeners()) {
+ attachInfo.mViewRootImpl.dispatchFlushHardwareLayerUpdates();
}
break;
case LAYER_TYPE_SOFTWARE:
@@ -13617,8 +13613,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return null;
}
- if (!mAttachInfo.mHardwareRenderer.validate()) return null;
-
final int width = mRight - mLeft;
final int height = mBottom - mTop;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 11030d984ad2..a68d06ab948c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -631,16 +631,25 @@ public final class ViewRootImpl implements ViewParent,
}
} else {
invalidateDisplayLists();
- if (mAttachInfo.mHardwareRenderer != null &&
- mAttachInfo.mHardwareRenderer.isEnabled()) {
- mAttachInfo.mHardwareRenderer.destroyLayers(mView);
+ destroyHardwareLayer(mView);
+ }
+ }
+
+ private static void destroyHardwareLayer(View view) {
+ view.destroyLayer(true);
+
+ if (view instanceof ViewGroup) {
+ ViewGroup group = (ViewGroup) view;
+
+ int count = group.getChildCount();
+ for (int i = 0; i < count; i++) {
+ destroyHardwareLayer(group.getChildAt(i));
}
}
}
void flushHardwareLayerUpdates() {
- if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled() &&
- mAttachInfo.mHardwareRenderer.validate()) {
+ if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
mAttachInfo.mHardwareRenderer.flushLayerUpdates();
}
}
@@ -2845,10 +2854,6 @@ public final class ViewRootImpl implements ViewParent,
void dispatchDetachedFromWindow() {
if (mView != null && mView.mAttachInfo != null) {
- if (mAttachInfo.mHardwareRenderer != null &&
- mAttachInfo.mHardwareRenderer.isEnabled()) {
- mAttachInfo.mHardwareRenderer.validate();
- }
mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false);
mView.dispatchDetachedFromWindow();
}