ef26fcb13f
Image filters cannot let descendent damage pass through, as they may transform their inputs arbitrarily. Introduce the notion of "damage override" SG nodes (nodes which block descendent damage and replace it with their own), and update ImageFilterEffect to opt in for this behavior. Also make InvalidationController damage dispatch optional (such that we don't accumulate inval rects unnecessarily). TBR= Change-Id: Ie9f7d32ecdcc77dbe6ea009aed9ce269b3649a04 Reviewed-on: https://skia-review.googlesource.com/c/191005 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
122 lines
4.4 KiB
C++
122 lines
4.4 KiB
C++
/*
|
|
* Copyright 2017 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#ifndef SkSGNode_DEFINED
|
|
#define SkSGNode_DEFINED
|
|
|
|
#include "SkRect.h"
|
|
#include "SkRefCnt.h"
|
|
|
|
#include <vector>
|
|
|
|
class SkCanvas;
|
|
class SkMatrix;
|
|
|
|
namespace sksg {
|
|
|
|
class InvalidationController;
|
|
|
|
/**
|
|
* Base class for all scene graph nodes.
|
|
*
|
|
* Handles ingress edge management for the DAG (i.e. node -> "parent" node mapping),
|
|
* and invalidation.
|
|
*
|
|
* Note: egress edges are only implemented/supported in container subclasses
|
|
* (e.g. Group, Effect, Draw).
|
|
*/
|
|
class Node : public SkRefCnt {
|
|
public:
|
|
// Traverse the DAG and revalidate any dependant/invalidated nodes.
|
|
// Returns the bounding box for the DAG fragment.
|
|
const SkRect& revalidate(InvalidationController*, const SkMatrix&);
|
|
|
|
protected:
|
|
enum InvalTraits {
|
|
// Nodes with this trait never generate direct damage -- instead,
|
|
// the damage bubbles up to ancestors.
|
|
kBubbleDamage_Trait = 1 << 0,
|
|
|
|
// Nodes with this trait obscure the descendants' damage and always override it.
|
|
kOverrideDamage_Trait = 1 << 1,
|
|
};
|
|
|
|
explicit Node(uint32_t invalTraits);
|
|
~Node() override;
|
|
|
|
const SkRect& bounds() const {
|
|
SkASSERT(!this->hasInval());
|
|
return fBounds;
|
|
}
|
|
|
|
// Tag this node for invalidation and optional damage.
|
|
void invalidate(bool damage = true);
|
|
bool hasInval() const { return fFlags & kInvalidated_Flag; }
|
|
|
|
// 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;
|
|
|
|
// 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
|
|
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)
|
|
};
|
|
|
|
template <typename Func>
|
|
void forEachInvalObserver(Func&&) const;
|
|
|
|
class ScopedFlag;
|
|
|
|
union {
|
|
Node* fInvalObserver;
|
|
std::vector<Node*>* fInvalObserverArray;
|
|
};
|
|
SkRect fBounds;
|
|
const uint32_t fInvalTraits : 16;
|
|
uint32_t fFlags : 16;
|
|
|
|
typedef SkRefCnt INHERITED;
|
|
};
|
|
|
|
// Helper for defining attribute getters/setters in subclasses.
|
|
#define SG_ATTRIBUTE(attr_name, attr_type, attr_container) \
|
|
const attr_type& get##attr_name() const { return attr_container; } \
|
|
void set##attr_name(const attr_type& v) { \
|
|
if (attr_container == v) return; \
|
|
attr_container = v; \
|
|
this->invalidate(); \
|
|
} \
|
|
void set##attr_name(attr_type&& v) { \
|
|
if (attr_container == v) return; \
|
|
attr_container = std::move(v); \
|
|
this->invalidate(); \
|
|
}
|
|
|
|
#define SG_MAPPED_ATTRIBUTE(attr_name, attr_type, attr_container) \
|
|
attr_type get##attr_name() const { return attr_container.get##attr_name(); } \
|
|
void set##attr_name(const attr_type& v) { \
|
|
if (attr_container.get##attr_name() == v) return; \
|
|
attr_container.set##attr_name(v); \
|
|
this->invalidate(); \
|
|
} \
|
|
void set##attr_name(attr_type&& v) { \
|
|
if (attr_container.get##attr_name() == v) return; \
|
|
attr_container.set##attr_name(std::move(v)); \
|
|
this->invalidate(); \
|
|
}
|
|
|
|
} // namespace sksg
|
|
|
|
#endif // SkSGNode_DEFINED
|