diff options
author | John Reck <jreck@google.com> | 2014-04-07 22:42:21 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-04-07 22:42:21 +0000 |
commit | 96c637e9414600a67c71014274e7757161dcc709 (patch) | |
tree | 4840374c35af37bc235dbe885dd03cb4c315fe3a /libs | |
parent | 8ea553d03a84e2fc3ded507dd978fca0dee22e77 (diff) | |
parent | 087bc0c14bdccf7c258dce0cdef46a69a839b427 (diff) | |
download | frameworks_base-96c637e9414600a67c71014274e7757161dcc709.zip frameworks_base-96c637e9414600a67c71014274e7757161dcc709.tar.gz frameworks_base-96c637e9414600a67c71014274e7757161dcc709.tar.bz2 |
Merge "Refcount RenderNode"
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Caches.cpp | 16 | ||||
-rw-r--r-- | libs/hwui/Caches.h | 6 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.h | 2 | ||||
-rw-r--r-- | libs/hwui/DisplayList.cpp | 14 | ||||
-rw-r--r-- | libs/hwui/DisplayList.h | 16 | ||||
-rw-r--r-- | libs/hwui/DisplayListOp.h | 2 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/Layer.cpp | 11 | ||||
-rw-r--r-- | libs/hwui/Layer.h | 11 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 35 | ||||
-rw-r--r-- | libs/hwui/RenderNode.h | 4 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.cpp | 64 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.h | 25 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/utils/VirtualLightRefBase.h | 34 |
17 files changed, 173 insertions, 82 deletions
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 477d691..df2123b 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -315,24 +315,15 @@ void Caches::clearGarbage() { pathCache.clearGarbage(); patchCache.clearGarbage(); - Vector<RenderNode*> displayLists; Vector<Layer*> layers; { // scope for the lock Mutex::Autolock _l(mGarbageLock); - displayLists = mDisplayListGarbage; layers = mLayerGarbage; - mDisplayListGarbage.clear(); mLayerGarbage.clear(); } - size_t count = displayLists.size(); - for (size_t i = 0; i < count; i++) { - RenderNode* displayList = displayLists.itemAt(i); - delete displayList; - } - - count = layers.size(); + size_t count = layers.size(); for (size_t i = 0; i < count; i++) { Layer* layer = layers.itemAt(i); delete layer; @@ -345,11 +336,6 @@ void Caches::deleteLayerDeferred(Layer* layer) { mLayerGarbage.push(layer); } -void Caches::deleteDisplayListDeferred(RenderNode* displayList) { - Mutex::Autolock _l(mGarbageLock); - mDisplayListGarbage.push(displayList); -} - void Caches::flush(FlushMode mode) { FLUSH_LOGD("Flushing caches (mode %d)", mode); diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index 50c5fef..ba3ccaf 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -166,11 +166,6 @@ public: */ void deleteLayerDeferred(Layer* layer); - /* - * Can be used to delete a display list from a non EGL thread. - */ - void deleteDisplayListDeferred(RenderNode* layer); - /** * Binds the VBO used to render simple textured quads. */ @@ -420,7 +415,6 @@ private: mutable Mutex mGarbageLock; Vector<Layer*> mLayerGarbage; - Vector<RenderNode*> mDisplayListGarbage; DebugLevel mDebugLevel; bool mInitialized; diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index 5b4e03f..ce711b6 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -68,13 +68,13 @@ bool DeferredLayerUpdater::apply() { mLayer->setColorFilter(mColorFilter); mLayer->setAlpha(mAlpha, mMode); - if (mDisplayList) { + if (mDisplayList.get()) { if (mWidth != mLayer->layer.getWidth() || mHeight != mLayer->layer.getHeight()) { success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight); } mLayer->setBlend(mBlend); mDisplayList->updateProperties(); - mLayer->updateDeferred(mDisplayList, + mLayer->updateDeferred(mDisplayList.get(), mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom); mDirtyRect.setEmpty(); mDisplayList = 0; diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h index 10fa264..ce08c2d 100644 --- a/libs/hwui/DeferredLayerUpdater.h +++ b/libs/hwui/DeferredLayerUpdater.h @@ -101,7 +101,7 @@ private: // Layer type specific properties // displayList and surfaceTexture are mutually exclusive, only 1 may be set // dirtyRect is only valid if displayList is set - RenderNode* mDisplayList; + sp<RenderNode> mDisplayList; Rect mDirtyRect; sp<GLConsumer> mSurfaceTexture; SkMatrix* mTransform; diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index 9e6a96d..a5d8dcb 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -29,6 +29,13 @@ namespace android { namespace uirenderer { +DisplayListData::DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) { +} + +DisplayListData::~DisplayListData() { + cleanupResources(); +} + void DisplayListData::cleanupResources() { Caches& caches = Caches::getInstance(); caches.unregisterFunctors(functorCount); @@ -91,5 +98,12 @@ void DisplayListData::cleanupResources() { layers.clear(); } +void DisplayListData::addChild(DrawDisplayListOp* op) { + LOG_ALWAYS_FATAL_IF(!op->renderNode(), "DrawDisplayListOp with no render node!"); + + mChildren.push(op); + mReferenceHolders.push(op->renderNode()); +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index df5cba6..fe70d13 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -41,6 +41,7 @@ #include "Matrix.h" #include "DeferredDisplayList.h" #include "RenderProperties.h" +#include "utils/VirtualLightRefBase.h" class SkBitmap; class SkPaint; @@ -106,8 +107,8 @@ public: */ class DisplayListData { public: - DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) {} - virtual ~DisplayListData() { cleanupResources(); } + DisplayListData(); + ~DisplayListData(); // allocator into which all ops were allocated LinearAllocator allocator; @@ -115,9 +116,6 @@ public: // pointers to all ops within display list, pointing into allocator data Vector<DisplayListOp*> displayListOps; - // list of children display lists for quick, non-drawing traversal - Vector<DrawDisplayListOp*> children; - // index of DisplayListOp restore, after which projected descendents should be drawn int projectionReceiveIndex; @@ -139,7 +137,15 @@ public: return !displayListOps.size(); } + void addChild(DrawDisplayListOp* childOp); + const Vector<DrawDisplayListOp*>& children() { return mChildren; } + private: + Vector< sp<VirtualLightRefBase> > mReferenceHolders; + + // list of children display lists for quick, non-drawing traversal + Vector<DrawDisplayListOp*> mChildren; + void cleanupResources(); }; diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 5fa8f1d..06f675e 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -1523,6 +1523,8 @@ public: virtual const char* name() { return "DrawDisplayList"; } + RenderNode* renderNode() { return mDisplayList; } + private: RenderNode* mDisplayList; const int mFlags; diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 78c97e1..a84aa6b 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -191,7 +191,7 @@ status_t DisplayListRenderer::drawDisplayList(RenderNode* displayList, DrawDisplayListOp* op = new (alloc()) DrawDisplayListOp(displayList, flags, *currentTransform()); addDrawOp(op); - mDisplayListData->children.push(op); + mDisplayListData->addChild(op); if (displayList->isProjectionReceiver()) { mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size() - 1; } diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index 27409a2..bfe4eda 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -140,6 +140,15 @@ void Layer::removeFbo(bool flush) { } } +void Layer::updateDeferred(RenderNode* displayList, + int left, int top, int right, int bottom) { + requireRenderer(); + this->displayList = displayList; + const Rect r(left, top, right, bottom); + dirtyRect.unionWith(r); + deferredUpdateScheduled = true; +} + void Layer::setPaint(const SkPaint* paint) { OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode); setColorFilter((paint) ? paint->getColorFilter() : NULL); @@ -244,7 +253,7 @@ void Layer::render() { renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, !isBlend()); - renderer->drawDisplayList(displayList, dirtyRect, RenderNode::kReplayFlag_ClipChildren); + renderer->drawDisplayList(displayList.get(), dirtyRect, RenderNode::kReplayFlag_ClipChildren); renderer->finish(); diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index b428404..5375b45 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -19,6 +19,7 @@ #include <cutils/compiler.h> #include <sys/types.h> +#include <utils/StrongPointer.h> #include <GLES2/gl2.h> @@ -85,13 +86,7 @@ public: } void updateDeferred(RenderNode* displayList, - int left, int top, int right, int bottom) { - requireRenderer(); - this->displayList = displayList; - const Rect r(left, top, right, bottom); - dirtyRect.unionWith(r); - deferredUpdateScheduled = true; - } + int left, int top, int right, int bottom); inline uint32_t getWidth() const { return texture.width; @@ -294,7 +289,7 @@ public: */ bool deferredUpdateScheduled; OpenGLRenderer* renderer; - RenderNode* displayList; + sp<RenderNode> displayList; Rect dirtyRect; bool debugDrawUpdate; bool hasDrawnSinceUpdate; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index e1f484d..9dbcd36 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -537,7 +537,7 @@ void OpenGLRenderer::countOverdraw() { bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) { if (layer->deferredUpdateScheduled && layer->renderer && - layer->displayList && layer->displayList->isRenderable()) { + layer->displayList.get() && layer->displayList->isRenderable()) { ATRACE_CALL(); Rect& dirty = layer->dirtyRect; diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 663b67e..5010076 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -59,17 +59,6 @@ RenderNode::~RenderNode() { delete mDisplayListData; } -void RenderNode::destroyDisplayListDeferred(RenderNode* displayList) { - if (displayList) { - if (Caches::hasInstance()) { - DISPLAY_LIST_LOGD("Deferring display list destruction"); - Caches::getInstance().deleteDisplayListDeferred(displayList); - } else { - delete displayList; - } - } -} - void RenderNode::setData(DisplayListData* data) { delete mDisplayListData; mDisplayListData = data; @@ -104,8 +93,8 @@ void RenderNode::updateProperties() { } if (mDisplayListData) { - for (size_t i = 0; i < mDisplayListData->children.size(); i++) { - RenderNode* childNode = mDisplayListData->children[i]->mDisplayList; + for (size_t i = 0; i < mDisplayListData->children().size(); i++) { + RenderNode* childNode = mDisplayListData->children()[i]->mDisplayList; childNode->updateProperties(); } } @@ -118,8 +107,8 @@ bool RenderNode::hasFunctors() { return true; } - for (size_t i = 0; i < mDisplayListData->children.size(); i++) { - RenderNode* childNode = mDisplayListData->children[i]->mDisplayList; + for (size_t i = 0; i < mDisplayListData->children().size(); i++) { + RenderNode* childNode = mDisplayListData->children()[i]->mDisplayList; if (childNode->hasFunctors()) { return true; } @@ -248,8 +237,8 @@ void RenderNode::computeOrdering() { // TODO: create temporary DDLOp and call computeOrderingImpl on top DisplayList so that // transform properties are applied correctly to top level children if (mDisplayListData == NULL) return; - for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) { - DrawDisplayListOp* childOp = mDisplayListData->children[i]; + for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) { + DrawDisplayListOp* childOp = mDisplayListData->children()[i]; childOp->mDisplayList->computeOrderingImpl(childOp, &mProjectedNodes, &mat4::identity()); } @@ -277,11 +266,11 @@ void RenderNode::computeOrderingImpl( opState->mSkipInOrderDraw = false; } - if (mDisplayListData->children.size() > 0) { + if (mDisplayListData->children().size() > 0) { const bool isProjectionReceiver = mDisplayListData->projectionReceiveIndex >= 0; bool haveAppliedPropertiesToProjection = false; - for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) { - DrawDisplayListOp* childOp = mDisplayListData->children[i]; + for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) { + DrawDisplayListOp* childOp = mDisplayListData->children()[i]; RenderNode* child = childOp->mDisplayList; Vector<DrawDisplayListOp*>* projectionChildren = NULL; @@ -375,10 +364,10 @@ void RenderNode::replayNodeInParent(ReplayStateStruct& replayStruct, const int l } void RenderNode::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes) { - if (mDisplayListData == NULL || mDisplayListData->children.size() == 0) return; + if (mDisplayListData == NULL || mDisplayListData->children().size() == 0) return; - for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) { - DrawDisplayListOp* childOp = mDisplayListData->children[i]; + for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) { + DrawDisplayListOp* childOp = mDisplayListData->children()[i]; RenderNode* child = childOp->mDisplayList; float childZ = child->properties().getTranslationZ(); diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index fb5336d..fd0fabc 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -41,6 +41,7 @@ #include "DeferredDisplayList.h" #include "DisplayList.h" #include "RenderProperties.h" +#include "utils/VirtualLightRefBase.h" class SkBitmap; class SkPaint; @@ -76,7 +77,7 @@ class DrawDisplayListOp; * recorded stream of canvas operations is refreshed. The DisplayList (and its properties) stay * attached. */ -class RenderNode { +class RenderNode : public VirtualLightRefBase { public: ANDROID_API RenderNode(); ANDROID_API ~RenderNode(); @@ -86,7 +87,6 @@ public: kReplayFlag_ClipChildren = 0x1 }; - ANDROID_API static void destroyDisplayListDeferred(RenderNode* displayList); ANDROID_API static void outputLogBuffer(int fd); ANDROID_API void setData(DisplayListData* newData); diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index 1e9089a..7b509a2 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -30,7 +30,19 @@ namespace android { namespace uirenderer { namespace renderthread { -DrawFrameTask::DrawFrameTask() : mContext(0), mRenderNode(0) { +SetDisplayListData::SetDisplayListData() : mNewData(0) {} + +SetDisplayListData::SetDisplayListData(RenderNode* node, DisplayListData* newData) + : mTargetNode(node), mNewData(newData) { +} + +SetDisplayListData::~SetDisplayListData() {} + +void SetDisplayListData::apply() const { + mTargetNode->setData(mNewData); +} + +DrawFrameTask::DrawFrameTask() : mContext(0), mTaskMode(MODE_INVALID), mRenderNode(0) { } DrawFrameTask::~DrawFrameTask() { @@ -41,13 +53,15 @@ void DrawFrameTask::setContext(CanvasContext* context) { } void DrawFrameTask::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) { - SetDisplayListData setter; - setter.targetNode = renderNode; - setter.newData = newData; + LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to setDisplayListData with!"); + + SetDisplayListData setter(renderNode, newData); mDisplayListDataUpdates.push(setter); } void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) { + LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to addLayer with!"); + mLayers.push(layer); } @@ -61,6 +75,8 @@ void DrawFrameTask::removeLayer(DeferredLayerUpdater* layer) { } void DrawFrameTask::setRenderNode(RenderNode* renderNode) { + LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to setRenderNode with!"); + mRenderNode = renderNode; } @@ -69,37 +85,55 @@ void DrawFrameTask::setDirty(int left, int top, int right, int bottom) { } void DrawFrameTask::drawFrame(RenderThread* renderThread) { - LOG_ALWAYS_FATAL_IF(!mRenderNode, "Cannot drawFrame with no render node!"); + LOG_ALWAYS_FATAL_IF(!mRenderNode.get(), "Cannot drawFrame with no render node!"); LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!"); - AutoMutex _lock(mLock); - renderThread->queue(this); - mSignal.wait(mLock); + postAndWait(renderThread, MODE_FULL); // Reset the single-frame data mDirty.setEmpty(); mRenderNode = 0; } +void DrawFrameTask::flushStateChanges(RenderThread* renderThread) { + LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!"); + + postAndWait(renderThread, MODE_STATE_ONLY); +} + +void DrawFrameTask::postAndWait(RenderThread* renderThread, TaskMode mode) { + LOG_ALWAYS_FATAL_IF(mode == MODE_INVALID, "That's not a real mode, silly!"); + + mTaskMode = mode; + AutoMutex _lock(mLock); + renderThread->queue(this); + mSignal.wait(mLock); +} + void DrawFrameTask::run() { ATRACE_NAME("DrawFrame"); syncFrameState(); + if (mTaskMode == MODE_STATE_ONLY) { + unblockUiThread(); + return; + } + // Grab a copy of everything we need Rect dirtyCopy(mDirty); - RenderNode* renderNode = mRenderNode; + sp<RenderNode> renderNode = mRenderNode; CanvasContext* context = mContext; // This is temporary until WebView has a solution for syncing frame state - bool canUnblockUiThread = !requiresSynchronousDraw(renderNode); + bool canUnblockUiThread = !requiresSynchronousDraw(renderNode.get()); // From this point on anything in "this" is *UNSAFE TO ACCESS* if (canUnblockUiThread) { unblockUiThread(); } - drawRenderNode(context, renderNode, &dirtyCopy); + drawRenderNode(context, renderNode.get(), &dirtyCopy); if (!canUnblockUiThread) { unblockUiThread(); @@ -111,12 +145,16 @@ void DrawFrameTask::syncFrameState() { for (size_t i = 0; i < mDisplayListDataUpdates.size(); i++) { const SetDisplayListData& setter = mDisplayListDataUpdates[i]; - setter.targetNode->setData(setter.newData); + setter.apply(); } mDisplayListDataUpdates.clear(); mContext->processLayerUpdates(&mLayers); - mRenderNode->updateProperties(); + + // If we don't have an mRenderNode this is a state flush only + if (mRenderNode.get()) { + mRenderNode->updateProperties(); + } } void DrawFrameTask::unblockUiThread() { diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h index 5450dd5..4e9b244 100644 --- a/libs/hwui/renderthread/DrawFrameTask.h +++ b/libs/hwui/renderthread/DrawFrameTask.h @@ -18,6 +18,7 @@ #include <utils/Condition.h> #include <utils/Mutex.h> +#include <utils/StrongPointer.h> #include <utils/Vector.h> #include "RenderTask.h" @@ -36,9 +37,16 @@ namespace renderthread { class CanvasContext; class RenderThread; -struct SetDisplayListData { - RenderNode* targetNode; - DisplayListData* newData; +class SetDisplayListData { +public: + // This ctor exists for Vector's usage + SetDisplayListData(); + SetDisplayListData(RenderNode* node, DisplayListData* newData); + ~SetDisplayListData(); + void apply() const; +private: + sp<RenderNode> mTargetNode; + DisplayListData* mNewData; }; /* @@ -61,10 +69,18 @@ public: void setRenderNode(RenderNode* renderNode); void setDirty(int left, int top, int right, int bottom); void drawFrame(RenderThread* renderThread); + void flushStateChanges(RenderThread* renderThread); virtual void run(); private: + enum TaskMode { + MODE_INVALID, + MODE_FULL, + MODE_STATE_ONLY, + }; + + void postAndWait(RenderThread* renderThread, TaskMode mode); void syncFrameState(); void unblockUiThread(); static void drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty); @@ -81,7 +97,8 @@ private: /********************************************* * Single frame data *********************************************/ - RenderNode* mRenderNode; + TaskMode mTaskMode; + sp<RenderNode> mRenderNode; Rect mDirty; Vector<SetDisplayListData> mDisplayListDataUpdates; diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index cd711b0..43182d5 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -75,6 +75,9 @@ CREATE_BRIDGE1(destroyContext, CanvasContext* context) { void RenderProxy::destroyContext() { if (mContext) { + // Flush any pending changes to ensure all garbage is destroyed + mDrawFrameTask.flushStateChanges(&mRenderThread); + SETUP_TASK(destroyContext); args->context = mContext; mContext = 0; @@ -138,6 +141,10 @@ CREATE_BRIDGE1(destroyCanvas, CanvasContext* context) { } void RenderProxy::destroyCanvas() { + // If the canvas is being destroyed we won't be drawing again anytime soon + // So flush any pending state changes to allow for resource cleanup. + mDrawFrameTask.flushStateChanges(&mRenderThread); + SETUP_TASK(destroyCanvas); args->context = mContext; post(task); diff --git a/libs/hwui/utils/VirtualLightRefBase.h b/libs/hwui/utils/VirtualLightRefBase.h new file mode 100644 index 0000000..b545aab --- /dev/null +++ b/libs/hwui/utils/VirtualLightRefBase.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef VIRTUALLIGHTREFBASE_H +#define VIRTUALLIGHTREFBASE_H + +#include <utils/RefBase.h> + +namespace android { +namespace uirenderer { + +// This is a wrapper around LightRefBase that simply enforces a virtual +// destructor to eliminate the template requirement of LightRefBase +class VirtualLightRefBase : public LightRefBase<VirtualLightRefBase> { +public: + virtual ~VirtualLightRefBase() {} +}; + +} /* namespace uirenderer */ +} /* namespace android */ + +#endif /* VIRTUALLIGHTREFBASE_H */ |