[sksg] Refactor inval registration
... to avoid having too many Node friends. TBR= Change-Id: I8f8ff570d94ea48017935066a3d51cd8265ec120 Reviewed-on: https://skia-review.googlesource.com/97980 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
dba65f95e4
commit
3ba3fa72ae
@ -16,13 +16,13 @@ namespace sksg {
|
||||
Draw::Draw(sk_sp<GeometryNode> geometry, sk_sp<PaintNode> paint)
|
||||
: fGeometry(std::move(geometry))
|
||||
, fPaint(std::move(paint)) {
|
||||
fGeometry->addInvalReceiver(this);
|
||||
fPaint->addInvalReceiver(this);
|
||||
this->observeInval(fGeometry);
|
||||
this->observeInval(fPaint);
|
||||
}
|
||||
|
||||
Draw::~Draw() {
|
||||
fGeometry->removeInvalReceiver(this);
|
||||
fPaint->removeInvalReceiver(this);
|
||||
this->unobserveInval(fGeometry);
|
||||
this->unobserveInval(fPaint);
|
||||
}
|
||||
|
||||
void Draw::onRender(SkCanvas* canvas) const {
|
||||
|
@ -11,11 +11,11 @@ namespace sksg {
|
||||
|
||||
EffectNode::EffectNode(sk_sp<RenderNode> child)
|
||||
: fChild(std::move(child)) {
|
||||
fChild->addInvalReceiver(this);
|
||||
this->observeInval(fChild);
|
||||
}
|
||||
|
||||
EffectNode::~EffectNode() {
|
||||
fChild->removeInvalReceiver(this);
|
||||
this->unobserveInval(fChild);
|
||||
}
|
||||
|
||||
void EffectNode::onRender(SkCanvas* canvas) const {
|
||||
|
@ -13,7 +13,7 @@ Group::Group() {}
|
||||
|
||||
Group::~Group() {
|
||||
for (const auto& child : fChildren) {
|
||||
child->removeInvalReceiver(this);
|
||||
this->unobserveInval(child);
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ void Group::addChild(sk_sp<RenderNode> node) {
|
||||
}
|
||||
}
|
||||
|
||||
node->addInvalReceiver(this);
|
||||
this->observeInval(node);
|
||||
fChildren.push_back(std::move(node));
|
||||
|
||||
this->invalidate();
|
||||
@ -36,7 +36,7 @@ void Group::removeChild(const sk_sp<RenderNode>& node) {
|
||||
for (int i = 0; i < origCount; ++i) {
|
||||
if (fChildren[i] == node) {
|
||||
fChildren.removeShuffle(i);
|
||||
node->removeInvalReceiver(this);
|
||||
this->unobserveInval(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -39,64 +39,66 @@ private:
|
||||
return
|
||||
|
||||
Node::Node(uint32_t invalTraits)
|
||||
: fInvalReceiver(nullptr)
|
||||
: fInvalObserver(nullptr)
|
||||
, fBounds(SkRectPriv::MakeLargeS32())
|
||||
, fInvalTraits(invalTraits)
|
||||
, fFlags(kInvalidated_Flag) {}
|
||||
|
||||
Node::~Node() {
|
||||
if (fFlags & kReceiverArray_Flag) {
|
||||
SkASSERT(fInvalReceiverArray->isEmpty());
|
||||
delete fInvalReceiverArray;
|
||||
if (fFlags & kObserverArray_Flag) {
|
||||
SkASSERT(fInvalObserverArray->isEmpty());
|
||||
delete fInvalObserverArray;
|
||||
} else {
|
||||
SkASSERT(!fInvalReceiver);
|
||||
SkASSERT(!fInvalObserver);
|
||||
}
|
||||
}
|
||||
|
||||
void Node::addInvalReceiver(Node* receiver) {
|
||||
if (!(fFlags & kReceiverArray_Flag)) {
|
||||
if (!fInvalReceiver) {
|
||||
fInvalReceiver = receiver;
|
||||
void Node::observeInval(const sk_sp<Node>& node) {
|
||||
SkASSERT(node);
|
||||
if (!(node->fFlags & kObserverArray_Flag)) {
|
||||
if (!node->fInvalObserver) {
|
||||
node->fInvalObserver = this;
|
||||
return;
|
||||
}
|
||||
|
||||
auto receivers = new SkTDArray<Node*>();
|
||||
receivers->setReserve(2);
|
||||
receivers->push(fInvalReceiver);
|
||||
auto observers = new SkTDArray<Node*>();
|
||||
observers->setReserve(2);
|
||||
observers->push(node->fInvalObserver);
|
||||
|
||||
fInvalReceiverArray = receivers;
|
||||
fFlags |= kReceiverArray_Flag;
|
||||
node->fInvalObserverArray = observers;
|
||||
node->fFlags |= kObserverArray_Flag;
|
||||
}
|
||||
|
||||
// No duplicate receivers.
|
||||
SkASSERT(fInvalReceiverArray->find(receiver) < 0);
|
||||
// No duplicate observers.
|
||||
SkASSERT(node->fInvalObserverArray->find(this) < 0);
|
||||
|
||||
fInvalReceiverArray->push(receiver);
|
||||
node->fInvalObserverArray->push(this);
|
||||
}
|
||||
|
||||
void Node::removeInvalReceiver(Node* receiver) {
|
||||
if (!(fFlags & kReceiverArray_Flag)) {
|
||||
SkASSERT(fInvalReceiver == receiver);
|
||||
fInvalReceiver = nullptr;
|
||||
void Node::unobserveInval(const sk_sp<Node>& node) {
|
||||
SkASSERT(node);
|
||||
if (!(node->fFlags & kObserverArray_Flag)) {
|
||||
SkASSERT(node->fInvalObserver == this);
|
||||
node->fInvalObserver = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto idx = fInvalReceiverArray->find(receiver);
|
||||
const auto idx = node->fInvalObserverArray->find(this);
|
||||
SkASSERT(idx >= 0);
|
||||
fInvalReceiverArray->remove(idx);
|
||||
node->fInvalObserverArray->remove(idx);
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
void Node::forEachInvalReceiver(Func&& func) const {
|
||||
if (fFlags & kReceiverArray_Flag) {
|
||||
for (const auto& parent : *fInvalReceiverArray) {
|
||||
void Node::forEachInvalObserver(Func&& func) const {
|
||||
if (fFlags & kObserverArray_Flag) {
|
||||
for (const auto& parent : *fInvalObserverArray) {
|
||||
func(parent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (fInvalReceiver) {
|
||||
func(fInvalReceiver);
|
||||
if (fInvalObserver) {
|
||||
func(fInvalObserver);
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,15 +111,15 @@ void Node::invalidate(bool damageBubbling) {
|
||||
}
|
||||
|
||||
if (damageBubbling && !(fInvalTraits & kBubbleDamage_Trait)) {
|
||||
// Found a damage receiver.
|
||||
// Found a damage observer.
|
||||
fFlags |= kDamage_Flag;
|
||||
damageBubbling = false;
|
||||
}
|
||||
|
||||
fFlags |= kInvalidated_Flag;
|
||||
|
||||
forEachInvalReceiver([&](Node* receiver) {
|
||||
receiver->invalidate(damageBubbling);
|
||||
forEachInvalObserver([&](Node* observer) {
|
||||
observer->invalidate(damageBubbling);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -57,36 +57,26 @@ protected:
|
||||
// and return their bounding box in local coordinates.
|
||||
virtual SkRect onRevalidate(InvalidationController*, const SkMatrix& ctm) = 0;
|
||||
|
||||
// Register/unregister |this| to receive invalidation events from a descendant.
|
||||
void observeInval(const sk_sp<Node>&);
|
||||
void unobserveInval(const sk_sp<Node>&);
|
||||
|
||||
private:
|
||||
enum Flags {
|
||||
kInvalidated_Flag = 1 << 0, // the node or its descendants require revalidation
|
||||
kDamage_Flag = 1 << 1, // the node contributes damage during revalidation
|
||||
kReceiverArray_Flag = 1 << 2, // the node has more than one inval receiver
|
||||
kObserverArray_Flag = 1 << 2, // the node has more than one inval observer
|
||||
kInTraversal_Flag = 1 << 3, // the node is part of a traversal (cycle detection)
|
||||
};
|
||||
|
||||
void addInvalReceiver(Node*);
|
||||
void removeInvalReceiver(Node*);
|
||||
// TODO: too friendly, find another way.
|
||||
friend class Draw;
|
||||
friend class EffectNode;
|
||||
friend class GeometryTransform;
|
||||
friend class Group;
|
||||
friend class MaskEffect;
|
||||
friend class Matrix;
|
||||
friend class Merge;
|
||||
friend class Stroke;
|
||||
friend class Transform;
|
||||
friend class TrimEffect;
|
||||
|
||||
template <typename Func>
|
||||
void forEachInvalReceiver(Func&&) const;
|
||||
void forEachInvalObserver(Func&&) const;
|
||||
|
||||
class ScopedFlag;
|
||||
|
||||
union {
|
||||
Node* fInvalReceiver;
|
||||
SkTDArray<Node*>* fInvalReceiverArray;
|
||||
Node* fInvalObserver;
|
||||
SkTDArray<Node*>* fInvalObserverArray;
|
||||
};
|
||||
SkRect fBounds;
|
||||
const uint32_t fInvalTraits : 16;
|
||||
|
@ -14,11 +14,11 @@ namespace sksg {
|
||||
MaskEffect::MaskEffect(sk_sp<RenderNode> child, sk_sp<RenderNode> mask)
|
||||
: INHERITED(std::move(child))
|
||||
, fMaskNode(std::move(mask)) {
|
||||
fMaskNode->addInvalReceiver(this);
|
||||
this->observeInval(fMaskNode);
|
||||
}
|
||||
|
||||
MaskEffect::~MaskEffect() {
|
||||
fMaskNode->removeInvalReceiver(this);
|
||||
this->unobserveInval(fMaskNode);
|
||||
}
|
||||
|
||||
void MaskEffect::onRender(SkCanvas* canvas) const {
|
||||
|
@ -16,13 +16,13 @@ Matrix::Matrix(const SkMatrix& m, sk_sp<Matrix> parent)
|
||||
, fParent(std::move(parent))
|
||||
, fLocalMatrix(m) {
|
||||
if (fParent) {
|
||||
fParent->addInvalReceiver(this);
|
||||
this->observeInval(fParent);
|
||||
}
|
||||
}
|
||||
|
||||
Matrix::~Matrix() {
|
||||
if (fParent) {
|
||||
fParent->removeInvalReceiver(this);
|
||||
this->unobserveInval(fParent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,11 +40,11 @@ SkRect Matrix::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
|
||||
Transform::Transform(sk_sp<RenderNode> child, sk_sp<Matrix> matrix)
|
||||
: INHERITED(std::move(child))
|
||||
, fMatrix(std::move(matrix)) {
|
||||
fMatrix->addInvalReceiver(this);
|
||||
this->observeInval(fMatrix);
|
||||
}
|
||||
|
||||
Transform::~Transform() {
|
||||
fMatrix->removeInvalReceiver(this);
|
||||
this->unobserveInval(fMatrix);
|
||||
}
|
||||
|
||||
void Transform::onRender(SkCanvas* canvas) const {
|
||||
|
@ -14,13 +14,13 @@ namespace sksg {
|
||||
GeometryTransform::GeometryTransform(sk_sp<GeometryNode> child, sk_sp<Matrix> matrix)
|
||||
: fChild(std::move(child))
|
||||
, fMatrix(std::move(matrix)) {
|
||||
fChild->addInvalReceiver(this);
|
||||
fMatrix->addInvalReceiver(this);
|
||||
this->observeInval(fChild);
|
||||
this->observeInval(fMatrix);
|
||||
}
|
||||
|
||||
GeometryTransform::~GeometryTransform() {
|
||||
fChild->removeInvalReceiver(this);
|
||||
fMatrix->removeInvalReceiver(this);
|
||||
this->unobserveInval(fChild);
|
||||
this->unobserveInval(fMatrix);
|
||||
}
|
||||
|
||||
SkRect GeometryTransform::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
|
||||
|
@ -16,13 +16,13 @@ Merge::Merge(std::vector<sk_sp<GeometryNode>>&& geos, Mode mode)
|
||||
: fGeos(std::move(geos))
|
||||
, fMode(mode) {
|
||||
for (const auto& geo : fGeos) {
|
||||
geo->addInvalReceiver(this);
|
||||
this->observeInval(geo);
|
||||
}
|
||||
}
|
||||
|
||||
Merge::~Merge() {
|
||||
for (const auto& geo : fGeos) {
|
||||
geo->removeInvalReceiver(this);
|
||||
this->unobserveInval(geo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,11 +15,11 @@ namespace sksg {
|
||||
|
||||
TrimEffect::TrimEffect(sk_sp<GeometryNode> child)
|
||||
: fChild(std::move(child)) {
|
||||
fChild->addInvalReceiver(this);
|
||||
this->observeInval(fChild);
|
||||
}
|
||||
|
||||
TrimEffect::~TrimEffect() {
|
||||
fChild->removeInvalReceiver(this);
|
||||
this->unobserveInval(fChild);
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
Loading…
Reference in New Issue
Block a user