summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2014-04-07 22:42:21 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-04-07 22:42:21 +0000
commit96c637e9414600a67c71014274e7757161dcc709 (patch)
tree4840374c35af37bc235dbe885dd03cb4c315fe3a /libs
parent8ea553d03a84e2fc3ded507dd978fca0dee22e77 (diff)
parent087bc0c14bdccf7c258dce0cdef46a69a839b427 (diff)
downloadframeworks_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.cpp16
-rw-r--r--libs/hwui/Caches.h6
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp4
-rw-r--r--libs/hwui/DeferredLayerUpdater.h2
-rw-r--r--libs/hwui/DisplayList.cpp14
-rw-r--r--libs/hwui/DisplayList.h16
-rw-r--r--libs/hwui/DisplayListOp.h2
-rw-r--r--libs/hwui/DisplayListRenderer.cpp2
-rw-r--r--libs/hwui/Layer.cpp11
-rw-r--r--libs/hwui/Layer.h11
-rw-r--r--libs/hwui/OpenGLRenderer.cpp2
-rw-r--r--libs/hwui/RenderNode.cpp35
-rw-r--r--libs/hwui/RenderNode.h4
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp64
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h25
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp7
-rw-r--r--libs/hwui/utils/VirtualLightRefBase.h34
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 */