diff options
-rw-r--r-- | libs/hwui/RenderNode.cpp | 48 | ||||
-rw-r--r-- | libs/hwui/RenderNode.h | 1 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 12 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.h | 17 | ||||
-rw-r--r-- | libs/hwui/renderthread/IRenderPipeline.h | 2 | ||||
-rw-r--r-- | libs/hwui/renderthread/OpenGLPipeline.cpp | 40 | ||||
-rw-r--r-- | libs/hwui/renderthread/OpenGLPipeline.h | 3 |
7 files changed, 80 insertions, 43 deletions
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index dd20a76eb561..8c36ab5d94dd 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -229,19 +229,6 @@ void RenderNode::prepareLayer(TreeInfo& info, uint32_t dirtyMask) { } } -static OffscreenBuffer* createLayer(RenderState& renderState, uint32_t width, uint32_t height) { - return renderState.layerPool().get(renderState, width, height); -} - -static void destroyLayer(OffscreenBuffer* layer) { - RenderState& renderState = layer->renderState; - renderState.layerPool().putOrDelete(layer); -} - -static bool layerMatchesWidthAndHeight(OffscreenBuffer* layer, int width, int height) { - return layer->viewportWidth == (uint32_t) width && layer->viewportHeight == (uint32_t)height; -} - void RenderNode::pushLayerUpdate(TreeInfo& info) { LayerType layerType = properties().effectiveLayerType(); // If we are not a layer OR we cannot be rendered (eg, view was detached) @@ -251,34 +238,15 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { || CC_UNLIKELY(properties().getWidth() == 0) || CC_UNLIKELY(properties().getHeight() == 0)) { if (CC_UNLIKELY(mLayer)) { - destroyLayer(mLayer); - mLayer = nullptr; + renderthread::CanvasContext::destroyLayer(this); } return; } - bool transformUpdateNeeded = false; - if (!mLayer) { - mLayer = createLayer(info.canvasContext.getRenderState(), getWidth(), getHeight()); + if(info.canvasContext.createOrUpdateLayer(this, *info.damageAccumulator)) { damageSelf(info); - transformUpdateNeeded = true; - } else if (!layerMatchesWidthAndHeight(mLayer, getWidth(), getHeight())) { - // TODO: remove now irrelevant, currently enqueued damage (respecting damage ordering) - // Or, ideally, maintain damage between frames on node/layer so ordering is always correct - RenderState& renderState = mLayer->renderState; - if (properties().fitsOnLayer()) { - mLayer = renderState.layerPool().resize(mLayer, getWidth(), getHeight()); - } else { - destroyLayer(mLayer); - mLayer = nullptr; - } - damageSelf(info); - transformUpdateNeeded = true; } - SkRect dirty; - info.damageAccumulator->peekAtDirty(&dirty); - if (!mLayer) { Caches::getInstance().dumpMemoryUsage(); if (info.errorHandler) { @@ -296,13 +264,8 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { return; } - if (transformUpdateNeeded && mLayer) { - // update the transform in window of the layer to reset its origin wrt light source position - Matrix4 windowTransform; - info.damageAccumulator->computeCurrentTransform(&windowTransform); - mLayer->setWindowTransform(windowTransform); - } - + SkRect dirty; + info.damageAccumulator->peekAtDirty(&dirty); info.layerUpdateQueue->enqueueLayerWithDamage(this, dirty); // There might be prefetched layers that need to be accounted for. @@ -451,8 +414,7 @@ void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayL void RenderNode::destroyHardwareResources(TreeObserver* observer, TreeInfo* info) { if (mLayer) { - destroyLayer(mLayer); - mLayer = nullptr; + renderthread::CanvasContext::destroyLayer(this); } if (mDisplayList) { for (auto&& child : mDisplayList->getChildren()) { diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index a0679b1e55f0..da93c131bb5a 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -199,6 +199,7 @@ public: } OffscreenBuffer* getLayer() const { return mLayer; } OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh... + void setLayer(OffscreenBuffer* layer) { mLayer = layer; } // Note: The position callbacks are relying on the listener using // the frameNumber to appropriately batch/synchronize these transactions. diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 43471e50d82b..0f2d55bc209d 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -85,6 +85,18 @@ CanvasContext* CanvasContext::create(RenderThread& thread, return nullptr; } +void CanvasContext::destroyLayer(RenderNode* node) { + auto renderType = Properties::getRenderPipelineType(); + switch (renderType) { + case RenderPipelineType::OpenGL: + OpenGLPipeline::destroyLayer(node); + break; + default: + LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType); + break; + } +} + CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline) diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 7ebe0aeb1107..652cddd968bb 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -68,6 +68,23 @@ public: RenderNode* rootRenderNode, IContextFactory* contextFactory); virtual ~CanvasContext(); + /** + * Update or create a layer specific for the provided RenderNode. The layer + * attached to the node will be specific to the RenderPipeline used by this + * context + * + * @return true if the layer has been created or updated + */ + bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& dmgAccumulator) { + return mRenderPipeline->createOrUpdateLayer(node, dmgAccumulator); + } + + /** + * Destroy any layers that have been attached to the provided RenderNode removing + * any state that may have been set during createOrUpdateLayer(). + */ + static void destroyLayer(RenderNode* node); + // Won't take effect until next EGLSurface creation void setSwapBehavior(SwapBehavior swapBehavior); diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h index 3250fed8f429..97cdf7fd4e8c 100644 --- a/libs/hwui/renderthread/IRenderPipeline.h +++ b/libs/hwui/renderthread/IRenderPipeline.h @@ -67,6 +67,8 @@ public: LayerUpdateQueue* layerUpdateQueue, bool opaque, const BakedOpRenderer::LightInfo& lightInfo) = 0; virtual TaskManager* getTaskManager() = 0; + virtual bool createOrUpdateLayer(RenderNode* node, + const DamageAccumulator& damageAccumulator) = 0; virtual ~IRenderPipeline() {} }; diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp index c8971f828a53..c758f6c6d1ad 100644 --- a/libs/hwui/renderthread/OpenGLPipeline.cpp +++ b/libs/hwui/renderthread/OpenGLPipeline.cpp @@ -183,6 +183,46 @@ TaskManager* OpenGLPipeline::getTaskManager() { return &Caches::getInstance().tasks; } +static bool layerMatchesWH(OffscreenBuffer* layer, int width, int height) { + return layer->viewportWidth == (uint32_t)width && layer->viewportHeight == (uint32_t)height; +} + +bool OpenGLPipeline::createOrUpdateLayer(RenderNode* node, + const DamageAccumulator& damageAccumulator) { + RenderState& renderState = mRenderThread.renderState(); + OffscreenBufferPool& layerPool = renderState.layerPool(); + bool transformUpdateNeeded = false; + if (node->getLayer() == nullptr) { + node->setLayer(layerPool.get(renderState, node->getWidth(), node->getHeight())); + transformUpdateNeeded = true; + } else if (!layerMatchesWH(node->getLayer(), node->getWidth(), node->getHeight())) { + // TODO: remove now irrelevant, currently enqueued damage (respecting damage ordering) + // Or, ideally, maintain damage between frames on node/layer so ordering is always correct + if (node->properties().fitsOnLayer()) { + node->setLayer(layerPool.resize(node->getLayer(), node->getWidth(), node->getHeight())); + } else { + destroyLayer(node); + } + transformUpdateNeeded = true; + } + + if (transformUpdateNeeded && node->getLayer()) { + // update the transform in window of the layer to reset its origin wrt light source position + Matrix4 windowTransform; + damageAccumulator.computeCurrentTransform(&windowTransform); + node->getLayer()->setWindowTransform(windowTransform); + } + + return transformUpdateNeeded; +} + +void OpenGLPipeline::destroyLayer(RenderNode* node) { + if (OffscreenBuffer* layer = node->getLayer()) { + layer->renderState.layerPool().putOrDelete(layer); + node->setLayer(nullptr); + } +} + } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/renderthread/OpenGLPipeline.h b/libs/hwui/renderthread/OpenGLPipeline.h index e08fd9b63ffa..34d9bc0c96bd 100644 --- a/libs/hwui/renderthread/OpenGLPipeline.h +++ b/libs/hwui/renderthread/OpenGLPipeline.h @@ -56,6 +56,9 @@ public: LayerUpdateQueue* layerUpdateQueue, bool opaque, const BakedOpRenderer::LightInfo& lightInfo) override; TaskManager* getTaskManager() override; + bool createOrUpdateLayer(RenderNode* node, + const DamageAccumulator& damageAccumulator) override; + static void destroyLayer(RenderNode* node); private: EglManager& mEglManager; |