From 0ebf4192f18778df844767c31dab8d502d78684c Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Thu, 4 Jan 2018 19:21:58 -0500 Subject: [sksg] More inval fiddling Node subclasses can now control whether their bounds (changes) contribute to damage. Tristate: * Default: The node bounds contribute to damage if the node itself was invalidated, observing hasSelfInval(). This is the default behavior. * ForceSelf: The node bounds contribute to damage, regardless of hasSelfInval(). Used for domain-boundary nodes (e.g. Draw), which gate blocked fragments (e.g. geometry, paint nodes). * BlockSelf: The node bounds do not contribute to damage, regardless of hasSelfInval(). Used for nodes which do not contribute damage directly (e.g. paints, geometry). TBR= Change-Id: I7c941c7ea12e14b008d846ec13108e66e34dbc73 Reviewed-on: https://skia-review.googlesource.com/91104 Reviewed-by: Florin Malita Commit-Queue: Florin Malita --- experimental/sksg/SkSGDraw.cpp | 8 +++++--- experimental/sksg/SkSGDraw.h | 2 +- experimental/sksg/SkSGEffectNode.cpp | 4 ++-- experimental/sksg/SkSGEffectNode.h | 2 +- experimental/sksg/SkSGGroup.cpp | 8 ++++---- experimental/sksg/SkSGGroup.h | 2 +- experimental/sksg/SkSGNode.cpp | 22 +++++++++++----------- experimental/sksg/SkSGNode.h | 11 ++++++++++- experimental/sksg/SkSGPaintNode.cpp | 5 +++-- experimental/sksg/SkSGPaintNode.h | 2 +- experimental/sksg/effects/SkSGTransform.cpp | 8 ++++---- experimental/sksg/effects/SkSGTransform.h | 2 +- experimental/sksg/geometry/SkSGMerge.cpp | 5 +++-- experimental/sksg/geometry/SkSGMerge.h | 2 +- experimental/sksg/geometry/SkSGPath.cpp | 5 +++-- experimental/sksg/geometry/SkSGPath.h | 2 +- experimental/sksg/geometry/SkSGRect.cpp | 10 ++++++---- experimental/sksg/geometry/SkSGRect.h | 4 ++-- 18 files changed, 60 insertions(+), 44 deletions(-) (limited to 'experimental') diff --git a/experimental/sksg/SkSGDraw.cpp b/experimental/sksg/SkSGDraw.cpp index c8e621856a..56415fc86e 100644 --- a/experimental/sksg/SkSGDraw.cpp +++ b/experimental/sksg/SkSGDraw.cpp @@ -29,14 +29,16 @@ void Draw::onRender(SkCanvas* canvas) const { fGeometry->draw(canvas, fPaint->makePaint()); } -SkRect Draw::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { +Node::RevalidationResult Draw::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { SkASSERT(this->hasInval()); - // TODO: paint bounds extents + // TODO: adjust bounds for paint const auto bounds = fGeometry->revalidate(ic, ctm); fPaint->revalidate(ic, ctm); - return bounds; + // Neither paint nor geometry contribute to damage directly; instead we generate + // damage here, at the binding point. + return { bounds, Damage::kForceSelf }; } } // namespace sksg diff --git a/experimental/sksg/SkSGDraw.h b/experimental/sksg/SkSGDraw.h index 20ead3d5f6..ad2b8fd602 100644 --- a/experimental/sksg/SkSGDraw.h +++ b/experimental/sksg/SkSGDraw.h @@ -34,7 +34,7 @@ protected: void onRender(SkCanvas*) const override; - SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; + RevalidationResult onRevalidate(InvalidationController*, const SkMatrix&) override; private: sk_sp fGeometry; diff --git a/experimental/sksg/SkSGEffectNode.cpp b/experimental/sksg/SkSGEffectNode.cpp index 1ecf7c7a92..4a1c8add8f 100644 --- a/experimental/sksg/SkSGEffectNode.cpp +++ b/experimental/sksg/SkSGEffectNode.cpp @@ -22,10 +22,10 @@ void EffectNode::onRender(SkCanvas* canvas) const { fChild->render(canvas); } -SkRect EffectNode::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { +Node::RevalidationResult EffectNode::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { SkASSERT(this->hasInval()); - return fChild->revalidate(ic, ctm); + return { fChild->revalidate(ic, ctm), Damage::kDefault }; } } // namespace sksg diff --git a/experimental/sksg/SkSGEffectNode.h b/experimental/sksg/SkSGEffectNode.h index ab0968e96c..0fd71bc996 100644 --- a/experimental/sksg/SkSGEffectNode.h +++ b/experimental/sksg/SkSGEffectNode.h @@ -25,7 +25,7 @@ protected: void onRender(SkCanvas*) const override; - SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; + RevalidationResult onRevalidate(InvalidationController*, const SkMatrix&) override; private: sk_sp fChild; diff --git a/experimental/sksg/SkSGGroup.cpp b/experimental/sksg/SkSGGroup.cpp index fa9ae1e90e..9f40d6ad48 100644 --- a/experimental/sksg/SkSGGroup.cpp +++ b/experimental/sksg/SkSGGroup.cpp @@ -51,16 +51,16 @@ void Group::onRender(SkCanvas* canvas) const { } } -SkRect Group::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { +Node::RevalidationResult Group::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { SkASSERT(this->hasInval()); - SkRect bounds = SkRect::MakeEmpty(); + RevalidationResult result = { SkRect::MakeEmpty(), Damage::kDefault }; for (const auto& child : fChildren) { - bounds.join(child->revalidate(ic, ctm)); + result.fBounds.join(child->revalidate(ic, ctm)); } - return bounds; + return result; } } // namespace sksg diff --git a/experimental/sksg/SkSGGroup.h b/experimental/sksg/SkSGGroup.h index f9126ea37f..3d8b1ad3c4 100644 --- a/experimental/sksg/SkSGGroup.h +++ b/experimental/sksg/SkSGGroup.h @@ -31,7 +31,7 @@ protected: ~Group() override; void onRender(SkCanvas*) const override; - SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; + RevalidationResult onRevalidate(InvalidationController*, const SkMatrix&) override; private: SkTArray, true> fChildren; diff --git a/experimental/sksg/SkSGNode.cpp b/experimental/sksg/SkSGNode.cpp index d3e804070c..13e9864147 100644 --- a/experimental/sksg/SkSGNode.cpp +++ b/experimental/sksg/SkSGNode.cpp @@ -127,20 +127,20 @@ const SkRect& Node::revalidate(InvalidationController* ic, const SkMatrix& ctm) return fBounds; } - SkRect prevBounds; - if (this->hasSelfInval()) { - prevBounds = fBounds; - } - - fBounds = this->onRevalidate(ic, ctm); - - if (this->hasSelfInval()) { - ic->inval(prevBounds, ctm); - if (fBounds != prevBounds) { - ic->inval(fBounds, ctm); + const auto result = this->onRevalidate(ic, ctm); + const auto selfDamage = result.fReval == Damage::kForceSelf || + (this->hasSelfInval() && result.fReval != Damage::kBlockSelf); + + if (selfDamage) { + // old bounds + ic->inval(fBounds, ctm); + if (result.fBounds != fBounds) { + // new bounds + ic->inval(result.fBounds, ctm); } } + fBounds = result.fBounds; fFlags &= ~(kInvalSelf_Flag | kInvalDescendant_Flag); return fBounds; diff --git a/experimental/sksg/SkSGNode.h b/experimental/sksg/SkSGNode.h index 7758eca4c5..58456cf387 100644 --- a/experimental/sksg/SkSGNode.h +++ b/experimental/sksg/SkSGNode.h @@ -47,7 +47,16 @@ protected: // Dispatched on revalidation. Subclasses are expected to recompute/cache their properties // and return their bounding box in local coordinates. - virtual SkRect onRevalidate(InvalidationController*, const SkMatrix& ctm) = 0; + enum class Damage { + kDefault, // respects the local kInvalSelf_Flag + kForceSelf, // forces self revalidation regardless of kInvalSelf_Flag + kBlockSelf, // blocks self revalidation regardless of kInvalSelf_Flag + }; + struct RevalidationResult { + SkRect fBounds; + Damage fReval; + }; + virtual RevalidationResult onRevalidate(InvalidationController*, const SkMatrix& ctm) = 0; private: void addInvalReceiver(Node*); diff --git a/experimental/sksg/SkSGPaintNode.cpp b/experimental/sksg/SkSGPaintNode.cpp index fbdfae5d69..be8edac7c5 100644 --- a/experimental/sksg/SkSGPaintNode.cpp +++ b/experimental/sksg/SkSGPaintNode.cpp @@ -17,7 +17,7 @@ const SkPaint& PaintNode::makePaint() { return fPaint; } -SkRect PaintNode::onRevalidate(InvalidationController*, const SkMatrix&) { +Node::RevalidationResult PaintNode::onRevalidate(InvalidationController*, const SkMatrix&) { SkASSERT(this->hasInval()); if (this->hasSelfInval()) { @@ -32,7 +32,8 @@ SkRect PaintNode::onRevalidate(InvalidationController*, const SkMatrix&) { this->onApplyToPaint(&fPaint); } - return SkRect::MakeEmpty(); + // Paints have no bounds and don't contribute to damage. + return { SkRect::MakeEmpty(), Damage::kBlockSelf }; } } // namespace sksg diff --git a/experimental/sksg/SkSGPaintNode.h b/experimental/sksg/SkSGPaintNode.h index a2fbada065..0dac92e444 100644 --- a/experimental/sksg/SkSGPaintNode.h +++ b/experimental/sksg/SkSGPaintNode.h @@ -36,7 +36,7 @@ protected: virtual void onApplyToPaint(SkPaint*) const = 0; - SkRect onRevalidate(InvalidationController*, const SkMatrix&) final; + RevalidationResult onRevalidate(InvalidationController*, const SkMatrix&) final; private: SkPaint fPaint; diff --git a/experimental/sksg/effects/SkSGTransform.cpp b/experimental/sksg/effects/SkSGTransform.cpp index ca4c5cd162..dc31623db2 100644 --- a/experimental/sksg/effects/SkSGTransform.cpp +++ b/experimental/sksg/effects/SkSGTransform.cpp @@ -21,13 +21,13 @@ void Transform::onRender(SkCanvas* canvas) const { this->INHERITED::onRender(canvas); } -SkRect Transform::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { +Node::RevalidationResult Transform::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { SkASSERT(this->hasInval()); - auto bounds = this->INHERITED::onRevalidate(ic, SkMatrix::Concat(ctm, fMatrix)); - fMatrix.mapRect(&bounds); + auto result = this->INHERITED::onRevalidate(ic, SkMatrix::Concat(ctm, fMatrix)); + fMatrix.mapRect(&result.fBounds); - return bounds; + return result; } } // namespace sksg diff --git a/experimental/sksg/effects/SkSGTransform.h b/experimental/sksg/effects/SkSGTransform.h index a32f83dcc6..8a97a679ed 100644 --- a/experimental/sksg/effects/SkSGTransform.h +++ b/experimental/sksg/effects/SkSGTransform.h @@ -30,7 +30,7 @@ protected: void onRender(SkCanvas*) const override; - SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; + RevalidationResult onRevalidate(InvalidationController*, const SkMatrix&) override; private: SkMatrix fMatrix; diff --git a/experimental/sksg/geometry/SkSGMerge.cpp b/experimental/sksg/geometry/SkSGMerge.cpp index a9f06d464f..47429a5444 100644 --- a/experimental/sksg/geometry/SkSGMerge.cpp +++ b/experimental/sksg/geometry/SkSGMerge.cpp @@ -54,7 +54,7 @@ static SkPathOp mode_to_op(Merge::Mode mode) { return kUnion_SkPathOp; } -SkRect Merge::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { +Node::RevalidationResult Merge::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { SkASSERT(this->hasInval()); const auto op = mode_to_op(fMode); @@ -75,7 +75,8 @@ SkRect Merge::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { builder.resolve(&fMerged); } - return fMerged.computeTightBounds(); + // Geometry does not contribute damage directly. + return { fMerged.computeTightBounds(), Damage::kBlockSelf }; } } // namespace skotty diff --git a/experimental/sksg/geometry/SkSGMerge.h b/experimental/sksg/geometry/SkSGMerge.h index b0cb40de9c..f3e20877fa 100644 --- a/experimental/sksg/geometry/SkSGMerge.h +++ b/experimental/sksg/geometry/SkSGMerge.h @@ -45,7 +45,7 @@ public: protected: void onDraw(SkCanvas*, const SkPaint&) const override; - SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; + RevalidationResult onRevalidate(InvalidationController*, const SkMatrix&) override; SkPath onAsPath() const override; private: diff --git a/experimental/sksg/geometry/SkSGPath.cpp b/experimental/sksg/geometry/SkSGPath.cpp index a04dcf60cc..ce1ff392ac 100644 --- a/experimental/sksg/geometry/SkSGPath.cpp +++ b/experimental/sksg/geometry/SkSGPath.cpp @@ -18,10 +18,11 @@ void Path::onDraw(SkCanvas* canvas, const SkPaint& paint) const { canvas->drawPath(fPath, paint); } -SkRect Path::onRevalidate(InvalidationController*, const SkMatrix&) { +Node::RevalidationResult Path::onRevalidate(InvalidationController*, const SkMatrix&) { SkASSERT(this->hasSelfInval()); - return fPath.computeTightBounds(); + // Geometry does not contribute damage directly. + return { fPath.computeTightBounds(), Damage::kBlockSelf }; } SkPath Path::onAsPath() const { diff --git a/experimental/sksg/geometry/SkSGPath.h b/experimental/sksg/geometry/SkSGPath.h index 18caa10f2a..32388c988b 100644 --- a/experimental/sksg/geometry/SkSGPath.h +++ b/experimental/sksg/geometry/SkSGPath.h @@ -30,7 +30,7 @@ public: protected: void onDraw(SkCanvas*, const SkPaint&) const override; - SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; + RevalidationResult onRevalidate(InvalidationController*, const SkMatrix&) override; SkPath onAsPath() const override; private: diff --git a/experimental/sksg/geometry/SkSGRect.cpp b/experimental/sksg/geometry/SkSGRect.cpp index c2ac384bef..0184dace90 100644 --- a/experimental/sksg/geometry/SkSGRect.cpp +++ b/experimental/sksg/geometry/SkSGRect.cpp @@ -19,10 +19,11 @@ void Rect::onDraw(SkCanvas* canvas, const SkPaint& paint) const { canvas->drawRect(fRect, paint); } -SkRect Rect::onRevalidate(InvalidationController*, const SkMatrix&) { +Node::RevalidationResult Rect::onRevalidate(InvalidationController*, const SkMatrix&) { SkASSERT(this->hasSelfInval()); - return fRect; + // Geometry does not contribute damage directly. + return { fRect, Damage::kBlockSelf }; } SkPath Rect::onAsPath() const { @@ -37,10 +38,11 @@ void RRect::onDraw(SkCanvas* canvas, const SkPaint& paint) const { canvas->drawRRect(fRRect, paint); } -SkRect RRect::onRevalidate(InvalidationController*, const SkMatrix&) { +Node::RevalidationResult RRect::onRevalidate(InvalidationController*, const SkMatrix&) { SkASSERT(this->hasSelfInval()); - return fRRect.getBounds(); + // Geometry does not contribute damage directly. + return { fRRect.getBounds(), Damage::kBlockSelf }; } SkPath RRect::onAsPath() const { diff --git a/experimental/sksg/geometry/SkSGRect.h b/experimental/sksg/geometry/SkSGRect.h index ad27910da9..4667b6b42d 100644 --- a/experimental/sksg/geometry/SkSGRect.h +++ b/experimental/sksg/geometry/SkSGRect.h @@ -34,7 +34,7 @@ public: protected: void onDraw(SkCanvas*, const SkPaint&) const override; - SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; + RevalidationResult onRevalidate(InvalidationController*, const SkMatrix&) override; SkPath onAsPath() const override; private: @@ -56,7 +56,7 @@ public: protected: void onDraw(SkCanvas*, const SkPaint&) const override; - SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; + RevalidationResult onRevalidate(InvalidationController*, const SkMatrix&) override; SkPath onAsPath() const override; private: -- cgit v1.2.3