diff options
author | John Reck <jreck@google.com> | 2014-05-29 18:56:11 -0700 |
---|---|---|
committer | John Reck <jreck@google.com> | 2014-05-30 12:19:33 -0700 |
commit | d72e0a339b54af0c4e731513bbad120dff694723 (patch) | |
tree | ca8ac198de9a0cfeeae1e9e8039e35523e7810c3 | |
parent | aee470c0232afdac4256d13020fa0cf04f30395c (diff) | |
download | frameworks_base-d72e0a339b54af0c4e731513bbad120dff694723.zip frameworks_base-d72e0a339b54af0c4e731513bbad120dff694723.tar.gz frameworks_base-d72e0a339b54af0c4e731513bbad120dff694723.tar.bz2 |
Re-jigger layers
Bug: 15185239
Bug: 15238382
Make DeferredLayerUpdater ref counted so that
HardwareLayer:finalizer() works non-crashily on
leaked layers
Give DeferredLayerUpdater the ability to have a layer destroyer
set so that leaked layers can still be recycled on the
RenderThread
Order layer updates based off of pushLayerUpdate() calls to fix
issue with nested layers
Change-Id: I4449cee607f7e5126e02fed7464cf48038e3dfdf
-rw-r--r-- | core/java/android/view/GLRenderer.java | 22 | ||||
-rw-r--r-- | core/java/android/view/HardwareLayer.java | 105 | ||||
-rw-r--r-- | core/java/android/view/HardwareRenderer.java | 6 | ||||
-rw-r--r-- | core/java/android/view/ThreadedRenderer.java | 12 | ||||
-rw-r--r-- | core/java/com/android/internal/util/VirtualRefBasePtr.java | 10 | ||||
-rw-r--r-- | core/jni/android_view_HardwareLayer.cpp | 18 | ||||
-rw-r--r-- | core/jni/android_view_ThreadedRenderer.cpp | 14 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.cpp | 17 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.h | 14 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 26 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.h | 6 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.cpp | 31 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.h | 13 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 33 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.h | 3 |
15 files changed, 135 insertions, 195 deletions
diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java index 64a4c41..f1163e2 100644 --- a/core/java/android/view/GLRenderer.java +++ b/core/java/android/view/GLRenderer.java @@ -178,7 +178,7 @@ public class GLRenderer extends HardwareRenderer { private static EGLSurface sPbuffer; private static final Object[] sPbufferLock = new Object[0]; - private List<HardwareLayer> mAttachedLayers = new ArrayList<HardwareLayer>(); + private List<HardwareLayer> mLayerUpdates = new ArrayList<HardwareLayer>(); private static class GLRendererEglContext extends ManagedEGLContext { final Handler mHandler = new Handler(); @@ -471,7 +471,7 @@ public class GLRenderer extends HardwareRenderer { @Override void pushLayerUpdate(HardwareLayer layer) { - mGlCanvas.pushLayerUpdate(layer); + mLayerUpdates.add(layer); } @Override @@ -494,11 +494,6 @@ public class GLRenderer extends HardwareRenderer { return HardwareLayer.createDisplayListLayer(this, width, height); } - @Override - void onLayerCreated(HardwareLayer hardwareLayer) { - mAttachedLayers.add(hardwareLayer); - } - boolean hasContext() { return sEgl != null && mEglContext != null && mEglContext.equals(sEgl.eglGetCurrentContext()); @@ -509,11 +504,7 @@ public class GLRenderer extends HardwareRenderer { if (mGlCanvas != null) { mGlCanvas.cancelLayerUpdate(layer); } - if (hasContext()) { - long backingLayer = layer.detachBackingLayer(); - nDestroyLayer(backingLayer); - } - mAttachedLayers.remove(layer); + mLayerUpdates.remove(layer); } @Override @@ -1198,16 +1189,19 @@ public class GLRenderer extends HardwareRenderer { private void flushLayerChanges() { // Loop through and apply any pending layer changes - for (int i = 0; i < mAttachedLayers.size(); i++) { - HardwareLayer layer = mAttachedLayers.get(i); + for (int i = 0; i < mLayerUpdates.size(); i++) { + HardwareLayer layer = mLayerUpdates.get(i); layer.flushChanges(); if (!layer.isValid()) { // The layer was removed from mAttachedLayers, rewind i by 1 // Note that this shouldn't actually happen as View.getHardwareLayer() // is already flushing for error checking reasons i--; + } else if (layer.hasDisplayList()) { + mCanvas.pushLayerUpdate(layer); } } + mLayerUpdates.clear(); } @Override diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java index 4d78733..652bcd2 100644 --- a/core/java/android/view/HardwareLayer.java +++ b/core/java/android/view/HardwareLayer.java @@ -22,6 +22,8 @@ import android.graphics.Paint; import android.graphics.Rect; import android.graphics.SurfaceTexture; +import com.android.internal.util.VirtualRefBasePtr; + /** * A hardware layer can be used to render graphics operations into a hardware * friendly buffer. For instance, with an OpenGL backend a hardware layer @@ -36,7 +38,7 @@ final class HardwareLayer { private static final int LAYER_TYPE_DISPLAY_LIST = 2; private HardwareRenderer mRenderer; - private Finalizer mFinalizer; + private VirtualRefBasePtr mFinalizer; private RenderNode mDisplayList; private final int mLayerType; @@ -47,10 +49,7 @@ final class HardwareLayer { } mRenderer = renderer; mLayerType = type; - mFinalizer = new Finalizer(deferredUpdater); - - // Layer is considered initialized at this point, notify the HardwareRenderer - mRenderer.onLayerCreated(this); + mFinalizer = new VirtualRefBasePtr(deferredUpdater); } private void assertType(int type) { @@ -59,6 +58,10 @@ final class HardwareLayer { } } + boolean hasDisplayList() { + return mDisplayList != null; + } + /** * Update the paint used when drawing this layer. * @@ -66,7 +69,8 @@ final class HardwareLayer { * @see View#setLayerPaint(android.graphics.Paint) */ public void setLayerPaint(Paint paint) { - nSetLayerPaint(mFinalizer.mDeferredUpdater, paint.mNativePaint); + nSetLayerPaint(mFinalizer.get(), paint.mNativePaint); + mRenderer.pushLayerUpdate(this); } /** @@ -75,7 +79,7 @@ final class HardwareLayer { * @return True if the layer can be rendered into, false otherwise */ public boolean isValid() { - return mFinalizer != null && mFinalizer.mDeferredUpdater != 0; + return mFinalizer != null && mFinalizer.get() != 0; } /** @@ -91,35 +95,14 @@ final class HardwareLayer { mDisplayList.destroyDisplayListData(); mDisplayList = null; } - if (mRenderer != null) { - mRenderer.onLayerDestroyed(this); - mRenderer = null; - } - doDestroyLayerUpdater(); + mRenderer.onLayerDestroyed(this); + mRenderer = null; + mFinalizer.release(); + mFinalizer = null; } 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 - * to destroy/recycle as appropriate. - * - * It is safe to call this in onLayerDestroyed only - */ - public long detachBackingLayer() { - long backingLayer = nDetachBackingLayer(mFinalizer.mDeferredUpdater); - doDestroyLayerUpdater(); - return backingLayer; - } - - private void doDestroyLayerUpdater() { - if (mFinalizer != null) { - mFinalizer.destroy(); - mFinalizer = null; - } + return mFinalizer.get(); } public RenderNode startRecording() { @@ -132,7 +115,7 @@ final class HardwareLayer { } public void endRecording(Rect dirtyRect) { - nUpdateRenderLayer(mFinalizer.mDeferredUpdater, mDisplayList.getNativeDisplayList(), + nUpdateRenderLayer(mFinalizer.get(), mDisplayList.getNativeDisplayList(), dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom); mRenderer.pushLayerUpdate(this); } @@ -160,7 +143,7 @@ final class HardwareLayer { * match the desired values. */ public boolean prepare(int width, int height, boolean isOpaque) { - return nPrepare(mFinalizer.mDeferredUpdater, width, height, isOpaque); + return nPrepare(mFinalizer.get(), width, height, isOpaque); } /** @@ -169,7 +152,8 @@ final class HardwareLayer { * @param matrix The transform to apply to the layer. */ public void setTransform(Matrix matrix) { - nSetTransform(mFinalizer.mDeferredUpdater, matrix.native_instance); + nSetTransform(mFinalizer.get(), matrix.native_instance); + mRenderer.pushLayerUpdate(this); } /** @@ -183,7 +167,7 @@ final class HardwareLayer { surface.detachFromGLContext(); // SurfaceTexture owns the texture name and detachFromGLContext // should have deleted it - nOnTextureDestroyed(mFinalizer.mDeferredUpdater); + nOnTextureDestroyed(mFinalizer.get()); } }); } @@ -200,24 +184,26 @@ final class HardwareLayer { return; } - boolean success = nFlushChanges(mFinalizer.mDeferredUpdater); + boolean success = nFlushChanges(mFinalizer.get()); if (!success) { destroy(); } } public long getLayer() { - return nGetLayer(mFinalizer.mDeferredUpdater); + return nGetLayer(mFinalizer.get()); } public void setSurfaceTexture(SurfaceTexture surface) { assertType(LAYER_TYPE_TEXTURE); - nSetSurfaceTexture(mFinalizer.mDeferredUpdater, surface, false); + nSetSurfaceTexture(mFinalizer.get(), surface, false); + mRenderer.pushLayerUpdate(this); } public void updateSurfaceTexture() { assertType(LAYER_TYPE_TEXTURE); - nUpdateSurfaceTexture(mFinalizer.mDeferredUpdater); + nUpdateSurfaceTexture(mFinalizer.get()); + mRenderer.pushLayerUpdate(this); } /** @@ -225,8 +211,8 @@ final class HardwareLayer { */ SurfaceTexture createSurfaceTexture() { assertType(LAYER_TYPE_TEXTURE); - SurfaceTexture st = new SurfaceTexture(nGetTexName(mFinalizer.mDeferredUpdater)); - nSetSurfaceTexture(mFinalizer.mDeferredUpdater, st, true); + SurfaceTexture st = new SurfaceTexture(nGetTexName(mFinalizer.get())); + nSetSurfaceTexture(mFinalizer.get(), st, true); return st; } @@ -258,15 +244,6 @@ final class HardwareLayer { private static native long nCreateRenderLayer(int width, int height); private static native void nOnTextureDestroyed(long layerUpdater); - private static native long nDetachBackingLayer(long layerUpdater); - - /** This also destroys the underlying layer if it is still attached. - * Note it does not recycle the underlying layer, but instead queues it - * for deferred deletion. - * The HardwareRenderer should use detachBackingLayer() in the - * onLayerDestroyed() callback to do recycling if desired. - */ - private static native void nDestroyLayerUpdater(long layerUpdater); private static native boolean nPrepare(long layerUpdater, int width, int height, boolean isOpaque); private static native void nSetLayerPaint(long layerUpdater, long paint); @@ -281,28 +258,4 @@ final class HardwareLayer { private static native long nGetLayer(long layerUpdater); private static native int nGetTexName(long layerUpdater); - - private static class Finalizer { - private long mDeferredUpdater; - - public Finalizer(long deferredUpdater) { - mDeferredUpdater = deferredUpdater; - } - - @Override - protected void finalize() throws Throwable { - try { - destroy(); - } finally { - super.finalize(); - } - } - - void destroy() { - if (mDeferredUpdater != 0) { - nDestroyLayerUpdater(mDeferredUpdater); - mDeferredUpdater = 0; - } - } - } } diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 60f8ee3..d71de9f 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -323,12 +323,6 @@ public abstract class HardwareRenderer { abstract void pushLayerUpdate(HardwareLayer layer); /** - * Tells the HardwareRenderer that a layer was created. The renderer should - * make sure to apply any pending layer changes at the start of a new frame - */ - abstract void onLayerCreated(HardwareLayer hardwareLayer); - - /** * Tells the HardwareRenderer that the layer is destroyed. The renderer * should remove the layer from any update queues. */ diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index cac23a8..11db996 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -294,12 +294,7 @@ public class ThreadedRenderer extends HardwareRenderer { @Override void pushLayerUpdate(HardwareLayer layer) { - // TODO: Remove this, it's not needed outside of GLRenderer - } - - @Override - void onLayerCreated(HardwareLayer layer) { - // TODO: Is this actually useful? + nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater()); } @Override @@ -309,7 +304,7 @@ public class ThreadedRenderer extends HardwareRenderer { @Override void onLayerDestroyed(HardwareLayer layer) { - nDestroyLayer(mNativeProxy, layer.getDeferredLayerUpdater()); + nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater()); } @Override @@ -398,7 +393,8 @@ public class ThreadedRenderer extends HardwareRenderer { 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); + private static native void nPushLayerUpdate(long nativeProxy, long layer); + private static native void nCancelLayerUpdate(long nativeProxy, long layer); private static native void nFlushCaches(long nativeProxy, int flushMode); diff --git a/core/java/com/android/internal/util/VirtualRefBasePtr.java b/core/java/com/android/internal/util/VirtualRefBasePtr.java index 0bd4d3a..52306f1 100644 --- a/core/java/com/android/internal/util/VirtualRefBasePtr.java +++ b/core/java/com/android/internal/util/VirtualRefBasePtr.java @@ -32,11 +32,17 @@ public final class VirtualRefBasePtr { return mNativePtr; } + public void release() { + if (mNativePtr != 0) { + nDecStrong(mNativePtr); + mNativePtr = 0; + } + } + @Override protected void finalize() throws Throwable { try { - nDecStrong(mNativePtr); - mNativePtr = 0; + release(); } finally { super.finalize(); } diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp index b2f17de..33a2705 100644 --- a/core/jni/android_view_HardwareLayer.cpp +++ b/core/jni/android_view_HardwareLayer.cpp @@ -55,9 +55,7 @@ static jlong android_view_HardwareLayer_createRenderLayer(JNIEnv* env, jobject c Layer* layer = LayerRenderer::createRenderLayer(width, height); if (!layer) return 0; - OpenGLRenderer* renderer = new LayerRenderer(layer); - renderer->initProperties(); - return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer, renderer) ); + return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer) ); } static void android_view_HardwareLayer_onTextureDestroyed(JNIEnv* env, jobject clazz, @@ -66,18 +64,6 @@ static void android_view_HardwareLayer_onTextureDestroyed(JNIEnv* env, jobject c layer->backingLayer()->clearTexture(); } -static jlong android_view_HardwareLayer_detachBackingLayer(JNIEnv* env, jobject clazz, - jlong layerUpdaterPtr) { - DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); - return reinterpret_cast<jlong>( layer->detachBackingLayer() ); -} - -static void android_view_HardwareLayer_destroyLayerUpdater(JNIEnv* env, jobject clazz, - jlong layerUpdaterPtr) { - DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); - delete layer; -} - static jboolean android_view_HardwareLayer_prepare(JNIEnv* env, jobject clazz, jlong layerUpdaterPtr, jint width, jint height, jboolean isOpaque) { DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); @@ -157,8 +143,6 @@ static JNINativeMethod gMethods[] = { { "nCreateTextureLayer", "()J", (void*) android_view_HardwareLayer_createTextureLayer }, { "nCreateRenderLayer", "(II)J", (void*) android_view_HardwareLayer_createRenderLayer }, { "nOnTextureDestroyed", "(J)V", (void*) android_view_HardwareLayer_onTextureDestroyed }, - { "nDetachBackingLayer", "(J)J", (void*) android_view_HardwareLayer_detachBackingLayer }, - { "nDestroyLayerUpdater", "(J)V", (void*) android_view_HardwareLayer_destroyLayerUpdater }, { "nPrepare", "(JIIZ)Z", (void*) android_view_HardwareLayer_prepare }, { "nSetLayerPaint", "(JJ)V", (void*) android_view_HardwareLayer_setLayerPaint }, diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index bd016fd..1397131 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -287,11 +287,18 @@ static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject return proxy->copyLayerInto(layer, bitmap); } -static void android_view_ThreadedRenderer_destroyLayer(JNIEnv* env, jobject clazz, +static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz, jlong proxyPtr, jlong layerPtr) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); - proxy->destroyLayer(layer); + proxy->pushLayerUpdate(layer); +} + +static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz, + jlong proxyPtr, jlong layerPtr) { + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); + proxy->cancelLayerUpdate(layer); } static void android_view_ThreadedRenderer_flushCaches(JNIEnv* env, jobject clazz, @@ -347,7 +354,8 @@ static JNINativeMethod gMethods[] = { { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer }, { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer }, { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto }, - { "nDestroyLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_destroyLayer }, + { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate }, + { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate }, { "nFlushCaches", "(JI)V", (void*) android_view_ThreadedRenderer_flushCaches }, { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence }, { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending }, diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index 285c8c3..97e9bf6 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -22,14 +22,19 @@ namespace android { namespace uirenderer { -DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, OpenGLRenderer* renderer) +static void defaultLayerDestroyer(Layer* layer) { + Caches::getInstance().resourceCache.decrementRefcount(layer); +} + +DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, LayerDestroyer destroyer) : mDisplayList(0) , mSurfaceTexture(0) , mTransform(0) , mNeedsGLContextAttach(false) , mUpdateTexImage(false) , mLayer(layer) - , mCaches(Caches::getInstance()) { + , mCaches(Caches::getInstance()) + , mDestroyer(destroyer) { mWidth = mLayer->layer.getWidth(); mHeight = mLayer->layer.getHeight(); mBlend = mLayer->isBlend(); @@ -37,14 +42,16 @@ DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, OpenGLRenderer* rendere mAlpha = mLayer->getAlpha(); mMode = mLayer->getMode(); mDirtyRect.setEmpty(); + + if (!mDestroyer) { + mDestroyer = defaultLayerDestroyer; + } } DeferredLayerUpdater::~DeferredLayerUpdater() { SkSafeUnref(mColorFilter); setTransform(0); - if (mLayer) { - mCaches.resourceCache.decrementRefcount(mLayer); - } + mDestroyer(mLayer); } void DeferredLayerUpdater::setPaint(const SkPaint* paint) { diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h index cc62caa..b7cfe80 100644 --- a/libs/hwui/DeferredLayerUpdater.h +++ b/libs/hwui/DeferredLayerUpdater.h @@ -30,13 +30,15 @@ namespace android { namespace uirenderer { +typedef void (*LayerDestroyer)(Layer* layer); + // Container to hold the properties a layer should be set to at the start // of a render pass -class DeferredLayerUpdater { +class DeferredLayerUpdater : public VirtualLightRefBase { public: // Note that DeferredLayerUpdater assumes it is taking ownership of the layer // and will not call incrementRef on it as a result. - ANDROID_API DeferredLayerUpdater(Layer* layer, OpenGLRenderer* renderer = 0); + ANDROID_API DeferredLayerUpdater(Layer* layer, LayerDestroyer = 0); ANDROID_API ~DeferredLayerUpdater(); ANDROID_API bool setSize(uint32_t width, uint32_t height) { @@ -83,12 +85,6 @@ public: return mLayer; } - ANDROID_API Layer* detachBackingLayer() { - Layer* layer = mLayer; - mLayer = 0; - return layer; - } - private: // Generic properties uint32_t mWidth; @@ -111,6 +107,8 @@ private: Layer* mLayer; Caches& mCaches; + LayerDestroyer mDestroyer; + void doUpdateTexImage(); }; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index f91e90e..9ebee1d 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -427,27 +427,11 @@ void CanvasContext::makeCurrent() { mHaveNewSurface |= mGlobalContext->makeCurrent(mEglSurface); } -void CanvasContext::prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters, - TreeInfo& info) { - LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot prepareDraw without a canvas!"); - makeCurrent(); - - processLayerUpdates(layerUpdaters, info); - if (info.out.hasAnimations) { - // TODO: Uh... crap? - } - prepareTree(info); -} - -void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, - TreeInfo& info) { - for (size_t i = 0; i < layerUpdaters->size(); i++) { - DeferredLayerUpdater* update = layerUpdaters->itemAt(i); - bool success = update->apply(info); - LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!"); - if (update->backingLayer()->deferredUpdateScheduled) { - mCanvas->pushLayerUpdate(update->backingLayer()); - } +void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater, TreeInfo& info) { + bool success = layerUpdater->apply(info); + LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!"); + if (layerUpdater->backingLayer()->deferredUpdateScheduled) { + mCanvas->pushLayerUpdate(layerUpdater->backingLayer()); } } diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index a04269b..00c5bf0 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -55,7 +55,8 @@ public: void setup(int width, int height, const Vector3& lightCenter, float lightRadius); void setOpaque(bool opaque); void makeCurrent(); - void prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info); + void processLayerUpdate(DeferredLayerUpdater* layerUpdater, TreeInfo& info); + void prepareTree(TreeInfo& info); void draw(Rect* dirty); void destroyCanvasAndSurface(); @@ -83,9 +84,6 @@ public: private: friend class RegisterFrameCallbackTask; - void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info); - void prepareTree(TreeInfo& info); - void setSurface(ANativeWindow* window); void swapBuffers(); void requireSurface(); diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index 7ea358f..61d67ca 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -21,6 +21,7 @@ #include <utils/Log.h> #include <utils/Trace.h> +#include "../DeferredLayerUpdater.h" #include "../DisplayList.h" #include "../RenderNode.h" #include "CanvasContext.h" @@ -47,17 +48,22 @@ void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context) { mContext = context; } -void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) { - LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to addLayer with!"); +void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) { + LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to pushLayerUpdate with!"); - mLayers.push(layer); + for (size_t i = 0; i < mLayers.size(); i++) { + if (mLayers[i].get() == layer) { + return; + } + } + mLayers.push_back(layer); } -void DrawFrameTask::removeLayer(DeferredLayerUpdater* layer) { +void DrawFrameTask::removeLayerUpdate(DeferredLayerUpdater* layer) { for (size_t i = 0; i < mLayers.size(); i++) { - if (mLayers[i] == layer) { - mLayers.removeAt(i); - break; + if (mLayers[i].get() == layer) { + mLayers.erase(mLayers.begin() + i); + return; } } } @@ -132,7 +138,16 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) { mContext->makeCurrent(); Caches::getInstance().textureCache.resetMarkInUse(); initTreeInfo(info); - mContext->prepareDraw(&mLayers, info); + + for (size_t i = 0; i < mLayers.size(); i++) { + mContext->processLayerUpdate(mLayers[i].get(), info); + } + mLayers.clear(); + if (info.out.hasAnimations) { + // TODO: Uh... crap? + } + mContext->prepareTree(info); + if (info.out.hasAnimations) { // TODO: dirty calculations, for now just do a full-screen inval mDirty.setEmpty(); diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h index 30c8880..d4129b6 100644 --- a/libs/hwui/renderthread/DrawFrameTask.h +++ b/libs/hwui/renderthread/DrawFrameTask.h @@ -16,10 +16,11 @@ #ifndef DRAWFRAMETASK_H #define DRAWFRAMETASK_H +#include <vector> + #include <utils/Condition.h> #include <utils/Mutex.h> #include <utils/StrongPointer.h> -#include <utils/Vector.h> #include "RenderTask.h" @@ -56,8 +57,8 @@ public: void setContext(RenderThread* thread, CanvasContext* context); - void addLayer(DeferredLayerUpdater* layer); - void removeLayer(DeferredLayerUpdater* layer); + void pushLayerUpdate(DeferredLayerUpdater* layer); + void removeLayerUpdate(DeferredLayerUpdater* layer); void setDirty(int left, int top, int right, int bottom); void setDensity(float density) { mDensity = density; } @@ -83,13 +84,9 @@ private: nsecs_t mFrameTimeNanos; nsecs_t mRecordDurationNanos; float mDensity; + std::vector< sp<DeferredLayerUpdater> > mLayers; int mSyncResult; - - /********************************************* - * Multi frame data - *********************************************/ - Vector<DeferredLayerUpdater*> mLayers; }; } /* namespace renderthread */ diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 77c0aa7..0901963 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -229,10 +229,21 @@ void RenderProxy::runWithGlContext(RenderTask* gltask) { postAndWait(task); } +CREATE_BRIDGE1(destroyLayer, Layer* layer) { + LayerRenderer::destroyLayer(args->layer); + return NULL; +} + +static void enqueueDestroyLayer(Layer* layer) { + SETUP_TASK(destroyLayer); + args->layer = layer; + RenderThread::getInstance().queue(task); +} + CREATE_BRIDGE3(createDisplayListLayer, CanvasContext* context, int width, int height) { Layer* layer = args->context->createRenderLayer(args->width, args->height); if (!layer) return 0; - return new DeferredLayerUpdater(layer); + return new DeferredLayerUpdater(layer, enqueueDestroyLayer); } DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) { @@ -242,14 +253,13 @@ DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) args->context = mContext; void* retval = postAndWait(task); DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); - mDrawFrameTask.addLayer(layer); return layer; } CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) { Layer* layer = args->context->createTextureLayer(); if (!layer) return 0; - return new DeferredLayerUpdater(layer); + return new DeferredLayerUpdater(layer, enqueueDestroyLayer); } DeferredLayerUpdater* RenderProxy::createTextureLayer() { @@ -257,15 +267,9 @@ DeferredLayerUpdater* RenderProxy::createTextureLayer() { args->context = mContext; void* retval = postAndWait(task); DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); - mDrawFrameTask.addLayer(layer); return layer; } -CREATE_BRIDGE1(destroyLayer, Layer* layer) { - LayerRenderer::destroyLayer(args->layer); - return NULL; -} - CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer, SkBitmap* bitmap) { bool success = args->context->copyLayerInto(args->layer, args->bitmap); @@ -280,11 +284,12 @@ bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { return (bool) postAndWait(task); } -void RenderProxy::destroyLayer(DeferredLayerUpdater* layer) { - mDrawFrameTask.removeLayer(layer); - SETUP_TASK(destroyLayer); - args->layer = layer->detachBackingLayer(); - post(task); +void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { + mDrawFrameTask.pushLayerUpdate(layer); +} + +void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) { + mDrawFrameTask.removeLayerUpdate(layer); } CREATE_BRIDGE2(flushCaches, CanvasContext* context, Caches::FlushMode flushMode) { diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index c8d42ec..944ff9c 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -80,7 +80,8 @@ public: ANDROID_API DeferredLayerUpdater* createDisplayListLayer(int width, int height); ANDROID_API DeferredLayerUpdater* createTextureLayer(); ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap); - ANDROID_API void destroyLayer(DeferredLayerUpdater* layer); + ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer); + ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer); ANDROID_API void flushCaches(Caches::FlushMode flushMode); |