Move GrClipStack to skgpu::v1 namespace

Bug: skia:11837
Change-Id: I42dfaf795ec6afe9d648b0715457a3a38ef8c7a4
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/439943
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2021-08-17 11:50:20 -04:00 committed by SkCQ
parent 1e45dcd12f
commit 74b943237e
7 changed files with 399 additions and 312 deletions

View File

@ -494,8 +494,6 @@ skia_skgpu_v1_sources = [
"$_src/gpu/GrAuditTrail.cpp", "$_src/gpu/GrAuditTrail.cpp",
"$_src/gpu/GrBlurUtils.cpp", "$_src/gpu/GrBlurUtils.cpp",
"$_src/gpu/GrBlurUtils.h", "$_src/gpu/GrBlurUtils.h",
"$_src/gpu/GrClipStack.cpp",
"$_src/gpu/GrClipStack.h",
"$_src/gpu/GrDrawOpTest.cpp", "$_src/gpu/GrDrawOpTest.cpp",
"$_src/gpu/GrDrawOpTest.h", "$_src/gpu/GrDrawOpTest.h",
"$_src/gpu/GrOpsTask.cpp", "$_src/gpu/GrOpsTask.cpp",
@ -589,6 +587,8 @@ skia_skgpu_v1_sources = [
"$_src/gpu/tessellate/GrTessellationPathRenderer.cpp", "$_src/gpu/tessellate/GrTessellationPathRenderer.cpp",
# v1 # v1
"$_src/gpu/v1/ClipStack.cpp",
"$_src/gpu/v1/ClipStack.h",
"$_src/gpu/v1/Device.cpp", "$_src/gpu/v1/Device.cpp",
"$_src/gpu/v1/Device_drawTexture.cpp", "$_src/gpu/v1/Device_drawTexture.cpp",
"$_src/gpu/v1/Device_v1.h", "$_src/gpu/v1/Device_v1.h",

View File

@ -5,7 +5,7 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "src/gpu/GrClipStack.h" #include "src/gpu/v1/ClipStack.h"
#include "include/core/SkMatrix.h" #include "include/core/SkMatrix.h"
#include "src/core/SkMatrixProvider.h" #include "src/core/SkMatrixProvider.h"
@ -44,7 +44,7 @@ enum class ClipGeometry {
// A and B can be Element, SaveRecord, or Draw. Supported combinations are, order not mattering, // A and B can be Element, SaveRecord, or Draw. Supported combinations are, order not mattering,
// (Element, Element), (Element, SaveRecord), (Element, Draw), and (SaveRecord, Draw). // (Element, Element), (Element, SaveRecord), (Element, Draw), and (SaveRecord, Draw).
template<typename A, typename B> template<typename A, typename B>
static ClipGeometry get_clip_geometry(const A& a, const B& b) { ClipGeometry get_clip_geometry(const A& a, const B& b) {
// NOTE: SkIRect::Intersects() returns false when two rectangles touch at an edge (so the result // NOTE: SkIRect::Intersects() returns false when two rectangles touch at an edge (so the result
// is empty). This behavior is desired for the following clip effect policies. // is empty). This behavior is desired for the following clip effect policies.
if (a.op() == SkClipOp::kIntersect) { if (a.op() == SkClipOp::kIntersect) {
@ -117,8 +117,7 @@ static ClipGeometry get_clip_geometry(const A& a, const B& b) {
// Automatically takes into account if the anti-aliasing policies differ. When the policies match, // Automatically takes into account if the anti-aliasing policies differ. When the policies match,
// we assume that coverage AA or GPU's non-AA rasterization will apply to A and B equivalently, so // we assume that coverage AA or GPU's non-AA rasterization will apply to A and B equivalently, so
// we can compare the original shapes. When the modes are mixed, we outset B in device space first. // we can compare the original shapes. When the modes are mixed, we outset B in device space first.
static bool shape_contains_rect( bool shape_contains_rect(const GrShape& a, const SkMatrix& aToDevice, const SkMatrix& deviceToA,
const GrShape& a, const SkMatrix& aToDevice, const SkMatrix& deviceToA,
const SkRect& b, const SkMatrix& bToDevice, bool mixedAAMode) { const SkRect& b, const SkMatrix& bToDevice, bool mixedAAMode) {
if (!a.convex()) { if (!a.convex()) {
return false; return false;
@ -163,7 +162,7 @@ static bool shape_contains_rect(
return true; return true;
} }
static SkIRect subtract(const SkIRect& a, const SkIRect& b, bool exact) { SkIRect subtract(const SkIRect& a, const SkIRect& b, bool exact) {
SkIRect diff; SkIRect diff;
if (SkRectPriv::Subtract(a, b, &diff) || !exact) { if (SkRectPriv::Subtract(a, b, &diff) || !exact) {
// Either A-B is exactly the rectangle stored in diff, or we don't need an exact answer // Either A-B is exactly the rectangle stored in diff, or we don't need an exact answer
@ -175,7 +174,7 @@ static SkIRect subtract(const SkIRect& a, const SkIRect& b, bool exact) {
} }
} }
static GrClipEdgeType get_clip_edge_type(SkClipOp op, GrAA aa) { GrClipEdgeType get_clip_edge_type(SkClipOp op, GrAA aa) {
if (op == SkClipOp::kIntersect) { if (op == SkClipOp::kIntersect) {
return aa == GrAA::kYes ? GrClipEdgeType::kFillAA : GrClipEdgeType::kFillBW; return aa == GrAA::kYes ? GrClipEdgeType::kFillAA : GrClipEdgeType::kFillBW;
} else { } else {
@ -187,7 +186,7 @@ static uint32_t kInvalidGenID = 0;
static uint32_t kEmptyGenID = 1; static uint32_t kEmptyGenID = 1;
static uint32_t kWideOpenGenID = 2; static uint32_t kWideOpenGenID = 2;
static uint32_t next_gen_id() { uint32_t next_gen_id() {
// 0-2 are reserved for invalid, empty & wide-open // 0-2 are reserved for invalid, empty & wide-open
static const uint32_t kFirstUnreservedGenID = 3; static const uint32_t kFirstUnreservedGenID = 3;
static std::atomic<uint32_t> nextID{kFirstUnreservedGenID}; static std::atomic<uint32_t> nextID{kFirstUnreservedGenID};
@ -209,7 +208,7 @@ static uint32_t next_gen_id() {
// in parallel. // in parallel.
static constexpr GrSurfaceOrigin kMaskOrigin = kTopLeft_GrSurfaceOrigin; static constexpr GrSurfaceOrigin kMaskOrigin = kTopLeft_GrSurfaceOrigin;
static GrFPResult analytic_clip_fp(const GrClipStack::Element& e, GrFPResult analytic_clip_fp(const skgpu::v1::ClipStack::Element& e,
const GrShaderCaps& caps, const GrShaderCaps& caps,
std::unique_ptr<GrFragmentProcessor> fp) { std::unique_ptr<GrFragmentProcessor> fp) {
// All analytic clip shape FPs need to be in device space // All analytic clip shape FPs need to be in device space
@ -237,11 +236,11 @@ static GrFPResult analytic_clip_fp(const GrClipStack::Element& e,
// TODO: Currently this only works with tessellation because the tessellation path renderer owns and // TODO: Currently this only works with tessellation because the tessellation path renderer owns and
// manages the atlas. The high-level concept could be generalized to support any path renderer going // manages the atlas. The high-level concept could be generalized to support any path renderer going
// into a shared atlas. // into a shared atlas.
static GrFPResult clip_atlas_fp(const skgpu::v1::SurfaceDrawContext* sdc, GrFPResult clip_atlas_fp(const skgpu::v1::SurfaceDrawContext* sdc,
const GrOp* opBeingClipped, const GrOp* opBeingClipped,
GrAtlasPathRenderer* atlasPathRenderer, GrAtlasPathRenderer* atlasPathRenderer,
const SkIRect& scissorBounds, const SkIRect& scissorBounds,
const GrClipStack::Element& e, const skgpu::v1::ClipStack::Element& e,
std::unique_ptr<GrFragmentProcessor> inputFP) { std::unique_ptr<GrFragmentProcessor> inputFP) {
if (e.fAA != GrAA::kYes) { if (e.fAA != GrAA::kYes) {
return GrFPFailure(std::move(inputFP)); return GrFPFailure(std::move(inputFP));
@ -257,7 +256,9 @@ static GrFPResult clip_atlas_fp(const skgpu::v1::SurfaceDrawContext* sdc,
scissorBounds, e.fLocalToDevice, path); scissorBounds, e.fLocalToDevice, path);
} }
static void draw_to_sw_mask(GrSWMaskHelper* helper, const GrClipStack::Element& e, bool clearMask) { void draw_to_sw_mask(GrSWMaskHelper* helper,
const skgpu::v1::ClipStack::Element& e,
bool clearMask) {
// If the first element to draw is an intersect, we clear to 0 and will draw it directly with // If the first element to draw is an intersect, we clear to 0 and will draw it directly with
// coverage 1 (subsequent intersect elements will be inverse-filled and draw 0 outside). // coverage 1 (subsequent intersect elements will be inverse-filled and draw 0 outside).
// If the first element to draw is a difference, we clear to 1, and in all cases we draw the // If the first element to draw is a difference, we clear to 1, and in all cases we draw the
@ -303,8 +304,10 @@ static void draw_to_sw_mask(GrSWMaskHelper* helper, const GrClipStack::Element&
} }
} }
static GrSurfaceProxyView render_sw_mask(GrRecordingContext* context, const SkIRect& bounds, GrSurfaceProxyView render_sw_mask(GrRecordingContext* context,
const GrClipStack::Element** elements, int count) { const SkIRect& bounds,
const skgpu::v1::ClipStack::Element** elements,
int count) {
SkASSERT(count > 0); SkASSERT(count > 0);
SkTaskGroup* taskGroup = nullptr; SkTaskGroup* taskGroup = nullptr;
@ -327,7 +330,7 @@ static GrSurfaceProxyView render_sw_mask(GrRecordingContext* context, const SkIR
// Since this will be rendered on another thread, make a copy of the elements in case // Since this will be rendered on another thread, make a copy of the elements in case
// the clip stack is modified on the main thread // the clip stack is modified on the main thread
using Uploader = GrTDeferredProxyUploader<SkTArray<GrClipStack::Element>>; using Uploader = GrTDeferredProxyUploader<SkTArray<skgpu::v1::ClipStack::Element>>;
std::unique_ptr<Uploader> uploader = std::make_unique<Uploader>(count); std::unique_ptr<Uploader> uploader = std::make_unique<Uploader>(count);
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
uploader->data().push_back(*(elements[i])); uploader->data().push_back(*(elements[i]));
@ -365,11 +368,11 @@ static GrSurfaceProxyView render_sw_mask(GrRecordingContext* context, const SkIR
} }
} }
static void render_stencil_mask(GrRecordingContext* rContext, void render_stencil_mask(GrRecordingContext* rContext,
skgpu::v1::SurfaceDrawContext* sdc, skgpu::v1::SurfaceDrawContext* sdc,
uint32_t genID, uint32_t genID,
const SkIRect& bounds, const SkIRect& bounds,
const GrClipStack::Element** elements, const skgpu::v1::ClipStack::Element** elements,
int count, int count,
GrAppliedClip* out) { GrAppliedClip* out) {
GrStencilMaskHelper helper(rContext, sdc); GrStencilMaskHelper helper(rContext, sdc);
@ -378,7 +381,7 @@ static void render_stencil_mask(GrRecordingContext* rContext,
bool startInside = elements[0]->fOp == SkClipOp::kDifference; bool startInside = elements[0]->fOp == SkClipOp::kDifference;
helper.clear(startInside); helper.clear(startInside);
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
const GrClipStack::Element& e = *(elements[i]); const skgpu::v1::ClipStack::Element& e = *(elements[i]);
SkRegion::Op op; SkRegion::Op op;
if (e.fOp == SkClipOp::kIntersect) { if (e.fOp == SkClipOp::kIntersect) {
op = (i == 0) ? SkRegion::kReplace_Op : SkRegion::kIntersect_Op; op = (i == 0) ? SkRegion::kReplace_Op : SkRegion::kIntersect_Op;
@ -394,7 +397,9 @@ static void render_stencil_mask(GrRecordingContext* rContext,
} // anonymous namespace } // anonymous namespace
class GrClipStack::Draw { namespace skgpu::v1 {
class ClipStack::Draw {
public: public:
Draw(const SkRect& drawBounds, GrAA aa) Draw(const SkRect& drawBounds, GrAA aa)
: fBounds(GrClip::GetPixelIBounds(drawBounds, aa, BoundsType::kExterior)) : fBounds(GrClip::GetPixelIBounds(drawBounds, aa, BoundsType::kExterior))
@ -428,9 +433,9 @@ private:
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GrClipStack::Element // ClipStack::Element
GrClipStack::RawElement::RawElement(const SkMatrix& localToDevice, const GrShape& shape, ClipStack::RawElement::RawElement(const SkMatrix& localToDevice, const GrShape& shape,
GrAA aa, SkClipOp op) GrAA aa, SkClipOp op)
: Element{shape, localToDevice, op, aa} : Element{shape, localToDevice, op, aa}
, fInnerBounds(SkIRect::MakeEmpty()) , fInnerBounds(SkIRect::MakeEmpty())
@ -443,18 +448,18 @@ GrClipStack::RawElement::RawElement(const SkMatrix& localToDevice, const GrShape
} }
} }
void GrClipStack::RawElement::markInvalid(const SaveRecord& current) { void ClipStack::RawElement::markInvalid(const SaveRecord& current) {
SkASSERT(!this->isInvalid()); SkASSERT(!this->isInvalid());
fInvalidatedByIndex = current.firstActiveElementIndex(); fInvalidatedByIndex = current.firstActiveElementIndex();
} }
void GrClipStack::RawElement::restoreValid(const SaveRecord& current) { void ClipStack::RawElement::restoreValid(const SaveRecord& current) {
if (current.firstActiveElementIndex() < fInvalidatedByIndex) { if (current.firstActiveElementIndex() < fInvalidatedByIndex) {
fInvalidatedByIndex = -1; fInvalidatedByIndex = -1;
} }
} }
bool GrClipStack::RawElement::contains(const Draw& d) const { bool ClipStack::RawElement::contains(const Draw& d) const {
if (fInnerBounds.contains(d.outerBounds())) { if (fInnerBounds.contains(d.outerBounds())) {
return true; return true;
} else { } else {
@ -466,7 +471,7 @@ bool GrClipStack::RawElement::contains(const Draw& d) const {
} }
} }
bool GrClipStack::RawElement::contains(const SaveRecord& s) const { bool ClipStack::RawElement::contains(const SaveRecord& s) const {
if (fInnerBounds.contains(s.outerBounds())) { if (fInnerBounds.contains(s.outerBounds())) {
return true; return true;
} else { } else {
@ -477,7 +482,7 @@ bool GrClipStack::RawElement::contains(const SaveRecord& s) const {
} }
} }
bool GrClipStack::RawElement::contains(const RawElement& e) const { bool ClipStack::RawElement::contains(const RawElement& e) const {
// This is similar to how RawElement checks containment for a Draw, except that both the tester // This is similar to how RawElement checks containment for a Draw, except that both the tester
// and testee have a transform that needs to be considered. // and testee have a transform that needs to be considered.
if (fInnerBounds.contains(e.fOuterBounds)) { if (fInnerBounds.contains(e.fOuterBounds)) {
@ -505,7 +510,7 @@ bool GrClipStack::RawElement::contains(const RawElement& e) const {
} }
void GrClipStack::RawElement::simplify(const SkIRect& deviceBounds, bool forceAA) { void ClipStack::RawElement::simplify(const SkIRect& deviceBounds, bool forceAA) {
// Make sure the shape is not inverted. An inverted shape is equivalent to a non-inverted shape // Make sure the shape is not inverted. An inverted shape is equivalent to a non-inverted shape
// with the clip op toggled. // with the clip op toggled.
if (fShape.inverted()) { if (fShape.inverted()) {
@ -590,7 +595,7 @@ void GrClipStack::RawElement::simplify(const SkIRect& deviceBounds, bool forceAA
SkASSERT(fShape.isEmpty() || fInnerBounds.isEmpty() || fOuterBounds.contains(fInnerBounds)); SkASSERT(fShape.isEmpty() || fInnerBounds.isEmpty() || fOuterBounds.contains(fInnerBounds));
} }
bool GrClipStack::RawElement::combine(const RawElement& other, const SaveRecord& current) { bool ClipStack::RawElement::combine(const RawElement& other, const SaveRecord& current) {
// To reduce the number of possibilities, only consider intersect+intersect. Difference and // To reduce the number of possibilities, only consider intersect+intersect. Difference and
// mixed op cases could be analyzed to simplify one of the shapes, but that is a rare // mixed op cases could be analyzed to simplify one of the shapes, but that is a rare
// occurrence and the math is much more complicated. // occurrence and the math is much more complicated.
@ -669,7 +674,7 @@ bool GrClipStack::RawElement::combine(const RawElement& other, const SaveRecord&
} }
} }
void GrClipStack::RawElement::updateForElement(RawElement* added, const SaveRecord& current) { void ClipStack::RawElement::updateForElement(RawElement* added, const SaveRecord& current) {
if (this->isInvalid()) { if (this->isInvalid()) {
// Already doesn't do anything, so skip this element // Already doesn't do anything, so skip this element
return; return;
@ -704,7 +709,7 @@ void GrClipStack::RawElement::updateForElement(RawElement* added, const SaveReco
} }
} }
GrClipStack::ClipState GrClipStack::RawElement::clipType() const { ClipStack::ClipState ClipStack::RawElement::clipType() const {
// Map from the internal shape kind to the clip state enum // Map from the internal shape kind to the clip state enum
switch (fShape.type()) { switch (fShape.type()) {
case GrShape::Type::kEmpty: case GrShape::Type::kEmpty:
@ -732,9 +737,9 @@ GrClipStack::ClipState GrClipStack::RawElement::clipType() const {
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GrClipStack::Mask // ClipStack::Mask
GrClipStack::Mask::Mask(const SaveRecord& current, const SkIRect& drawBounds) ClipStack::Mask::Mask(const SaveRecord& current, const SkIRect& drawBounds)
: fBounds(drawBounds) : fBounds(drawBounds)
, fGenID(current.genID()) { , fGenID(current.genID()) {
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
@ -753,14 +758,14 @@ GrClipStack::Mask::Mask(const SaveRecord& current, const SkIRect& drawBounds)
SkDEBUGCODE(fOwner = &current;) SkDEBUGCODE(fOwner = &current;)
} }
bool GrClipStack::Mask::appliesToDraw(const SaveRecord& current, const SkIRect& drawBounds) const { bool ClipStack::Mask::appliesToDraw(const SaveRecord& current, const SkIRect& drawBounds) const {
// For the same save record, a larger mask will have the same or more elements // For the same save record, a larger mask will have the same or more elements
// baked into it, so it can be reused to clip the smaller draw. // baked into it, so it can be reused to clip the smaller draw.
SkASSERT(fGenID != current.genID() || &current == fOwner); SkASSERT(fGenID != current.genID() || &current == fOwner);
return fGenID == current.genID() && fBounds.contains(drawBounds); return fGenID == current.genID() && fBounds.contains(drawBounds);
} }
void GrClipStack::Mask::invalidate(GrProxyProvider* proxyProvider) { void ClipStack::Mask::invalidate(GrProxyProvider* proxyProvider) {
SkASSERT(proxyProvider); SkASSERT(proxyProvider);
SkASSERT(fKey.isValid()); // Should only be invalidated once SkASSERT(fKey.isValid()); // Should only be invalidated once
proxyProvider->processInvalidUniqueKey( proxyProvider->processInvalidUniqueKey(
@ -769,9 +774,9 @@ void GrClipStack::Mask::invalidate(GrProxyProvider* proxyProvider) {
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GrClipStack::SaveRecord // ClipStack::SaveRecord
GrClipStack::SaveRecord::SaveRecord(const SkIRect& deviceBounds) ClipStack::SaveRecord::SaveRecord(const SkIRect& deviceBounds)
: fInnerBounds(deviceBounds) : fInnerBounds(deviceBounds)
, fOuterBounds(deviceBounds) , fOuterBounds(deviceBounds)
, fShader(nullptr) , fShader(nullptr)
@ -783,7 +788,7 @@ GrClipStack::SaveRecord::SaveRecord(const SkIRect& deviceBounds)
, fState(ClipState::kWideOpen) , fState(ClipState::kWideOpen)
, fGenID(kInvalidGenID) {} , fGenID(kInvalidGenID) {}
GrClipStack::SaveRecord::SaveRecord(const SaveRecord& prior, ClipStack::SaveRecord::SaveRecord(const SaveRecord& prior,
int startingMaskIndex, int startingMaskIndex,
int startingElementIndex) int startingElementIndex)
: fInnerBounds(prior.fInnerBounds) : fInnerBounds(prior.fInnerBounds)
@ -803,7 +808,7 @@ GrClipStack::SaveRecord::SaveRecord(const SaveRecord& prior,
SkASSERT(startingElementIndex >= prior.fStartingElementIndex); SkASSERT(startingElementIndex >= prior.fStartingElementIndex);
} }
uint32_t GrClipStack::SaveRecord::genID() const { uint32_t ClipStack::SaveRecord::genID() const {
if (fState == ClipState::kEmpty) { if (fState == ClipState::kEmpty) {
return kEmptyGenID; return kEmptyGenID;
} else if (fState == ClipState::kWideOpen) { } else if (fState == ClipState::kWideOpen) {
@ -816,7 +821,7 @@ uint32_t GrClipStack::SaveRecord::genID() const {
} }
} }
GrClipStack::ClipState GrClipStack::SaveRecord::state() const { ClipStack::ClipState ClipStack::SaveRecord::state() const {
if (fShader && fState != ClipState::kEmpty) { if (fShader && fState != ClipState::kEmpty) {
return ClipState::kComplex; return ClipState::kComplex;
} else { } else {
@ -824,21 +829,21 @@ GrClipStack::ClipState GrClipStack::SaveRecord::state() const {
} }
} }
bool GrClipStack::SaveRecord::contains(const GrClipStack::Draw& draw) const { bool ClipStack::SaveRecord::contains(const ClipStack::Draw& draw) const {
return fInnerBounds.contains(draw.outerBounds()); return fInnerBounds.contains(draw.outerBounds());
} }
bool GrClipStack::SaveRecord::contains(const GrClipStack::RawElement& element) const { bool ClipStack::SaveRecord::contains(const ClipStack::RawElement& element) const {
return fInnerBounds.contains(element.outerBounds()); return fInnerBounds.contains(element.outerBounds());
} }
void GrClipStack::SaveRecord::removeElements(RawElement::Stack* elements) { void ClipStack::SaveRecord::removeElements(RawElement::Stack* elements) {
while (elements->count() > fStartingElementIndex) { while (elements->count() > fStartingElementIndex) {
elements->pop_back(); elements->pop_back();
} }
} }
void GrClipStack::SaveRecord::restoreElements(RawElement::Stack* elements) { void ClipStack::SaveRecord::restoreElements(RawElement::Stack* elements) {
// Presumably this SaveRecord is the new top of the stack, and so it owns the elements // Presumably this SaveRecord is the new top of the stack, and so it owns the elements
// from its starting index to restoreCount - 1. Elements from the old save record have // from its starting index to restoreCount - 1. Elements from the old save record have
// been destroyed already, so their indices would have been >= restoreCount, and any // been destroyed already, so their indices would have been >= restoreCount, and any
@ -853,7 +858,7 @@ void GrClipStack::SaveRecord::restoreElements(RawElement::Stack* elements) {
} }
} }
void GrClipStack::SaveRecord::invalidateMasks(GrProxyProvider* proxyProvider, void ClipStack::SaveRecord::invalidateMasks(GrProxyProvider* proxyProvider,
Mask::Stack* masks) { Mask::Stack* masks) {
// Must explicitly invalidate the key before removing the mask object from the stack // Must explicitly invalidate the key before removing the mask object from the stack
while (masks->count() > fStartingMaskIndex) { while (masks->count() > fStartingMaskIndex) {
@ -864,7 +869,7 @@ void GrClipStack::SaveRecord::invalidateMasks(GrProxyProvider* proxyProvider,
SkASSERT(masks->empty() || masks->back().genID() != fGenID); SkASSERT(masks->empty() || masks->back().genID() != fGenID);
} }
void GrClipStack::SaveRecord::reset(const SkIRect& bounds) { void ClipStack::SaveRecord::reset(const SkIRect& bounds) {
SkASSERT(this->canBeUpdated()); SkASSERT(this->canBeUpdated());
fOldestValidIndex = fStartingElementIndex; fOldestValidIndex = fStartingElementIndex;
fOuterBounds = bounds; fOuterBounds = bounds;
@ -874,7 +879,7 @@ void GrClipStack::SaveRecord::reset(const SkIRect& bounds) {
fShader = nullptr; fShader = nullptr;
} }
void GrClipStack::SaveRecord::addShader(sk_sp<SkShader> shader) { void ClipStack::SaveRecord::addShader(sk_sp<SkShader> shader) {
SkASSERT(shader); SkASSERT(shader);
SkASSERT(this->canBeUpdated()); SkASSERT(this->canBeUpdated());
if (!fShader) { if (!fShader) {
@ -887,7 +892,7 @@ void GrClipStack::SaveRecord::addShader(sk_sp<SkShader> shader) {
} }
} }
bool GrClipStack::SaveRecord::addElement(RawElement&& toAdd, RawElement::Stack* elements) { bool ClipStack::SaveRecord::addElement(RawElement&& toAdd, RawElement::Stack* elements) {
// Validity check the element's state first; if the shape class isn't empty, the outer bounds // Validity check the element's state first; if the shape class isn't empty, the outer bounds
// shouldn't be empty; if the inner bounds are not empty, they must be contained in outer. // shouldn't be empty; if the inner bounds are not empty, they must be contained in outer.
SkASSERT((toAdd.shape().isEmpty() || !toAdd.outerBounds().isEmpty()) && SkASSERT((toAdd.shape().isEmpty() || !toAdd.outerBounds().isEmpty()) &&
@ -984,7 +989,7 @@ bool GrClipStack::SaveRecord::addElement(RawElement&& toAdd, RawElement::Stack*
return this->appendElement(std::move(toAdd), elements); return this->appendElement(std::move(toAdd), elements);
} }
bool GrClipStack::SaveRecord::appendElement(RawElement&& toAdd, RawElement::Stack* elements) { bool ClipStack::SaveRecord::appendElement(RawElement&& toAdd, RawElement::Stack* elements) {
// Update past elements to account for the new element // Update past elements to account for the new element
int i = elements->count() - 1; int i = elements->count() - 1;
@ -1072,12 +1077,12 @@ bool GrClipStack::SaveRecord::appendElement(RawElement&& toAdd, RawElement::Stac
elements->back() = std::move(toAdd); elements->back() = std::move(toAdd);
} }
// Changing this will prompt GrClipStack to invalidate any masks associated with this record. // Changing this will prompt ClipStack to invalidate any masks associated with this record.
fGenID = next_gen_id(); fGenID = next_gen_id();
return true; return true;
} }
void GrClipStack::SaveRecord::replaceWithElement(RawElement&& toAdd, RawElement::Stack* elements) { void ClipStack::SaveRecord::replaceWithElement(RawElement&& toAdd, RawElement::Stack* elements) {
// The aggregate state of the save record mirrors the element // The aggregate state of the save record mirrors the element
fInnerBounds = toAdd.innerBounds(); fInnerBounds = toAdd.innerBounds();
fOuterBounds = toAdd.outerBounds(); fOuterBounds = toAdd.outerBounds();
@ -1103,11 +1108,11 @@ void GrClipStack::SaveRecord::replaceWithElement(RawElement&& toAdd, RawElement:
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GrClipStack // ClipStack
// NOTE: Based on draw calls in all GMs, SKPs, and SVGs as of 08/20, 98% use a clip stack with // NOTE: Based on draw calls in all GMs, SKPs, and SVGs as of 08/20, 98% use a clip stack with
// one Element and up to two SaveRecords, thus the inline size for RawElement::Stack and // one Element and up to two SaveRecords, thus the inline size for RawElement::Stack and
// SaveRecord::Stack (this conveniently keeps the size of GrClipStack manageable). The max // SaveRecord::Stack (this conveniently keeps the size of ClipStack manageable). The max
// encountered element stack depth was 5 and the max save depth was 6. Using an increment of 8 for // encountered element stack depth was 5 and the max save depth was 6. Using an increment of 8 for
// these stacks means that clip management will incur a single allocation for the remaining 2% // these stacks means that clip management will incur a single allocation for the remaining 2%
// of the draws, with extra head room for more complex clips encountered in the wild. // of the draws, with extra head room for more complex clips encountered in the wild.
@ -1127,7 +1132,7 @@ static constexpr int kMaxAnalyticFPs = 4;
// across our set of GMs, SKPs, and SVGs used for testing. // across our set of GMs, SKPs, and SVGs used for testing.
static constexpr int kNumStackMasks = 4; static constexpr int kNumStackMasks = 4;
GrClipStack::GrClipStack(const SkIRect& deviceBounds, const SkMatrixProvider* matrixProvider, ClipStack::ClipStack(const SkIRect& deviceBounds, const SkMatrixProvider* matrixProvider,
bool forceAA) bool forceAA)
: fElements(kElementStackIncrement) : fElements(kElementStackIncrement)
, fSaves(kSaveStackIncrement) , fSaves(kSaveStackIncrement)
@ -1140,7 +1145,7 @@ GrClipStack::GrClipStack(const SkIRect& deviceBounds, const SkMatrixProvider* ma
fSaves.emplace_back(deviceBounds); fSaves.emplace_back(deviceBounds);
} }
GrClipStack::~GrClipStack() { ClipStack::~ClipStack() {
// Invalidate all mask keys that remain. Since we're tearing the clip stack down, we don't need // Invalidate all mask keys that remain. Since we're tearing the clip stack down, we don't need
// to go through SaveRecord. // to go through SaveRecord.
SkASSERT(fProxyProvider || fMasks.empty()); SkASSERT(fProxyProvider || fMasks.empty());
@ -1151,12 +1156,12 @@ GrClipStack::~GrClipStack() {
} }
} }
void GrClipStack::save() { void ClipStack::save() {
SkASSERT(!fSaves.empty()); SkASSERT(!fSaves.empty());
fSaves.back().pushSave(); fSaves.back().pushSave();
} }
void GrClipStack::restore() { void ClipStack::restore() {
SkASSERT(!fSaves.empty()); SkASSERT(!fSaves.empty());
SaveRecord& current = fSaves.back(); SaveRecord& current = fSaves.back();
if (current.popSave()) { if (current.popSave()) {
@ -1176,7 +1181,7 @@ void GrClipStack::restore() {
fSaves.back().restoreElements(&fElements); fSaves.back().restoreElements(&fElements);
} }
SkIRect GrClipStack::getConservativeBounds() const { SkIRect ClipStack::getConservativeBounds() const {
const SaveRecord& current = this->currentSaveRecord(); const SaveRecord& current = this->currentSaveRecord();
if (current.state() == ClipState::kEmpty) { if (current.state() == ClipState::kEmpty) {
return SkIRect::MakeEmpty(); return SkIRect::MakeEmpty();
@ -1194,7 +1199,7 @@ SkIRect GrClipStack::getConservativeBounds() const {
} }
} }
GrClip::PreClipResult GrClipStack::preApply(const SkRect& bounds, GrAA aa) const { GrClip::PreClipResult ClipStack::preApply(const SkRect& bounds, GrAA aa) const {
Draw draw(bounds, fForceAA ? GrAA::kYes : aa); Draw draw(bounds, fForceAA ? GrAA::kYes : aa);
if (!draw.applyDeviceBounds(fDeviceBounds)) { if (!draw.applyDeviceBounds(fDeviceBounds)) {
return GrClip::Effect::kClippedOut; return GrClip::Effect::kClippedOut;
@ -1248,8 +1253,8 @@ GrClip::PreClipResult GrClipStack::preApply(const SkRect& bounds, GrAA aa) const
SkUNREACHABLE; SkUNREACHABLE;
} }
GrClip::Effect GrClipStack::apply(GrRecordingContext* rContext, GrClip::Effect ClipStack::apply(GrRecordingContext* rContext,
skgpu::v1::SurfaceDrawContext* sdc, SurfaceDrawContext* sdc,
GrDrawOp* op, GrDrawOp* op,
GrAAType aa, GrAAType aa,
GrAppliedClip* out, GrAppliedClip* out,
@ -1497,7 +1502,7 @@ GrClip::Effect GrClipStack::apply(GrRecordingContext* rContext,
return Effect::kClipped; return Effect::kClipped;
} }
GrClipStack::SaveRecord& GrClipStack::writableSaveRecord(bool* wasDeferred) { ClipStack::SaveRecord& ClipStack::writableSaveRecord(bool* wasDeferred) {
SaveRecord& current = fSaves.back(); SaveRecord& current = fSaves.back();
if (current.canBeUpdated()) { if (current.canBeUpdated()) {
// Current record is still open, so it can be modified directly // Current record is still open, so it can be modified directly
@ -1511,7 +1516,7 @@ GrClipStack::SaveRecord& GrClipStack::writableSaveRecord(bool* wasDeferred) {
} }
} }
void GrClipStack::clipShader(sk_sp<SkShader> shader) { void ClipStack::clipShader(sk_sp<SkShader> shader) {
// Shaders can't bring additional coverage // Shaders can't bring additional coverage
if (this->currentSaveRecord().state() == ClipState::kEmpty) { if (this->currentSaveRecord().state() == ClipState::kEmpty) {
return; return;
@ -1522,7 +1527,7 @@ void GrClipStack::clipShader(sk_sp<SkShader> shader) {
// Masks and geometry elements are not invalidated by updating the clip shader // Masks and geometry elements are not invalidated by updating the clip shader
} }
void GrClipStack::replaceClip(const SkIRect& rect) { void ClipStack::replaceClip(const SkIRect& rect) {
bool wasDeferred; bool wasDeferred;
SaveRecord& save = this->writableSaveRecord(&wasDeferred); SaveRecord& save = this->writableSaveRecord(&wasDeferred);
@ -1537,7 +1542,7 @@ void GrClipStack::replaceClip(const SkIRect& rect) {
} }
} }
void GrClipStack::clip(RawElement&& element) { void ClipStack::clip(RawElement&& element) {
if (this->currentSaveRecord().state() == ClipState::kEmpty) { if (this->currentSaveRecord().state() == ClipState::kEmpty) {
return; return;
} }
@ -1585,7 +1590,7 @@ void GrClipStack::clip(RawElement&& element) {
} }
} }
GrFPResult GrClipStack::GetSWMaskFP(GrRecordingContext* context, Mask::Stack* masks, GrFPResult ClipStack::GetSWMaskFP(GrRecordingContext* context, Mask::Stack* masks,
const SaveRecord& current, const SkIRect& bounds, const SaveRecord& current, const SkIRect& bounds,
const Element** elements, int count, const Element** elements, int count,
std::unique_ptr<GrFragmentProcessor> clipFP) { std::unique_ptr<GrFragmentProcessor> clipFP) {
@ -1643,3 +1648,5 @@ GrFPResult GrClipStack::GetSWMaskFP(GrRecordingContext* context, Mask::Stack* ma
fp = GrBlendFragmentProcessor::Make(std::move(fp), std::move(clipFP), SkBlendMode::kDstIn); fp = GrBlendFragmentProcessor::Make(std::move(fp), std::move(clipFP), SkBlendMode::kDstIn);
return GrFPSuccess(std::move(fp)); return GrFPSuccess(std::move(fp));
} }
} // namespace skgpu::v1

View File

@ -4,9 +4,9 @@
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef GrClipStack_DEFINED
#define GrClipStack_DEFINED #ifndef ClipStack_DEFINED
#define ClipStack_DEFINED
#include "include/core/SkClipOp.h" #include "include/core/SkClipOp.h"
#include "include/core/SkMatrix.h" #include "include/core/SkMatrix.h"
@ -24,7 +24,9 @@ namespace skgpu { namespace v1 { class SurfaceDrawContext; }}
class GrSWMaskHelper; class GrSWMaskHelper;
class SkMatrixProvider; class SkMatrixProvider;
class GrClipStack final : public GrClip { namespace skgpu::v1 {
class ClipStack final : public GrClip {
public: public:
enum class ClipState : uint8_t { enum class ClipState : uint8_t {
kEmpty, kWideOpen, kDeviceRect, kDeviceRRect, kComplex kEmpty, kWideOpen, kDeviceRect, kDeviceRRect, kComplex
@ -38,13 +40,13 @@ public:
GrAA fAA; GrAA fAA;
}; };
// The SkMatrixProvider must outlive the GrClipStack. // The SkMatrixProvider must outlive the ClipStack.
GrClipStack(const SkIRect& deviceBounds, const SkMatrixProvider* matrixProvider, bool forceAA); ClipStack(const SkIRect& deviceBounds, const SkMatrixProvider* matrixProvider, bool forceAA);
~GrClipStack() override; ~ClipStack() override;
GrClipStack(const GrClipStack&) = delete; ClipStack(const ClipStack&) = delete;
GrClipStack& operator=(const GrClipStack&) = delete; ClipStack& operator=(const ClipStack&) = delete;
ClipState clipState() const { return this->currentSaveRecord().state(); } ClipState clipState() const { return this->currentSaveRecord().state(); }
@ -162,7 +164,7 @@ private:
// Represents an alpha mask with the rasterized coverage from elements in a draw query that // Represents an alpha mask with the rasterized coverage from elements in a draw query that
// could not be converted to analytic coverage FPs. // could not be converted to analytic coverage FPs.
// TODO: This is only required for SW masks. Stencil masks and atlas masks don't have resources // TODO: This is only required for SW masks. Stencil masks and atlas masks don't have resources
// owned by the GrClipStack. Once SW masks are no longer needed, this can go away. // owned by the ClipStack. Once SW masks are no longer needed, this can go away.
class Mask { class Mask {
public: public:
using Stack = GrTBlockList<Mask, 1>; using Stack = GrTBlockList<Mask, 1>;
@ -226,7 +228,7 @@ private:
SkASSERT(fDeferredSaveCount >= 0); SkASSERT(fDeferredSaveCount >= 0);
fDeferredSaveCount++; fDeferredSaveCount++;
} }
// Returns true if the record should stay alive. False means the GrClipStack must delete it // Returns true if the record should stay alive. False means the ClipStack must delete it
bool popSave() { bool popSave() {
fDeferredSaveCount--; fDeferredSaveCount--;
SkASSERT(fDeferredSaveCount >= -1); SkASSERT(fDeferredSaveCount >= -1);
@ -315,7 +317,7 @@ private:
}; };
// Clip element iteration // Clip element iteration
class GrClipStack::ElementIter { class ClipStack::ElementIter {
public: public:
bool operator!=(const ElementIter& o) const { bool operator!=(const ElementIter& o) const {
return o.fItem != fItem && o.fRemaining != fRemaining; return o.fItem != fItem && o.fRemaining != fRemaining;
@ -338,10 +340,10 @@ public:
RawElement::Stack::CRIter::Item fItem; RawElement::Stack::CRIter::Item fItem;
int fRemaining; int fRemaining;
friend class GrClipStack; friend class ClipStack;
}; };
GrClipStack::ElementIter GrClipStack::begin() const { ClipStack::ElementIter ClipStack::begin() const {
if (this->currentSaveRecord().state() == ClipState::kEmpty || if (this->currentSaveRecord().state() == ClipState::kEmpty ||
this->currentSaveRecord().state() == ClipState::kWideOpen) { this->currentSaveRecord().state() == ClipState::kWideOpen) {
// No visible clip elements when empty or wide open // No visible clip elements when empty or wide open
@ -351,8 +353,10 @@ GrClipStack::ElementIter GrClipStack::begin() const {
return ElementIter(fElements.ritems().begin(), count); return ElementIter(fElements.ritems().begin(), count);
} }
GrClipStack::ElementIter GrClipStack::end() const { ClipStack::ElementIter ClipStack::end() const {
return ElementIter(fElements.ritems().end(), 0); return ElementIter(fElements.ritems().end(), 0);
} }
#endif } // namespace skgpu::v1
#endif // ClipStack_DEFINED

View File

@ -333,7 +333,7 @@ void Device::onAsRgnClip(SkRegion* region) const {
// Assume wide open and then perform intersect/difference operations reducing the region // Assume wide open and then perform intersect/difference operations reducing the region
region->setRect(bounds); region->setRect(bounds);
const SkRegion deviceBounds(bounds); const SkRegion deviceBounds(bounds);
for (const GrClipStack::Element& e : fClip) { for (const ClipStack::Element& e : fClip) {
SkRegion tmp; SkRegion tmp;
if (e.fShape.isRect() && e.fLocalToDevice.isIdentity()) { if (e.fShape.isRect() && e.fLocalToDevice.isIdentity()) {
tmp.setRect(e.fShape.rect().roundOut()); tmp.setRect(e.fShape.rect().roundOut());
@ -349,7 +349,7 @@ void Device::onAsRgnClip(SkRegion* region) const {
} }
bool Device::onClipIsAA() const { bool Device::onClipIsAA() const {
for (const GrClipStack::Element& e : fClip) { for (const ClipStack::Element& e : fClip) {
if (e.fAA == GrAA::kYes) { if (e.fAA == GrAA::kYes) {
return true; return true;
} }
@ -359,11 +359,11 @@ bool Device::onClipIsAA() const {
} }
SkBaseDevice::ClipType Device::onGetClipType() const { SkBaseDevice::ClipType Device::onGetClipType() const {
GrClipStack::ClipState state = fClip.clipState(); ClipStack::ClipState state = fClip.clipState();
if (state == GrClipStack::ClipState::kEmpty) { if (state == ClipStack::ClipState::kEmpty) {
return ClipType::kEmpty; return ClipType::kEmpty;
} else if (state == GrClipStack::ClipState::kDeviceRect || } else if (state == ClipStack::ClipState::kDeviceRect ||
state == GrClipStack::ClipState::kWideOpen) { state == ClipStack::ClipState::kWideOpen) {
return ClipType::kRect; return ClipType::kRect;
} else { } else {
return ClipType::kComplex; return ClipType::kComplex;

View File

@ -14,8 +14,8 @@
#include "include/core/SkSurface.h" #include "include/core/SkSurface.h"
#include "include/gpu/GrTypes.h" #include "include/gpu/GrTypes.h"
#include "src/gpu/BaseDevice.h" #include "src/gpu/BaseDevice.h"
#include "src/gpu/GrClipStack.h"
#include "src/gpu/SkGr.h" #include "src/gpu/SkGr.h"
#include "src/gpu/v1/ClipStack.h"
#include "src/gpu/v1/SurfaceDrawContext_v1.h" #include "src/gpu/v1/SurfaceDrawContext_v1.h"
class SkSpecialImage; class SkSpecialImage;
@ -178,14 +178,14 @@ protected:
bool onClipIsAA() const override; bool onClipIsAA() const override;
bool onClipIsWideOpen() const override { bool onClipIsWideOpen() const override {
return fClip.clipState() == GrClipStack::ClipState::kWideOpen; return fClip.clipState() == ClipStack::ClipState::kWideOpen;
} }
SkIRect onDevClipBounds() const override { return fClip.getConservativeBounds(); } SkIRect onDevClipBounds() const override { return fClip.getConservativeBounds(); }
private: private:
std::unique_ptr<SurfaceDrawContext> fSurfaceDrawContext; std::unique_ptr<SurfaceDrawContext> fSurfaceDrawContext;
GrClipStack fClip; ClipStack fClip;
enum Flags { enum Flags {
kNeedClear_Flag = 1 << 0, //!< Surface requires an initial clear kNeedClear_Flag = 1 << 0, //!< Surface requires an initial clear

View File

@ -530,7 +530,7 @@ public:
this->internalStencilClear(&scissor, insideStencilMask); this->internalStencilClear(&scissor, insideStencilMask);
} }
// While this can take a general clip, since GrClipStack relies on this function, it must take // While this can take a general clip, since ClipStack relies on this function, it must take
// care to only provide hard clips or we could get stuck in a loop. The general clip is needed // care to only provide hard clips or we could get stuck in a loop. The general clip is needed
// so that path renderers can use this function. // so that path renderers can use this function.
void stencilRect(const GrClip* clip, void stencilRect(const GrClip* clip,

File diff suppressed because it is too large Load Diff