Loading libs/hwui/RenderNode.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include "LayerRenderer.h" #include "OpenGLRenderer.h" #include "utils/MathUtils.h" #include "renderthread/CanvasContext.h" namespace android { namespace uirenderer { Loading Loading @@ -208,6 +209,13 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { if (info.renderer && mLayer->deferredUpdateScheduled) { info.renderer->pushLayerUpdate(mLayer); } if (CC_UNLIKELY(info.canvasContext)) { // If canvasContext is not null that means there are prefetched layers // that need to be accounted for. That might be us, so tell CanvasContext // that this layer is in the tree and should not be destroyed. info.canvasContext->markLayerInUse(this); } } void RenderNode::prepareTreeImpl(TreeInfo& info) { Loading libs/hwui/TreeInfo.h +8 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,10 @@ namespace android { namespace uirenderer { namespace renderthread { class CanvasContext; } class OpenGLRenderer; class RenderState; Loading Loading @@ -59,6 +63,7 @@ public: , renderState(renderState) , renderer(NULL) , errorHandler(NULL) , canvasContext(NULL) {} explicit TreeInfo(TraversalMode mode, const TreeInfo& clone) Loading @@ -69,6 +74,7 @@ public: , renderState(clone.renderState) , renderer(clone.renderer) , errorHandler(clone.errorHandler) , canvasContext(clone.canvasContext) {} const TraversalMode mode; Loading @@ -89,6 +95,8 @@ public: // layer updates or similar. May be NULL. OpenGLRenderer* renderer; ErrorHandler* errorHandler; // TODO: Remove this? May be NULL renderthread::CanvasContext* canvasContext; struct Out { Out() Loading libs/hwui/renderthread/CanvasContext.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "CanvasContext.h" #include <algorithm> #include <private/hwui/DrawGlInfo.h> #include <strings.h> Loading Loading @@ -53,6 +54,7 @@ CanvasContext::~CanvasContext() { destroyCanvasAndSurface(); mRenderThread.removeFrameCallback(this); delete mAnimationContext; freePrefetechedLayers(); } void CanvasContext::destroyCanvasAndSurface() { Loading Loading @@ -142,10 +144,17 @@ void CanvasContext::prepareTree(TreeInfo& info) { info.damageAccumulator = &mDamageAccumulator; info.renderer = mCanvas; if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) { info.canvasContext = this; } mAnimationContext->startFrame(); mRootRenderNode->prepareTree(info); mAnimationContext->runRemainingAnimations(info); if (info.canvasContext) { freePrefetechedLayers(); } int runningBehind = 0; // TODO: This query is moderately expensive, investigate adding some sort // of fast-path based off when we last called eglSwapBuffers() as well as Loading Loading @@ -249,6 +258,26 @@ void CanvasContext::invokeFunctor(RenderThread& thread, Functor* functor) { thread.renderState().invokeFunctor(functor, mode, NULL); } void CanvasContext::markLayerInUse(RenderNode* node) { if (mPrefetechedLayers.erase(node)) { node->decStrong(0); } } static void destroyPrefetechedNode(RenderNode* node) { ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...", node->getName()); node->destroyHardwareResources(); node->decStrong(0); } void CanvasContext::freePrefetechedLayers() { if (mPrefetechedLayers.size()) { requireGlContext(); std::for_each(mPrefetechedLayers.begin(), mPrefetechedLayers.end(), destroyPrefetechedNode); mPrefetechedLayers.clear(); } } void CanvasContext::buildLayer(RenderNode* node) { ATRACE_CALL(); if (!mEglManager.hasEglContext() || !mCanvas) { Loading @@ -270,6 +299,9 @@ void CanvasContext::buildLayer(RenderNode* node) { node->setPropertyFieldsDirty(RenderNode::GENERIC); mCanvas->flushLayerUpdates(); node->incStrong(0); mPrefetechedLayers.insert(node); } bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { Loading libs/hwui/renderthread/CanvasContext.h +7 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef CANVASCONTEXT_H_ #define CANVASCONTEXT_H_ #include <set> #include <cutils/compiler.h> #include <EGL/egl.h> #include <SkBitmap.h> Loading Loading @@ -71,6 +73,7 @@ public: void buildLayer(RenderNode* node); bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap); void markLayerInUse(RenderNode* node); void destroyHardwareResources(); static void trimMemory(RenderThread& thread, int level); Loading Loading @@ -99,6 +102,8 @@ private: void requireGlContext(); void freePrefetechedLayers(); RenderThread& mRenderThread; EglManager& mEglManager; sp<ANativeWindow> mNativeWindow; Loading @@ -114,6 +119,8 @@ private: const sp<RenderNode> mRootRenderNode; DrawProfiler mProfiler; std::set<RenderNode*> mPrefetechedLayers; }; } /* namespace renderthread */ Loading libs/hwui/renderthread/EglManager.cpp +0 −2 Original line number Diff line number Diff line Loading @@ -14,8 +14,6 @@ * limitations under the License. */ #define LOG_TAG "EglContext" #include "EglManager.h" #include <cutils/log.h> Loading Loading
libs/hwui/RenderNode.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include "LayerRenderer.h" #include "OpenGLRenderer.h" #include "utils/MathUtils.h" #include "renderthread/CanvasContext.h" namespace android { namespace uirenderer { Loading Loading @@ -208,6 +209,13 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { if (info.renderer && mLayer->deferredUpdateScheduled) { info.renderer->pushLayerUpdate(mLayer); } if (CC_UNLIKELY(info.canvasContext)) { // If canvasContext is not null that means there are prefetched layers // that need to be accounted for. That might be us, so tell CanvasContext // that this layer is in the tree and should not be destroyed. info.canvasContext->markLayerInUse(this); } } void RenderNode::prepareTreeImpl(TreeInfo& info) { Loading
libs/hwui/TreeInfo.h +8 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,10 @@ namespace android { namespace uirenderer { namespace renderthread { class CanvasContext; } class OpenGLRenderer; class RenderState; Loading Loading @@ -59,6 +63,7 @@ public: , renderState(renderState) , renderer(NULL) , errorHandler(NULL) , canvasContext(NULL) {} explicit TreeInfo(TraversalMode mode, const TreeInfo& clone) Loading @@ -69,6 +74,7 @@ public: , renderState(clone.renderState) , renderer(clone.renderer) , errorHandler(clone.errorHandler) , canvasContext(clone.canvasContext) {} const TraversalMode mode; Loading @@ -89,6 +95,8 @@ public: // layer updates or similar. May be NULL. OpenGLRenderer* renderer; ErrorHandler* errorHandler; // TODO: Remove this? May be NULL renderthread::CanvasContext* canvasContext; struct Out { Out() Loading
libs/hwui/renderthread/CanvasContext.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "CanvasContext.h" #include <algorithm> #include <private/hwui/DrawGlInfo.h> #include <strings.h> Loading Loading @@ -53,6 +54,7 @@ CanvasContext::~CanvasContext() { destroyCanvasAndSurface(); mRenderThread.removeFrameCallback(this); delete mAnimationContext; freePrefetechedLayers(); } void CanvasContext::destroyCanvasAndSurface() { Loading Loading @@ -142,10 +144,17 @@ void CanvasContext::prepareTree(TreeInfo& info) { info.damageAccumulator = &mDamageAccumulator; info.renderer = mCanvas; if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) { info.canvasContext = this; } mAnimationContext->startFrame(); mRootRenderNode->prepareTree(info); mAnimationContext->runRemainingAnimations(info); if (info.canvasContext) { freePrefetechedLayers(); } int runningBehind = 0; // TODO: This query is moderately expensive, investigate adding some sort // of fast-path based off when we last called eglSwapBuffers() as well as Loading Loading @@ -249,6 +258,26 @@ void CanvasContext::invokeFunctor(RenderThread& thread, Functor* functor) { thread.renderState().invokeFunctor(functor, mode, NULL); } void CanvasContext::markLayerInUse(RenderNode* node) { if (mPrefetechedLayers.erase(node)) { node->decStrong(0); } } static void destroyPrefetechedNode(RenderNode* node) { ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...", node->getName()); node->destroyHardwareResources(); node->decStrong(0); } void CanvasContext::freePrefetechedLayers() { if (mPrefetechedLayers.size()) { requireGlContext(); std::for_each(mPrefetechedLayers.begin(), mPrefetechedLayers.end(), destroyPrefetechedNode); mPrefetechedLayers.clear(); } } void CanvasContext::buildLayer(RenderNode* node) { ATRACE_CALL(); if (!mEglManager.hasEglContext() || !mCanvas) { Loading @@ -270,6 +299,9 @@ void CanvasContext::buildLayer(RenderNode* node) { node->setPropertyFieldsDirty(RenderNode::GENERIC); mCanvas->flushLayerUpdates(); node->incStrong(0); mPrefetechedLayers.insert(node); } bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { Loading
libs/hwui/renderthread/CanvasContext.h +7 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef CANVASCONTEXT_H_ #define CANVASCONTEXT_H_ #include <set> #include <cutils/compiler.h> #include <EGL/egl.h> #include <SkBitmap.h> Loading Loading @@ -71,6 +73,7 @@ public: void buildLayer(RenderNode* node); bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap); void markLayerInUse(RenderNode* node); void destroyHardwareResources(); static void trimMemory(RenderThread& thread, int level); Loading Loading @@ -99,6 +102,8 @@ private: void requireGlContext(); void freePrefetechedLayers(); RenderThread& mRenderThread; EglManager& mEglManager; sp<ANativeWindow> mNativeWindow; Loading @@ -114,6 +119,8 @@ private: const sp<RenderNode> mRootRenderNode; DrawProfiler mProfiler; std::set<RenderNode*> mPrefetechedLayers; }; } /* namespace renderthread */ Loading
libs/hwui/renderthread/EglManager.cpp +0 −2 Original line number Diff line number Diff line Loading @@ -14,8 +14,6 @@ * limitations under the License. */ #define LOG_TAG "EglContext" #include "EglManager.h" #include <cutils/log.h> Loading