Loading core/java/android/view/View.java +5 −3 Original line number Diff line number Diff line Loading @@ -13625,9 +13625,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @hide */ protected void destroyHardwareResources() { // Intentionally empty. RenderNode's lifecycle is now fully managed // by the hardware renderer. // However some subclasses (eg, WebView, TextureView) still need this signal // Although the Layer will be destroyed by RenderNode, we want to release // the staging display list, which is also a signal to RenderNode that it's // safe to free its copy of the display list as it knows that we will // push an updated DisplayList if we try to draw again resetDisplayList(); } /** libs/hwui/RenderNode.cpp +54 −26 Original line number Diff line number Diff line Loading @@ -63,11 +63,12 @@ RenderNode::RenderNode() , mDisplayListData(0) , mStagingDisplayListData(0) , mAnimatorManager(*this) , mLayer(0) { , mLayer(0) , mParentCount(0) { } RenderNode::~RenderNode() { delete mDisplayListData; deleteDisplayListData(); delete mStagingDisplayListData; LayerRenderer::destroyLayerDeferred(mLayer); } Loading Loading @@ -196,27 +197,12 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { void RenderNode::prepareTreeImpl(TreeInfo& info) { info.damageAccumulator->pushTransform(this); switch (info.mode) { case TreeInfo::MODE_FULL: pushStagingPropertiesChanges(info); mAnimatorManager.animate(info); break; case TreeInfo::MODE_MAYBE_DETACHING: if (info.mode == TreeInfo::MODE_FULL) { pushStagingPropertiesChanges(info); break; case TreeInfo::MODE_RT_ONLY: mAnimatorManager.animate(info); break; case TreeInfo::MODE_DESTROY_RESOURCES: // This will also release the hardware layer if we have one as // isRenderable() will return false, thus causing pushLayerUpdate // to recycle the hardware layer setStagingDisplayList(NULL); break; } mAnimatorManager.animate(info); prepareLayer(info); if (info.mode == TreeInfo::MODE_FULL || info.mode == TreeInfo::MODE_DESTROY_RESOURCES) { if (info.mode == TreeInfo::MODE_FULL) { pushStagingDisplayListChanges(info); } prepareSubTree(info, mDisplayListData); Loading Loading @@ -258,17 +244,30 @@ void RenderNode::applyLayerPropertiesToLayer(TreeInfo& info) { void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) { if (mNeedsDisplayListDataSync) { mNeedsDisplayListDataSync = false; // Do a push pass on the old tree to handle freeing DisplayListData // that are no longer used TreeInfo oldTreeInfo(TreeInfo::MODE_MAYBE_DETACHING, info); prepareSubTree(oldTreeInfo, mDisplayListData); delete mDisplayListData; // Make sure we inc first so that we don't fluctuate between 0 and 1, // which would thrash the layer cache if (mStagingDisplayListData) { for (size_t i = 0; i < mStagingDisplayListData->children().size(); i++) { mStagingDisplayListData->children()[i]->mRenderNode->incParentRefCount(); } } deleteDisplayListData(); mDisplayListData = mStagingDisplayListData; mStagingDisplayListData = 0; mStagingDisplayListData = NULL; damageSelf(info); } } void RenderNode::deleteDisplayListData() { if (mDisplayListData) { for (size_t i = 0; i < mDisplayListData->children().size(); i++) { mDisplayListData->children()[i]->mRenderNode->decParentRefCount(); } } delete mDisplayListData; mDisplayListData = NULL; } void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) { if (subtree) { TextureCache& cache = Caches::getInstance().textureCache; Loading @@ -291,6 +290,35 @@ void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) { } } void RenderNode::destroyHardwareResources() { if (mLayer) { LayerRenderer::destroyLayer(mLayer); mLayer = NULL; } if (mDisplayListData) { for (size_t i = 0; i < mDisplayListData->children().size(); i++) { mDisplayListData->children()[i]->mRenderNode->destroyHardwareResources(); } if (mNeedsDisplayListDataSync) { // Next prepare tree we are going to push a new display list, so we can // drop our current one now deleteDisplayListData(); } } } void RenderNode::decParentRefCount() { LOG_ALWAYS_FATAL_IF(!mParentCount, "already 0!"); mParentCount--; if (!mParentCount) { // If a child of ours is being attached to our parent then this will incorrectly // destroy its hardware resources. However, this situation is highly unlikely // and the failure is "just" that the layer is re-created, so this should // be safe enough destroyHardwareResources(); } } /* * For property operations, we pass a savecount of 0, since the operations aren't part of the * displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in Loading libs/hwui/RenderNode.h +14 −0 Original line number Diff line number Diff line Loading @@ -168,6 +168,7 @@ public: } ANDROID_API virtual void prepareTree(TreeInfo& info); void destroyHardwareResources(); // UI thread only! ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator); Loading Loading @@ -248,6 +249,10 @@ private: void applyLayerPropertiesToLayer(TreeInfo& info); void prepareLayer(TreeInfo& info); void pushLayerUpdate(TreeInfo& info); void deleteDisplayListData(); void incParentRefCount() { mParentCount++; } void decParentRefCount(); String8 mName; Loading @@ -256,6 +261,7 @@ private: RenderProperties mStagingProperties; bool mNeedsDisplayListDataSync; // WARNING: Do not delete this directly, you must go through deleteDisplayListData()! DisplayListData* mDisplayListData; DisplayListData* mStagingDisplayListData; Loading @@ -272,6 +278,14 @@ private: // for projection surfaces, contains a list of all children items Vector<DrawRenderNodeOp*> mProjectedNodes; // How many references our parent(s) have to us. Typically this should alternate // between 2 and 1 (when a staging push happens we inc first then dec) // When this hits 0 we are no longer in the tree, so any hardware resources // (specifically Layers) should be released. // This is *NOT* thread-safe, and should therefore only be tracking // mDisplayListData, not mStagingDisplayListData. uint32_t mParentCount; }; // class RenderNode } /* namespace uirenderer */ Loading libs/hwui/TreeInfo.h +0 −9 Original line number Diff line number Diff line Loading @@ -58,15 +58,6 @@ public: // animators, but potentially things like SurfaceTexture updates // could be handled by this as well if there are no listeners MODE_RT_ONLY, // The subtree is being detached. Maybe. If the RenderNode is present // in both the old and new display list's children then it will get a // MODE_MAYBE_DETACHING followed shortly by a MODE_FULL. // Push any pending display list changes in case it is detached, // but don't evaluate animators and such as if it isn't detached as a // MODE_FULL will follow shortly. MODE_MAYBE_DETACHING, // Destroy all hardware resources, including DisplayListData, in the tree. MODE_DESTROY_RESOURCES, }; explicit TreeInfo(TraversalMode mode, RenderState& renderState) Loading libs/hwui/renderthread/CanvasContext.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -250,8 +250,7 @@ void CanvasContext::destroyHardwareResources() { stopDrawing(); if (mEglManager.hasEglContext()) { requireGlContext(); TreeInfo info(TreeInfo::MODE_DESTROY_RESOURCES, mRenderThread.renderState()); mRootRenderNode->prepareTree(info); mRootRenderNode->destroyHardwareResources(); Caches::getInstance().flush(Caches::kFlushMode_Layers); } } Loading Loading
core/java/android/view/View.java +5 −3 Original line number Diff line number Diff line Loading @@ -13625,9 +13625,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @hide */ protected void destroyHardwareResources() { // Intentionally empty. RenderNode's lifecycle is now fully managed // by the hardware renderer. // However some subclasses (eg, WebView, TextureView) still need this signal // Although the Layer will be destroyed by RenderNode, we want to release // the staging display list, which is also a signal to RenderNode that it's // safe to free its copy of the display list as it knows that we will // push an updated DisplayList if we try to draw again resetDisplayList(); } /**
libs/hwui/RenderNode.cpp +54 −26 Original line number Diff line number Diff line Loading @@ -63,11 +63,12 @@ RenderNode::RenderNode() , mDisplayListData(0) , mStagingDisplayListData(0) , mAnimatorManager(*this) , mLayer(0) { , mLayer(0) , mParentCount(0) { } RenderNode::~RenderNode() { delete mDisplayListData; deleteDisplayListData(); delete mStagingDisplayListData; LayerRenderer::destroyLayerDeferred(mLayer); } Loading Loading @@ -196,27 +197,12 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { void RenderNode::prepareTreeImpl(TreeInfo& info) { info.damageAccumulator->pushTransform(this); switch (info.mode) { case TreeInfo::MODE_FULL: pushStagingPropertiesChanges(info); mAnimatorManager.animate(info); break; case TreeInfo::MODE_MAYBE_DETACHING: if (info.mode == TreeInfo::MODE_FULL) { pushStagingPropertiesChanges(info); break; case TreeInfo::MODE_RT_ONLY: mAnimatorManager.animate(info); break; case TreeInfo::MODE_DESTROY_RESOURCES: // This will also release the hardware layer if we have one as // isRenderable() will return false, thus causing pushLayerUpdate // to recycle the hardware layer setStagingDisplayList(NULL); break; } mAnimatorManager.animate(info); prepareLayer(info); if (info.mode == TreeInfo::MODE_FULL || info.mode == TreeInfo::MODE_DESTROY_RESOURCES) { if (info.mode == TreeInfo::MODE_FULL) { pushStagingDisplayListChanges(info); } prepareSubTree(info, mDisplayListData); Loading Loading @@ -258,17 +244,30 @@ void RenderNode::applyLayerPropertiesToLayer(TreeInfo& info) { void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) { if (mNeedsDisplayListDataSync) { mNeedsDisplayListDataSync = false; // Do a push pass on the old tree to handle freeing DisplayListData // that are no longer used TreeInfo oldTreeInfo(TreeInfo::MODE_MAYBE_DETACHING, info); prepareSubTree(oldTreeInfo, mDisplayListData); delete mDisplayListData; // Make sure we inc first so that we don't fluctuate between 0 and 1, // which would thrash the layer cache if (mStagingDisplayListData) { for (size_t i = 0; i < mStagingDisplayListData->children().size(); i++) { mStagingDisplayListData->children()[i]->mRenderNode->incParentRefCount(); } } deleteDisplayListData(); mDisplayListData = mStagingDisplayListData; mStagingDisplayListData = 0; mStagingDisplayListData = NULL; damageSelf(info); } } void RenderNode::deleteDisplayListData() { if (mDisplayListData) { for (size_t i = 0; i < mDisplayListData->children().size(); i++) { mDisplayListData->children()[i]->mRenderNode->decParentRefCount(); } } delete mDisplayListData; mDisplayListData = NULL; } void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) { if (subtree) { TextureCache& cache = Caches::getInstance().textureCache; Loading @@ -291,6 +290,35 @@ void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) { } } void RenderNode::destroyHardwareResources() { if (mLayer) { LayerRenderer::destroyLayer(mLayer); mLayer = NULL; } if (mDisplayListData) { for (size_t i = 0; i < mDisplayListData->children().size(); i++) { mDisplayListData->children()[i]->mRenderNode->destroyHardwareResources(); } if (mNeedsDisplayListDataSync) { // Next prepare tree we are going to push a new display list, so we can // drop our current one now deleteDisplayListData(); } } } void RenderNode::decParentRefCount() { LOG_ALWAYS_FATAL_IF(!mParentCount, "already 0!"); mParentCount--; if (!mParentCount) { // If a child of ours is being attached to our parent then this will incorrectly // destroy its hardware resources. However, this situation is highly unlikely // and the failure is "just" that the layer is re-created, so this should // be safe enough destroyHardwareResources(); } } /* * For property operations, we pass a savecount of 0, since the operations aren't part of the * displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in Loading
libs/hwui/RenderNode.h +14 −0 Original line number Diff line number Diff line Loading @@ -168,6 +168,7 @@ public: } ANDROID_API virtual void prepareTree(TreeInfo& info); void destroyHardwareResources(); // UI thread only! ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator); Loading Loading @@ -248,6 +249,10 @@ private: void applyLayerPropertiesToLayer(TreeInfo& info); void prepareLayer(TreeInfo& info); void pushLayerUpdate(TreeInfo& info); void deleteDisplayListData(); void incParentRefCount() { mParentCount++; } void decParentRefCount(); String8 mName; Loading @@ -256,6 +261,7 @@ private: RenderProperties mStagingProperties; bool mNeedsDisplayListDataSync; // WARNING: Do not delete this directly, you must go through deleteDisplayListData()! DisplayListData* mDisplayListData; DisplayListData* mStagingDisplayListData; Loading @@ -272,6 +278,14 @@ private: // for projection surfaces, contains a list of all children items Vector<DrawRenderNodeOp*> mProjectedNodes; // How many references our parent(s) have to us. Typically this should alternate // between 2 and 1 (when a staging push happens we inc first then dec) // When this hits 0 we are no longer in the tree, so any hardware resources // (specifically Layers) should be released. // This is *NOT* thread-safe, and should therefore only be tracking // mDisplayListData, not mStagingDisplayListData. uint32_t mParentCount; }; // class RenderNode } /* namespace uirenderer */ Loading
libs/hwui/TreeInfo.h +0 −9 Original line number Diff line number Diff line Loading @@ -58,15 +58,6 @@ public: // animators, but potentially things like SurfaceTexture updates // could be handled by this as well if there are no listeners MODE_RT_ONLY, // The subtree is being detached. Maybe. If the RenderNode is present // in both the old and new display list's children then it will get a // MODE_MAYBE_DETACHING followed shortly by a MODE_FULL. // Push any pending display list changes in case it is detached, // but don't evaluate animators and such as if it isn't detached as a // MODE_FULL will follow shortly. MODE_MAYBE_DETACHING, // Destroy all hardware resources, including DisplayListData, in the tree. MODE_DESTROY_RESOURCES, }; explicit TreeInfo(TraversalMode mode, RenderState& renderState) Loading
libs/hwui/renderthread/CanvasContext.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -250,8 +250,7 @@ void CanvasContext::destroyHardwareResources() { stopDrawing(); if (mEglManager.hasEglContext()) { requireGlContext(); TreeInfo info(TreeInfo::MODE_DESTROY_RESOURCES, mRenderThread.renderState()); mRootRenderNode->prepareTree(info); mRootRenderNode->destroyHardwareResources(); Caches::getInstance().flush(Caches::kFlushMode_Layers); } } Loading