summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2014-10-31 14:49:06 -0700
committerJohn Reck <jreck@google.com>2014-10-31 15:30:10 -0700
commit0e89e2b7bcb2c035e8cee77f93120e7c5617f8d2 (patch)
tree8fcd1f768f08fbeb2cd13425a2bf15b7670428f2
parent141823ec6313d9545b8354ea1e3e017a1da3cfa8 (diff)
downloadframeworks_base-0e89e2b7bcb2c035e8cee77f93120e7c5617f8d2.zip
frameworks_base-0e89e2b7bcb2c035e8cee77f93120e7c5617f8d2.tar.gz
frameworks_base-0e89e2b7bcb2c035e8cee77f93120e7c5617f8d2.tar.bz2
Layer changes
Bug: 17208461 * Switch Layer to be VirtualLightRefBase instead of Caches' side-channel ref-counting * Include active layers in gfxinfo dump * Run gfxinfo dump on the correct thread * Dump gfxinfo on Layer creation failure Change-Id: I28d195699e2334518e215ab28c7a17355aee9678
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp3
-rw-r--r--libs/hwui/Caches.cpp42
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp21
-rw-r--r--libs/hwui/DisplayList.cpp5
-rw-r--r--libs/hwui/DisplayList.h7
-rw-r--r--libs/hwui/DisplayListRenderer.cpp24
-rw-r--r--libs/hwui/DisplayListRenderer.h6
-rw-r--r--libs/hwui/Layer.cpp19
-rw-r--r--libs/hwui/Layer.h8
-rw-r--r--libs/hwui/LayerCache.cpp2
-rw-r--r--libs/hwui/LayerRenderer.cpp14
-rw-r--r--libs/hwui/LayerRenderer.h1
-rwxr-xr-xlibs/hwui/OpenGLRenderer.cpp25
-rwxr-xr-xlibs/hwui/OpenGLRenderer.h3
-rw-r--r--libs/hwui/RenderNode.cpp7
-rw-r--r--libs/hwui/RenderNode.h2
-rw-r--r--libs/hwui/RenderState.cpp37
-rw-r--r--libs/hwui/RenderState.h19
-rw-r--r--libs/hwui/ResourceCache.cpp23
-rw-r--r--libs/hwui/ResourceCache.h7
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp2
-rw-r--r--libs/hwui/renderthread/EglManager.cpp19
-rw-r--r--libs/hwui/renderthread/EglManager.h7
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp42
-rw-r--r--libs/hwui/renderthread/RenderProxy.h4
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp2
26 files changed, 163 insertions, 188 deletions
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 2e2b23f..9bdc6b5 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -43,6 +43,7 @@
#include <RenderNode.h>
#include <CanvasProperty.h>
#include <Paint.h>
+#include <renderthread/RenderProxy.h>
#include "MinikinUtils.h"
@@ -861,7 +862,7 @@ static void
android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
#ifdef USE_OPENGL_RENDERER
int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
- android::uirenderer::RenderNode::outputLogBuffer(fd);
+ android::uirenderer::renderthread::RenderProxy::outputLogBuffer(fd);
#endif // USE_OPENGL_RENDERER
}
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f0bf7b2..ad50894 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -265,14 +265,27 @@ void Caches::dumpMemoryUsage() {
}
void Caches::dumpMemoryUsage(String8 &log) {
+ uint32_t total = 0;
log.appendFormat("Current memory usage / total memory usage (bytes):\n");
log.appendFormat(" TextureCache %8d / %8d\n",
textureCache.getSize(), textureCache.getMaxSize());
log.appendFormat(" LayerCache %8d / %8d (numLayers = %zu)\n",
layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount());
- log.appendFormat(" Garbage layers %8zu\n", mLayerGarbage.size());
- log.appendFormat(" Active layers %8zu\n",
- mRenderState ? mRenderState->mActiveLayers.size() : 0);
+ if (mRenderState) {
+ int memused = 0;
+ for (std::set<const Layer*>::iterator it = mRenderState->mActiveLayers.begin();
+ it != mRenderState->mActiveLayers.end(); it++) {
+ const Layer* layer = *it;
+ log.appendFormat(" Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n",
+ layer->getWidth(), layer->getHeight(),
+ layer->isTextureLayer(), layer->getTexture(),
+ layer->getFbo(), layer->getStrongCount());
+ memused = layer->getWidth() * layer->getHeight() * 4;
+ }
+ log.appendFormat(" Layers total %8d (numLayers = %zu)\n",
+ memused, mRenderState->mActiveLayers.size());
+ total += memused;
+ }
log.appendFormat(" RenderBufferCache %8d / %8d\n",
renderBufferCache.getSize(), renderBufferCache.getMaxSize());
log.appendFormat(" GradientCache %8d / %8d\n",
@@ -297,9 +310,7 @@ void Caches::dumpMemoryUsage(String8 &log) {
log.appendFormat(" FboCache %8d / %8d\n",
fboCache.getSize(), fboCache.getMaxSize());
- uint32_t total = 0;
total += textureCache.getSize();
- total += layerCache.getSize();
total += renderBufferCache.getSize();
total += gradientCache.getSize();
total += pathCache.getSize();
@@ -323,27 +334,6 @@ void Caches::clearGarbage() {
textureCache.clearGarbage();
pathCache.clearGarbage();
patchCache.clearGarbage();
-
- Vector<Layer*> layers;
-
- { // scope for the lock
- Mutex::Autolock _l(mGarbageLock);
- layers = mLayerGarbage;
- mLayerGarbage.clear();
- }
-
- size_t count = layers.size();
- for (size_t i = 0; i < count; i++) {
- Layer* layer = layers.itemAt(i);
- delete layer;
- }
- layers.clear();
-}
-
-void Caches::deleteLayerDeferred(Layer* layer) {
- Mutex::Autolock _l(mGarbageLock);
- layer->state = Layer::kState_InGarbageList;
- mLayerGarbage.push(layer);
}
void Caches::flush(FlushMode mode) {
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index a6d7e78..d02455c 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -24,25 +24,6 @@
namespace android {
namespace uirenderer {
-class DeleteLayerTask : public renderthread::RenderTask {
-public:
- DeleteLayerTask(renderthread::EglManager& eglManager, Layer* layer)
- : mEglManager(eglManager)
- , mLayer(layer)
- {}
-
- virtual void run() {
- mEglManager.requireGlContext();
- LayerRenderer::destroyLayer(mLayer);
- mLayer = 0;
- delete this;
- }
-
-private:
- renderthread::EglManager& mEglManager;
- Layer* mLayer;
-};
-
DeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, Layer* layer)
: mSurfaceTexture(0)
, mTransform(0)
@@ -62,7 +43,7 @@ DeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, L
DeferredLayerUpdater::~DeferredLayerUpdater() {
SkSafeUnref(mColorFilter);
setTransform(0);
- mRenderThread.queue(new DeleteLayerTask(mRenderThread.eglManager(), mLayer));
+ mLayer->postDecStrong();
mLayer = 0;
}
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index d8932ce..4a927cf 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -61,10 +61,6 @@ void DisplayListData::cleanupResources() {
caches.resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i));
}
- for (size_t i = 0; i < layers.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(layers.itemAt(i));
- }
-
caches.resourceCache.unlock();
for (size_t i = 0; i < paints.size(); i++) {
@@ -86,7 +82,6 @@ void DisplayListData::cleanupResources() {
paints.clear();
regions.clear();
paths.clear();
- layers.clear();
}
size_t DisplayListData::addChild(DrawRenderNodeOp* op) {
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index dea109c..cb8a8d1 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -147,7 +147,6 @@ public:
Vector<const SkPath*> paths;
SortedVector<const SkPath*> sourcePaths;
Vector<const SkRegion*> regions;
- Vector<Layer*> layers;
Vector<Functor*> functors;
const Vector<Chunk>& getChunks() const {
@@ -157,11 +156,7 @@ public:
size_t addChild(DrawRenderNodeOp* childOp);
const Vector<DrawRenderNodeOp*>& children() { return mChildren; }
- void refProperty(CanvasPropertyPrimitive* prop) {
- mReferenceHolders.push(prop);
- }
-
- void refProperty(CanvasPropertyPaint* prop) {
+ void ref(VirtualLightRefBase* prop) {
mReferenceHolders.push(prop);
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 1f70921..c17dd09 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -189,7 +189,7 @@ status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty
}
status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y) {
- layer = refLayer(layer);
+ mDisplayListData->ref(layer);
addDrawOp(new (alloc()) DrawLayerOp(layer, x, y));
return DrawGlInfo::kStatusDone;
}
@@ -280,13 +280,13 @@ status_t DisplayListRenderer::drawRoundRect(
CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
CanvasPropertyPaint* paint) {
- mDisplayListData->refProperty(left);
- mDisplayListData->refProperty(top);
- mDisplayListData->refProperty(right);
- mDisplayListData->refProperty(bottom);
- mDisplayListData->refProperty(rx);
- mDisplayListData->refProperty(ry);
- mDisplayListData->refProperty(paint);
+ mDisplayListData->ref(left);
+ mDisplayListData->ref(top);
+ mDisplayListData->ref(right);
+ mDisplayListData->ref(bottom);
+ mDisplayListData->ref(rx);
+ mDisplayListData->ref(ry);
+ mDisplayListData->ref(paint);
addDrawOp(new (alloc()) DrawRoundRectPropsOp(&left->value, &top->value,
&right->value, &bottom->value, &rx->value, &ry->value, &paint->value));
return DrawGlInfo::kStatusDone;
@@ -300,10 +300,10 @@ status_t DisplayListRenderer::drawCircle(float x, float y, float radius, const S
status_t DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
- mDisplayListData->refProperty(x);
- mDisplayListData->refProperty(y);
- mDisplayListData->refProperty(radius);
- mDisplayListData->refProperty(paint);
+ mDisplayListData->ref(x);
+ mDisplayListData->ref(y);
+ mDisplayListData->ref(radius);
+ mDisplayListData->ref(paint);
addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value,
&radius->value, &paint->value));
return DrawGlInfo::kStatusDone;
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 3a3fc3a..901e8f0 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -267,12 +267,6 @@ private:
return regionCopy;
}
- inline Layer* refLayer(Layer* layer) {
- mDisplayListData->layers.add(layer);
- mCaches.resourceCache.incrementRefcount(layer);
- return layer;
- }
-
inline const SkBitmap* refBitmap(const SkBitmap* bitmap) {
// Note that this assumes the bitmap is immutable. There are cases this won't handle
// correctly, such as creating the bitmap from scratch, drawing with it, changing its
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index b5089aa..b95636b 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -35,6 +35,9 @@ Layer::Layer(Type layerType, RenderState& renderState, const uint32_t layerWidth
, renderState(renderState)
, texture(caches)
, type(layerType) {
+ // TODO: This is a violation of Android's typical ref counting, but it
+ // preserves the old inc/dec ref locations. This should be changed...
+ incStrong(0);
mesh = NULL;
meshElementCount = 0;
cacheable = true;
@@ -53,20 +56,14 @@ Layer::Layer(Type layerType, RenderState& renderState, const uint32_t layerWidth
forceFilter = false;
deferredList = NULL;
convexMask = NULL;
- caches.resourceCache.incrementRefcount(this);
rendererLightPosDirty = true;
wasBuildLayered = false;
- if (!isTextureLayer()) {
- // track only non-texture layer lifecycles in renderstate,
- // because texture layers are destroyed via finalizer
- renderState.registerLayer(this);
- }
+ renderState.registerLayer(this);
}
Layer::~Layer() {
- if (!isTextureLayer()) {
- renderState.unregisterLayer(this);
- }
+ renderState.requireGLContext();
+ renderState.unregisterLayer(this);
SkSafeUnref(colorFilter);
removeFbo();
deleteTexture();
@@ -292,5 +289,9 @@ void Layer::render(const OpenGLRenderer& rootRenderer) {
renderNode = NULL;
}
+void Layer::postDecStrong() {
+ renderState.postDecStrong(this);
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index a8e1c26..64d1d12 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -52,7 +52,7 @@ class DeferStateStruct;
/**
* A layer has dimensions and is backed by an OpenGL texture or FBO.
*/
-class Layer {
+class Layer : public VirtualLightRefBase {
public:
enum Type {
kType_Texture,
@@ -280,6 +280,12 @@ public:
void render(const OpenGLRenderer& rootRenderer);
/**
+ * Posts a decStrong call to the appropriate thread.
+ * Thread-safe.
+ */
+ void postDecStrong();
+
+ /**
* Bounds of the layer.
*/
Rect layer;
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 833f64b..3033dc6 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -84,7 +84,7 @@ void LayerCache::deleteLayer(Layer* layer) {
layer->getFbo());
mSize -= layer->getWidth() * layer->getHeight() * 4;
layer->state = Layer::kState_DeletedFromCache;
- Caches::getInstance().resourceCache.decrementRefcount(layer);
+ layer->decStrong(0);
}
}
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 103c843..394c647 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -212,7 +212,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width
// Creating a new layer always increment its refcount by 1, this allows
// us to destroy the layer object if one was created for us
- Caches::getInstance().resourceCache.decrementRefcount(layer);
+ layer->decStrong(0);
return NULL;
}
@@ -240,7 +240,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width
if (glGetError() != GL_NO_ERROR) {
ALOGE("Could not allocate texture for layer (fbo=%d %dx%d)", fbo, width, height);
renderState.bindFramebuffer(previousFbo);
- caches.resourceCache.decrementRefcount(layer);
+ layer->decStrong(0);
return NULL;
}
}
@@ -316,7 +316,7 @@ void LayerRenderer::destroyLayer(Layer* layer) {
if (!Caches::getInstance().layerCache.put(layer)) {
LAYER_RENDERER_LOGD(" Destroyed!");
- Caches::getInstance().resourceCache.decrementRefcount(layer);
+ layer->decStrong(0);
} else {
LAYER_RENDERER_LOGD(" Cached!");
#if DEBUG_LAYER_RENDERER
@@ -328,14 +328,6 @@ void LayerRenderer::destroyLayer(Layer* layer) {
}
}
-void LayerRenderer::destroyLayerDeferred(Layer* layer) {
- if (layer) {
- LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->getFbo());
-
- Caches::getInstance().deleteLayerDeferred(layer);
- }
-}
-
void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) {
#ifdef GL_EXT_discard_framebuffer
if (!layer) return;
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index bf7828c..4d8620b 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -60,7 +60,6 @@ public:
static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform);
static void destroyLayer(Layer* layer);
- ANDROID_API static void destroyLayerDeferred(Layer* layer);
static bool copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap);
static void flushLayer(RenderState& renderState, Layer* layer);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 19fc9a3..d570b0d 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -509,11 +509,8 @@ void OpenGLRenderer::updateLayers() {
// Note: it is very important to update the layers in order
for (int i = 0; i < count; i++) {
- Layer* layer = mLayerUpdates.itemAt(i);
+ Layer* layer = mLayerUpdates.itemAt(i).get();
updateLayer(layer, false);
- if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
- mCaches.resourceCache.decrementRefcount(layer);
- }
}
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
@@ -532,7 +529,7 @@ void OpenGLRenderer::flushLayers() {
// Note: it is very important to update the layers in order
for (int i = 0; i < count; i++) {
- Layer* layer = mLayerUpdates.itemAt(i);
+ Layer* layer = mLayerUpdates.itemAt(i).get();
sprintf(layerName, "Layer #%d", i);
startMark(layerName);
@@ -542,8 +539,6 @@ void OpenGLRenderer::flushLayers() {
ATRACE_END();
endMark();
-
- mCaches.resourceCache.decrementRefcount(layer);
}
mLayerUpdates.clear();
@@ -565,7 +560,6 @@ void OpenGLRenderer::pushLayerUpdate(Layer* layer) {
}
}
mLayerUpdates.push_back(layer);
- mCaches.resourceCache.incrementRefcount(layer);
}
}
@@ -574,25 +568,12 @@ void OpenGLRenderer::cancelLayerUpdate(Layer* layer) {
for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
if (mLayerUpdates.itemAt(i) == layer) {
mLayerUpdates.removeAt(i);
- mCaches.resourceCache.decrementRefcount(layer);
break;
}
}
}
}
-void OpenGLRenderer::clearLayerUpdates() {
- size_t count = mLayerUpdates.size();
- if (count > 0) {
- mCaches.resourceCache.lock();
- for (size_t i = 0; i < count; i++) {
- mCaches.resourceCache.decrementRefcountLocked(mLayerUpdates.itemAt(i));
- }
- mCaches.resourceCache.unlock();
- mLayerUpdates.clear();
- }
-}
-
void OpenGLRenderer::flushLayerUpdates() {
ATRACE_CALL();
syncState();
@@ -956,7 +937,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto
layer->setConvexMask(NULL);
if (!mCaches.layerCache.put(layer)) {
LAYER_LOGD("Deleting layer");
- Caches::getInstance().resourceCache.decrementRefcount(layer);
+ layer->decStrong(0);
}
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index c2c0b0e..e1c3d10 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -140,7 +140,6 @@ public:
void pushLayerUpdate(Layer* layer);
void cancelLayerUpdate(Layer* layer);
- void clearLayerUpdates();
void flushLayerUpdates();
void markLayersAsBuildLayers();
@@ -982,7 +981,7 @@ private:
// List of rectangles to clear after saveLayer() is invoked
Vector<Rect*> mLayers;
// List of layers to update at the beginning of a frame
- Vector<Layer*> mLayerUpdates;
+ Vector< sp<Layer> > mLayerUpdates;
// The following fields are used to setup drawing
// Used to describe the shaders to generate
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 40cd13e..c9ed9a7 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -87,7 +87,11 @@ RenderNode::RenderNode()
RenderNode::~RenderNode() {
deleteDisplayListData();
delete mStagingDisplayListData;
- LayerRenderer::destroyLayerDeferred(mLayer);
+ if (mLayer) {
+ ALOGW("Memory Warning: Layer %p missed its detachment, held on to for far too long!", mLayer);
+ mLayer->postDecStrong();
+ mLayer = 0;
+ }
}
void RenderNode::setStagingDisplayList(DisplayListData* data) {
@@ -201,6 +205,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
info.damageAccumulator->peekAtDirty(&dirty);
if (!mLayer) {
+ Caches::getInstance().dumpMemoryUsage();
if (info.errorHandler) {
std::string msg = "Unable to create layer for ";
msg += getName();
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index f329283..2ce7cb7 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -101,7 +101,7 @@ public:
kReplayFlag_ClipChildren = 0x1
};
- ANDROID_API static void outputLogBuffer(int fd);
+ static void outputLogBuffer(int fd);
void debugDumpLayers(const char* prefix);
ANDROID_API void setStagingDisplayList(DisplayListData* newData);
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp
index 86bd7dd..a8cf26f 100644
--- a/libs/hwui/RenderState.cpp
+++ b/libs/hwui/RenderState.cpp
@@ -16,15 +16,18 @@
#include "RenderState.h"
#include "renderthread/CanvasContext.h"
+#include "renderthread/EglManager.h"
namespace android {
namespace uirenderer {
-RenderState::RenderState()
- : mCaches(NULL)
+RenderState::RenderState(renderthread::RenderThread& thread)
+ : mRenderThread(thread)
+ , mCaches(NULL)
, mViewportWidth(0)
, mViewportHeight(0)
, mFramebuffer(0) {
+ mThreadId = pthread_self();
}
RenderState::~RenderState() {
@@ -39,7 +42,6 @@ void RenderState::onGLContextCreated() {
void RenderState::onGLContextDestroyed() {
/*
- AutoMutex _lock(mLayerLock);
size_t size = mActiveLayers.size();
if (CC_UNLIKELY(size != 0)) {
ALOGE("Crashing, have %d contexts and %d layers at context destruction. isempty %d",
@@ -146,5 +148,34 @@ void RenderState::debugOverdraw(bool enable, bool clear) {
}
}
+void RenderState::requireGLContext() {
+ assertOnGLThread();
+ mRenderThread.eglManager().requireGlContext();
+}
+
+void RenderState::assertOnGLThread() {
+ pthread_t curr = pthread_self();
+ LOG_ALWAYS_FATAL_IF(!pthread_equal(mThreadId, curr), "Wrong thread!");
+}
+
+
+class DecStrongTask : public renderthread::RenderTask {
+public:
+ DecStrongTask(VirtualLightRefBase* object) : mObject(object) {}
+
+ virtual void run() {
+ mObject->decStrong(0);
+ mObject = 0;
+ delete this;
+ }
+
+private:
+ VirtualLightRefBase* mObject;
+};
+
+void RenderState::postDecStrong(VirtualLightRefBase* object) {
+ mRenderThread.queue(new DecStrongTask(object));
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h
index cbe7cfc..afeef95 100644
--- a/libs/hwui/RenderState.h
+++ b/libs/hwui/RenderState.h
@@ -53,16 +53,10 @@ public:
void debugOverdraw(bool enable, bool clear);
void registerLayer(const Layer* layer) {
- /*
- AutoMutex _lock(mLayerLock);
mActiveLayers.insert(layer);
- */
}
void unregisterLayer(const Layer* layer) {
- /*
- AutoMutex _lock(mLayerLock);
mActiveLayers.erase(layer);
- */
}
void registerCanvasContext(renderthread::CanvasContext* context) {
@@ -73,16 +67,24 @@ public:
mRegisteredContexts.erase(context);
}
+ void requireGLContext();
+
+ // TODO: This system is a little clunky feeling, this could use some
+ // more thinking...
+ void postDecStrong(VirtualLightRefBase* object);
+
private:
friend class renderthread::RenderThread;
friend class Caches;
void interruptForFunctorInvoke();
void resumeFromFunctorInvoke();
+ void assertOnGLThread();
- RenderState();
+ RenderState(renderthread::RenderThread& thread);
~RenderState();
+ renderthread::RenderThread& mRenderThread;
Caches* mCaches;
std::set<const Layer*> mActiveLayers;
std::set<renderthread::CanvasContext*> mRegisteredContexts;
@@ -90,7 +92,8 @@ private:
GLsizei mViewportWidth;
GLsizei mViewportHeight;
GLuint mFramebuffer;
- Mutex mLayerLock;
+
+ pthread_t mThreadId;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 8b553d1..329d92f 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -75,10 +75,6 @@ void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) {
incrementRefcount((void*) patchResource, kNinePatch);
}
-void ResourceCache::incrementRefcount(Layer* layerResource) {
- incrementRefcount((void*) layerResource, kLayer);
-}
-
void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) {
ssize_t index = mCache->indexOfKey(resource);
ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
@@ -103,10 +99,6 @@ void ResourceCache::incrementRefcountLocked(const Res_png_9patch* patchResource)
incrementRefcountLocked((void*) patchResource, kNinePatch);
}
-void ResourceCache::incrementRefcountLocked(Layer* layerResource) {
- incrementRefcountLocked((void*) layerResource, kLayer);
-}
-
void ResourceCache::decrementRefcount(void* resource) {
Mutex::Autolock _l(mLock);
decrementRefcountLocked(resource);
@@ -126,10 +118,6 @@ void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
decrementRefcount((void*) patchResource);
}
-void ResourceCache::decrementRefcount(Layer* layerResource) {
- decrementRefcount((void*) layerResource);
-}
-
void ResourceCache::decrementRefcountLocked(void* resource) {
ssize_t index = mCache->indexOfKey(resource);
ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
@@ -157,10 +145,6 @@ void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource)
decrementRefcountLocked((void*) patchResource);
}
-void ResourceCache::decrementRefcountLocked(Layer* layerResource) {
- decrementRefcountLocked((void*) layerResource);
-}
-
void ResourceCache::destructor(SkPath* resource) {
Mutex::Autolock _l(mLock);
destructorLocked(resource);
@@ -274,7 +258,7 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource
if (ref->recycled && ref->resourceType == kBitmap) {
((SkBitmap*) resource)->setPixels(NULL, NULL);
}
- if (ref->destroyed || ref->resourceType == kLayer) {
+ if (ref->destroyed) {
switch (ref->resourceType) {
case kBitmap: {
SkBitmap* bitmap = (SkBitmap*) resource;
@@ -305,11 +289,6 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource
}
}
break;
- case kLayer: {
- Layer* layer = (Layer*) resource;
- Caches::getInstance().deleteLayerDeferred(layer);
- }
- break;
}
}
mCache->removeItem(resource);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 3864d4b..8539d12 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -36,8 +36,7 @@ namespace uirenderer {
enum ResourceType {
kBitmap,
kNinePatch,
- kPath,
- kLayer
+ kPath
};
class ResourceReference {
@@ -69,22 +68,18 @@ public:
void incrementRefcount(const SkPath* resource);
void incrementRefcount(const SkBitmap* resource);
void incrementRefcount(const Res_png_9patch* resource);
- void incrementRefcount(Layer* resource);
void incrementRefcountLocked(const SkPath* resource);
void incrementRefcountLocked(const SkBitmap* resource);
void incrementRefcountLocked(const Res_png_9patch* resource);
- void incrementRefcountLocked(Layer* resource);
void decrementRefcount(const SkBitmap* resource);
void decrementRefcount(const SkPath* resource);
void decrementRefcount(const Res_png_9patch* resource);
- void decrementRefcount(Layer* resource);
void decrementRefcountLocked(const SkBitmap* resource);
void decrementRefcountLocked(const SkPath* resource);
void decrementRefcountLocked(const Res_png_9patch* resource);
- void decrementRefcountLocked(Layer* resource);
void destructor(SkPath* resource);
void destructor(const SkBitmap* resource);
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 9d2ae8b..b499dd0 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -236,6 +236,8 @@ void CanvasContext::draw() {
if (status & DrawGlInfo::kStatusDrew) {
swapBuffers();
+ } else {
+ mEglManager.cancelFrame();
}
profiler().finishFrame();
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index e37aafc..9bd6f41 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -73,7 +73,8 @@ EglManager::EglManager(RenderThread& thread)
, mAllowPreserveBuffer(load_dirty_regions_property())
, mCurrentSurface(EGL_NO_SURFACE)
, mAtlasMap(NULL)
- , mAtlasMapSize(0) {
+ , mAtlasMapSize(0)
+ , mInFrame(false) {
mCanSetPreserveBuffer = mAllowPreserveBuffer;
ALOGD("Use EGL_SWAP_BEHAVIOR_PRESERVED: %s", mAllowPreserveBuffer ? "true" : "false");
}
@@ -105,10 +106,12 @@ bool EglManager::hasEglContext() {
void EglManager::requireGlContext() {
LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, "No EGL context");
- // We can't be certain about the state of the current surface (whether
- // or not it is destroyed, for example), so err on the side of using
- // the pbuffer surface which we fully control
- usePBufferSurface();
+ if (!mInFrame) {
+ // We can't be certain about the state of the current surface (whether
+ // or not it is destroyed, for example), so err on the side of using
+ // the pbuffer surface which we fully control
+ usePBufferSurface();
+ }
}
void EglManager::loadConfig() {
@@ -251,9 +254,11 @@ void EglManager::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) {
eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height);
}
eglBeginFrame(mEglDisplay, surface);
+ mInFrame = true;
}
bool EglManager::swapBuffers(EGLSurface surface) {
+ mInFrame = false;
eglSwapBuffers(mEglDisplay, surface);
EGLint err = eglGetError();
if (CC_LIKELY(err == EGL_SUCCESS)) {
@@ -272,6 +277,10 @@ bool EglManager::swapBuffers(EGLSurface surface) {
return false;
}
+void EglManager::cancelFrame() {
+ mInFrame = false;
+}
+
bool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) {
if (CC_UNLIKELY(!mAllowPreserveBuffer)) return false;
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index ae03ea1..e12db3a 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -48,6 +48,7 @@ public:
bool makeCurrent(EGLSurface surface);
void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
bool swapBuffers(EGLSurface surface);
+ void cancelFrame();
// Returns true iff the surface is now preserving buffers.
bool setPreserveBuffer(EGLSurface surface, bool preserve);
@@ -80,6 +81,12 @@ private:
sp<GraphicBuffer> mAtlasBuffer;
int64_t* mAtlasMap;
size_t mAtlasMapSize;
+
+ // Whether or not we are in the middle of drawing a frame. This is used
+ // to avoid switching surfaces mid-frame if requireGlContext() is called
+ // TODO: Need to be better about surface/context management so that this isn't
+ // necessary
+ bool mInFrame;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 8f99b4e..5d55ea6 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -235,12 +235,7 @@ void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
// waitForCompletion = true is expected to be fairly rare and only
// happen in destruction. Thus it should be fine to temporarily
// create a Mutex
- Mutex mutex;
- Condition condition;
- SignalingRenderTask syncTask(task, &mutex, &condition);
- AutoMutex _lock(mutex);
- thread.queue(&syncTask);
- condition.wait(mutex);
+ staticPostAndWait(task);
} else {
thread.queue(task);
}
@@ -258,17 +253,6 @@ void RenderProxy::runWithGlContext(RenderTask* gltask) {
postAndWait(task);
}
-CREATE_BRIDGE1(destroyLayer, Layer* layer) {
- LayerRenderer::destroyLayer(args->layer);
- return NULL;
-}
-
-void RenderProxy::enqueueDestroyLayer(Layer* layer) {
- SETUP_TASK(destroyLayer);
- args->layer = layer;
- RenderThread::getInstance().queue(task);
-}
-
CREATE_BRIDGE2(createTextureLayer, RenderThread* thread, CanvasContext* context) {
Layer* layer = args->context->createTextureLayer();
if (!layer) return 0;
@@ -400,6 +384,17 @@ void RenderProxy::dumpProfileInfo(int fd) {
postAndWait(task);
}
+CREATE_BRIDGE1(outputLogBuffer, int fd) {
+ RenderNode::outputLogBuffer(args->fd);
+ return NULL;
+}
+
+void RenderProxy::outputLogBuffer(int fd) {
+ SETUP_TASK(outputLogBuffer);
+ args->fd = fd;
+ staticPostAndWait(task);
+}
+
CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) {
CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size);
args->buffer->decStrong(0);
@@ -430,6 +425,19 @@ void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
return retval;
}
+void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) {
+ RenderThread& thread = RenderThread::getInstance();
+ void* retval;
+ task->setReturnPtr(&retval);
+ Mutex mutex;
+ Condition condition;
+ SignalingRenderTask syncTask(task, &mutex, &condition);
+ AutoMutex _lock(mutex);
+ thread.queue(&syncTask);
+ condition.wait(mutex);
+ return retval;
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index dddf0c7..4989b14 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -81,7 +81,6 @@ public:
ANDROID_API void runWithGlContext(RenderTask* task);
- static void enqueueDestroyLayer(Layer* layer);
ANDROID_API DeferredLayerUpdater* createTextureLayer();
ANDROID_API void buildLayer(RenderNode* node);
ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
@@ -97,6 +96,7 @@ public:
ANDROID_API void notifyFramePending();
ANDROID_API void dumpProfileInfo(int fd);
+ ANDROID_API static void outputLogBuffer(int fd);
ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size);
@@ -114,6 +114,8 @@ private:
void post(RenderTask* task);
void* postAndWait(MethodInvokeRenderTask* task);
+ static void* staticPostAndWait(MethodInvokeRenderTask* task);
+
// Friend class to help with bridging
friend class RenderProxyBridge;
};
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 403e164..f887103 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -168,7 +168,7 @@ void RenderThread::initializeDisplayEventReceiver() {
void RenderThread::initThreadLocals() {
initializeDisplayEventReceiver();
mEglManager = new EglManager(*this);
- mRenderState = new RenderState();
+ mRenderState = new RenderState(*this);
}
int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {