Loading libs/hwui/RecordingCanvas.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -759,6 +759,8 @@ RecordingCanvas::RecordingCanvas() : INHERITED(1, 1), fDL(nullptr) {} void RecordingCanvas::reset(DisplayListData* dl, const SkIRect& bounds) { this->resetCanvas(bounds.right(), bounds.bottom()); fDL = dl; mClipMayBeComplex = false; mSaveCount = mComplexSaveCount = 0; } sk_sp<SkSurface> RecordingCanvas::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) { Loading @@ -770,6 +772,7 @@ void RecordingCanvas::onFlush() { } void RecordingCanvas::willSave() { mSaveCount++; fDL->save(); } SkCanvas::SaveLayerStrategy RecordingCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) { Loading @@ -778,6 +781,11 @@ SkCanvas::SaveLayerStrategy RecordingCanvas::getSaveLayerStrategy(const SaveLaye return SkCanvas::kNoLayer_SaveLayerStrategy; } void RecordingCanvas::willRestore() { mSaveCount--; if (mSaveCount < mComplexSaveCount) { mClipMayBeComplex = false; mComplexSaveCount = 0; } fDL->restore(); } Loading @@ -798,17 +806,27 @@ void RecordingCanvas::didTranslate(SkScalar dx, SkScalar dy) { void RecordingCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle style) { fDL->clipRect(rect, op, style == kSoft_ClipEdgeStyle); if (!getTotalMatrix().isScaleTranslate()) { setClipMayBeComplex(); } this->INHERITED::onClipRect(rect, op, style); } void RecordingCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle style) { if (rrect.getType() > SkRRect::kRect_Type || !getTotalMatrix().isScaleTranslate()) { setClipMayBeComplex(); } fDL->clipRRect(rrect, op, style == kSoft_ClipEdgeStyle); this->INHERITED::onClipRRect(rrect, op, style); } void RecordingCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle style) { setClipMayBeComplex(); fDL->clipPath(path, op, style == kSoft_ClipEdgeStyle); this->INHERITED::onClipPath(path, op, style); } void RecordingCanvas::onClipRegion(const SkRegion& region, SkClipOp op) { if (region.isComplex() || !getTotalMatrix().isScaleTranslate()) { setClipMayBeComplex(); } fDL->clipRegion(region, op); this->INHERITED::onClipRegion(region, op); } Loading libs/hwui/RecordingCanvas.h +31 −0 Original line number Diff line number Diff line Loading @@ -203,10 +203,41 @@ public: void drawVectorDrawable(VectorDrawableRoot* tree); /** * If "isClipMayBeComplex" returns false, it is guaranteed the current clip is a rectangle. * If the return value is true, then clip may or may not be complex (there is no guarantee). */ inline bool isClipMayBeComplex() { return mClipMayBeComplex; } private: typedef SkCanvasVirtualEnforcer<SkNoDrawCanvas> INHERITED; inline void setClipMayBeComplex() { if (!mClipMayBeComplex) { mComplexSaveCount = mSaveCount; mClipMayBeComplex = true; } } DisplayListData* fDL; /** * mClipMayBeComplex tracks if the current clip is a rectangle. This flag is used to promote * FunctorDrawable to a layer, if it is clipped by a non-rect. */ bool mClipMayBeComplex = false; /** * mSaveCount is the current level of our save tree. */ int mSaveCount = 0; /** * mComplexSaveCount is the first save level, which has a complex clip. Every level below * mComplexSaveCount is assumed to have a complex clip and every level above mComplexSaveCount * is guaranteed to not be complex. */ int mComplexSaveCount = 0; }; } // namespace uirenderer Loading libs/hwui/RenderProperties.h +8 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ public: // parent may have already dictated that a descendant layer is needed bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer || CC_UNLIKELY(isClipMayBeComplex()) // Round rect clipping forces layer for functors || CC_UNLIKELY(getOutline().willRoundRectClip()) || Loading Loading @@ -193,6 +194,12 @@ public: bool isProjectionReceiver() const { return mPrimitiveFields.mProjectionReceiver; } bool setClipMayBeComplex(bool isClipMayBeComplex) { return RP_SET(mPrimitiveFields.mClipMayBeComplex, isClipMayBeComplex); } bool isClipMayBeComplex() const { return mPrimitiveFields.mClipMayBeComplex; } bool setStaticMatrix(const SkMatrix* matrix) { delete mStaticMatrix; if (matrix) { Loading Loading @@ -563,6 +570,7 @@ private: bool mProjectBackwards = false; bool mProjectionReceiver = false; bool mAllowForceDark = true; bool mClipMayBeComplex = false; Rect mClipBounds; Outline mOutline; RevealClip mRevealClip; Loading libs/hwui/pipeline/skia/SkiaDisplayList.cpp +0 −1 Original line number Diff line number Diff line Loading @@ -73,7 +73,6 @@ bool SkiaDisplayList::prepareListAndChildren( RenderNode* childNode = child.getRenderNode(); Matrix4 mat4(child.getRecordedMatrix()); info.damageAccumulator->pushTransform(&mat4); // TODO: a layer is needed if the canvas is rotated or has a non-rect clip info.hasBackwardProjectedNodes = false; childFn(childNode, observer, info, functorsNeedLayer); hasBackwardProjectedNodesSubtree |= info.hasBackwardProjectedNodes; Loading libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,10 @@ void SkiaRecordingCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) { // Record the child node. Drawable dtor will be invoked when mChildNodes deque is cleared. mDisplayList->mChildNodes.emplace_back(renderNode, asSkCanvas(), true, mCurrentBarrier); auto& renderNodeDrawable = mDisplayList->mChildNodes.back(); if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { // Put Vulkan WebViews with non-rectangular clips in a HW layer renderNode->mutateStagingProperties().setClipMayBeComplex(mRecorder.isClipMayBeComplex()); } drawDrawable(&renderNodeDrawable); // use staging property, since recording on UI thread Loading Loading
libs/hwui/RecordingCanvas.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -759,6 +759,8 @@ RecordingCanvas::RecordingCanvas() : INHERITED(1, 1), fDL(nullptr) {} void RecordingCanvas::reset(DisplayListData* dl, const SkIRect& bounds) { this->resetCanvas(bounds.right(), bounds.bottom()); fDL = dl; mClipMayBeComplex = false; mSaveCount = mComplexSaveCount = 0; } sk_sp<SkSurface> RecordingCanvas::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) { Loading @@ -770,6 +772,7 @@ void RecordingCanvas::onFlush() { } void RecordingCanvas::willSave() { mSaveCount++; fDL->save(); } SkCanvas::SaveLayerStrategy RecordingCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) { Loading @@ -778,6 +781,11 @@ SkCanvas::SaveLayerStrategy RecordingCanvas::getSaveLayerStrategy(const SaveLaye return SkCanvas::kNoLayer_SaveLayerStrategy; } void RecordingCanvas::willRestore() { mSaveCount--; if (mSaveCount < mComplexSaveCount) { mClipMayBeComplex = false; mComplexSaveCount = 0; } fDL->restore(); } Loading @@ -798,17 +806,27 @@ void RecordingCanvas::didTranslate(SkScalar dx, SkScalar dy) { void RecordingCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle style) { fDL->clipRect(rect, op, style == kSoft_ClipEdgeStyle); if (!getTotalMatrix().isScaleTranslate()) { setClipMayBeComplex(); } this->INHERITED::onClipRect(rect, op, style); } void RecordingCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle style) { if (rrect.getType() > SkRRect::kRect_Type || !getTotalMatrix().isScaleTranslate()) { setClipMayBeComplex(); } fDL->clipRRect(rrect, op, style == kSoft_ClipEdgeStyle); this->INHERITED::onClipRRect(rrect, op, style); } void RecordingCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle style) { setClipMayBeComplex(); fDL->clipPath(path, op, style == kSoft_ClipEdgeStyle); this->INHERITED::onClipPath(path, op, style); } void RecordingCanvas::onClipRegion(const SkRegion& region, SkClipOp op) { if (region.isComplex() || !getTotalMatrix().isScaleTranslate()) { setClipMayBeComplex(); } fDL->clipRegion(region, op); this->INHERITED::onClipRegion(region, op); } Loading
libs/hwui/RecordingCanvas.h +31 −0 Original line number Diff line number Diff line Loading @@ -203,10 +203,41 @@ public: void drawVectorDrawable(VectorDrawableRoot* tree); /** * If "isClipMayBeComplex" returns false, it is guaranteed the current clip is a rectangle. * If the return value is true, then clip may or may not be complex (there is no guarantee). */ inline bool isClipMayBeComplex() { return mClipMayBeComplex; } private: typedef SkCanvasVirtualEnforcer<SkNoDrawCanvas> INHERITED; inline void setClipMayBeComplex() { if (!mClipMayBeComplex) { mComplexSaveCount = mSaveCount; mClipMayBeComplex = true; } } DisplayListData* fDL; /** * mClipMayBeComplex tracks if the current clip is a rectangle. This flag is used to promote * FunctorDrawable to a layer, if it is clipped by a non-rect. */ bool mClipMayBeComplex = false; /** * mSaveCount is the current level of our save tree. */ int mSaveCount = 0; /** * mComplexSaveCount is the first save level, which has a complex clip. Every level below * mComplexSaveCount is assumed to have a complex clip and every level above mComplexSaveCount * is guaranteed to not be complex. */ int mComplexSaveCount = 0; }; } // namespace uirenderer Loading
libs/hwui/RenderProperties.h +8 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ public: // parent may have already dictated that a descendant layer is needed bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer || CC_UNLIKELY(isClipMayBeComplex()) // Round rect clipping forces layer for functors || CC_UNLIKELY(getOutline().willRoundRectClip()) || Loading Loading @@ -193,6 +194,12 @@ public: bool isProjectionReceiver() const { return mPrimitiveFields.mProjectionReceiver; } bool setClipMayBeComplex(bool isClipMayBeComplex) { return RP_SET(mPrimitiveFields.mClipMayBeComplex, isClipMayBeComplex); } bool isClipMayBeComplex() const { return mPrimitiveFields.mClipMayBeComplex; } bool setStaticMatrix(const SkMatrix* matrix) { delete mStaticMatrix; if (matrix) { Loading Loading @@ -563,6 +570,7 @@ private: bool mProjectBackwards = false; bool mProjectionReceiver = false; bool mAllowForceDark = true; bool mClipMayBeComplex = false; Rect mClipBounds; Outline mOutline; RevealClip mRevealClip; Loading
libs/hwui/pipeline/skia/SkiaDisplayList.cpp +0 −1 Original line number Diff line number Diff line Loading @@ -73,7 +73,6 @@ bool SkiaDisplayList::prepareListAndChildren( RenderNode* childNode = child.getRenderNode(); Matrix4 mat4(child.getRecordedMatrix()); info.damageAccumulator->pushTransform(&mat4); // TODO: a layer is needed if the canvas is rotated or has a non-rect clip info.hasBackwardProjectedNodes = false; childFn(childNode, observer, info, functorsNeedLayer); hasBackwardProjectedNodesSubtree |= info.hasBackwardProjectedNodes; Loading
libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,10 @@ void SkiaRecordingCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) { // Record the child node. Drawable dtor will be invoked when mChildNodes deque is cleared. mDisplayList->mChildNodes.emplace_back(renderNode, asSkCanvas(), true, mCurrentBarrier); auto& renderNodeDrawable = mDisplayList->mChildNodes.back(); if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { // Put Vulkan WebViews with non-rectangular clips in a HW layer renderNode->mutateStagingProperties().setClipMayBeComplex(mRecorder.isClipMayBeComplex()); } drawDrawable(&renderNodeDrawable); // use staging property, since recording on UI thread Loading