diff options
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaPipeline.cpp | 6 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaPipeline.h | 1 | ||||
| -rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 1 | ||||
| -rw-r--r-- | libs/hwui/renderthread/IRenderPipeline.h | 1 | ||||
| -rw-r--r-- | libs/hwui/renderthread/OpenGLPipeline.h | 1 | ||||
| -rw-r--r-- | libs/hwui/tests/unit/SkiaPipelineTests.cpp | 34 |
6 files changed, 44 insertions, 0 deletions
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index c4bd1e1b10d4..cdf4aee609fb 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -75,6 +75,12 @@ void SkiaPipeline::unpinImages() { mPinnedImages.clear(); } +void SkiaPipeline::onPrepareTree() { + // The only time mVectorDrawables is not empty is if prepare tree was called 2 times without + // a renderFrame in the middle. + mVectorDrawables.clear(); +} + void SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut, const BakedOpRenderer::LightInfo& lightInfo) { diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h index 3e6ae306217c..dc0b8f6dd2bc 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.h +++ b/libs/hwui/pipeline/skia/SkiaPipeline.h @@ -37,6 +37,7 @@ public: bool pinImages(std::vector<SkImage*>& mutableImages) override; bool pinImages(LsaVector<sk_sp<Bitmap>>& images) override { return false; } void unpinImages() override; + void onPrepareTree() override; void renderLayers(const FrameBuilder::LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut, diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 5d7f5948b0ec..ad684db56d94 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -331,6 +331,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, info.layerUpdateQueue = &mLayerUpdateQueue; mAnimationContext->startFrame(info.mode); + mRenderPipeline->onPrepareTree(); for (const sp<RenderNode>& node : mRenderNodes) { // Only the primary target node will be drawn full - all other nodes would get drawn in // real time mode. In case of a window, the primary node is the window content and the other diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h index f9b6e384d211..0bb3889c7a1d 100644 --- a/libs/hwui/renderthread/IRenderPipeline.h +++ b/libs/hwui/renderthread/IRenderPipeline.h @@ -81,6 +81,7 @@ public: virtual bool pinImages(std::vector<SkImage*>& mutableImages) = 0; virtual bool pinImages(LsaVector<sk_sp<Bitmap>>& images) = 0; virtual void unpinImages() = 0; + virtual void onPrepareTree() = 0; virtual ~IRenderPipeline() {} }; diff --git a/libs/hwui/renderthread/OpenGLPipeline.h b/libs/hwui/renderthread/OpenGLPipeline.h index 4ca19fb6245c..1f467c164d7f 100644 --- a/libs/hwui/renderthread/OpenGLPipeline.h +++ b/libs/hwui/renderthread/OpenGLPipeline.h @@ -58,6 +58,7 @@ public: bool pinImages(std::vector<SkImage*>& mutableImages) override { return false; } bool pinImages(LsaVector<sk_sp<Bitmap>>& images) override; void unpinImages() override; + void onPrepareTree() override {} static void destroyLayer(RenderNode* node); static void prepareToDraw(const RenderThread& thread, Bitmap* bitmap); static void invokeFunctor(const RenderThread& thread, Functor* functor); diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp index b397b151ad76..f430ce633717 100644 --- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp +++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp @@ -56,6 +56,40 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrame) { ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED); } +RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, testOnPrepareTree) { + + auto redNode = TestUtils::createSkiaNode(0, 0, 1, 1, + [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) { + redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver); + }); + + LayerUpdateQueue layerUpdateQueue; + SkRect dirty = SkRect::MakeLargest(); + std::vector<sp<RenderNode>> renderNodes; + renderNodes.push_back(redNode); + bool opaque = true; + android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1); + auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); + { + //add a pointer to a deleted vector drawable object in the pipeline + sp<VectorDrawableRoot> dirtyVD(new VectorDrawableRoot(new VectorDrawable::Group())); + dirtyVD->mutateProperties()->setScaledSize(5,5); + pipeline->getVectorDrawables()->push_back(dirtyVD.get()); + } + + //pipeline should clean list of dirty vector drawables before prepare tree + pipeline->onPrepareTree(); + + auto surface = SkSurface::MakeRasterN32Premul(1, 1); + surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); + ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); + + //drawFrame will crash if "SkiaPipeline::onPrepareTree" did not clean invalid VD pointer + pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, + opaque, false, contentDrawBounds, surface); + ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED); +} + RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckOpaque) { auto halfGreenNode = TestUtils::createSkiaNode(0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& bottomHalfGreenCanvas) { |