diff options
author | John Reck <jreck@google.com> | 2014-10-31 23:30:57 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-10-31 23:30:57 +0000 |
commit | 9481684560b2815d2706512086bb36467ef6acc0 (patch) | |
tree | e6258e3075f56533df3ec11cf1443a0d1882b17d /libs/hwui | |
parent | bc622ed7c3f9ead17c8aede3ccc10babf0b8e0fa (diff) | |
parent | e05575e9c36850d8cfe49396ac9a1372511b12bf (diff) | |
download | frameworks_base-9481684560b2815d2706512086bb36467ef6acc0.zip frameworks_base-9481684560b2815d2706512086bb36467ef6acc0.tar.gz frameworks_base-9481684560b2815d2706512086bb36467ef6acc0.tar.bz2 |
am e05575e9: am a8d83d63: Merge "Layer changes" into lmp-mr1-dev automerge: a51fba0
* commit 'e05575e9c36850d8cfe49396ac9a1372511b12bf':
Layer changes
Diffstat (limited to 'libs/hwui')
25 files changed, 161 insertions, 187 deletions
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 478a3ec..b313612 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -266,14 +266,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", @@ -298,9 +311,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(); @@ -324,27 +335,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 1777e11..7094cc1 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -148,7 +148,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 { @@ -158,11 +157,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 bcb34b9..1d6d630 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 f407617..3301ce4 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -270,12 +270,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 b264595..2d6a727 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -52,7 +52,7 @@ struct 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 e3c2f2e..39c420f 100755 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -512,11 +512,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)) { @@ -535,7 +532,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); @@ -545,8 +542,6 @@ void OpenGLRenderer::flushLayers() { ATRACE_END(); endMark(); - - mCaches.resourceCache.decrementRefcount(layer); } mLayerUpdates.clear(); @@ -568,7 +563,6 @@ void OpenGLRenderer::pushLayerUpdate(Layer* layer) { } } mLayerUpdates.push_back(layer); - mCaches.resourceCache.incrementRefcount(layer); } } @@ -577,25 +571,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(); @@ -959,7 +940,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 eb41796..5e40ec2 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -133,7 +133,6 @@ public: void pushLayerUpdate(Layer* layer); void cancelLayerUpdate(Layer* layer); - void clearLayerUpdates(); void flushLayerUpdates(); void markLayersAsBuildLayers(); @@ -972,7 +971,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 88b64b5..55fc99e 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -88,7 +88,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) { @@ -202,6 +206,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 93e2bb3..bbe53ff 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -99,7 +99,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 107f9bb..ada1591 100644 --- a/libs/hwui/RenderState.h +++ b/libs/hwui/RenderState.h @@ -56,16 +56,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) { @@ -76,16 +70,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; @@ -93,7 +95,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 c43a056..edd6331 100644 --- a/libs/hwui/ResourceCache.h +++ b/libs/hwui/ResourceCache.h @@ -37,8 +37,7 @@ class Layer; enum ResourceType { kBitmap, kNinePatch, - kPath, - kLayer + kPath }; class ResourceReference { @@ -70,22 +69,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 4f79ba7..e49863d 100644 --- a/libs/hwui/renderthread/EglManager.cpp +++ b/libs/hwui/renderthread/EglManager.cpp @@ -74,7 +74,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"); } @@ -106,10 +107,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() { @@ -252,9 +255,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)) { @@ -273,6 +278,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) { |