/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrStencilSettings_DEFINED #define GrStencilSettings_DEFINED #include "include/core/SkRegion.h" #include "src/gpu/ganesh/GrUserStencilSettings.h" namespace skgpu { class KeyBuilder; } enum class GrStencilTest : uint16_t { kAlways, kNever, kGreater, kGEqual, kLess, kLEqual, kEqual, kNotEqual }; static constexpr int kGrStencilTestCount = 1 + (int)GrStencilTest::kNotEqual; enum class GrStencilOp : uint8_t { kKeep, kZero, kReplace, // Replace stencil value with fRef (only the bits enabled in fWriteMask). kInvert, kIncWrap, kDecWrap, // NOTE: clamping occurs before the write mask. So if the MSB is zero and masked out, stencil // values will still wrap when using clamping ops. kIncClamp, kDecClamp }; static constexpr int kGrStencilOpCount = 1 + (int)GrStencilOp::kDecClamp; /** * This class defines concrete stencil settings that map directly to the underlying hardware. It * is deduced from user stencil settings, stencil clip status, and the number of bits in the * target stencil buffer. */ class GrStencilSettings { public: GrStencilSettings() { this->setDisabled(); } GrStencilSettings(const GrUserStencilSettings& user, bool hasStencilClip, int numStencilBits) { this->reset(user, hasStencilClip, numStencilBits); } GrStencilSettings(const GrStencilSettings& that) { this->reset(that); } GrStencilSettings& operator=(const GrStencilSettings& that) { this->reset(that); return *this; } void invalidate() { fFlags |= kInvalid_PrivateFlag; } void setDisabled() { fFlags = kAll_StencilFlags; } void reset(const GrUserStencilSettings&, bool hasStencilClip, int numStencilBits); void reset(const GrStencilSettings&); bool isValid() const { return !(fFlags & kInvalid_PrivateFlag); } bool isDisabled() const { SkASSERT(this->isValid()); return fFlags & kDisabled_StencilFlag; } bool doesWrite() const { SkASSERT(this->isValid()); return !(fFlags & kNoModifyStencil_StencilFlag); } bool isTwoSided() const { SkASSERT(this->isValid()); return !(fFlags & kSingleSided_StencilFlag); } bool usesWrapOp() const { SkASSERT(this->isValid()); return !(fFlags & kNoWrapOps_StencilFlag); } void genKey(skgpu::KeyBuilder* b, bool includeRefsAndMasks) const; bool operator!=(const GrStencilSettings& that) const { return !(*this == that); } bool operator==(const GrStencilSettings&) const; struct Face : public GrTStencilFaceSettings { void reset(const GrUserStencilSettings::Face&, bool useStencilClip, int numStencilBits); void setDisabled(); }; const Face& singleSidedFace() const { SkASSERT(!this->isDisabled()); SkASSERT(!this->isTwoSided()); return fCWFace; } // Returns the stencil settings for triangles that wind clockwise in "post-origin" space. // (i.e., the space that results after a potential y-axis flip on device space for bottom-left // origins.) const Face& postOriginCWFace(GrSurfaceOrigin origin) const { SkASSERT(this->isTwoSided()); return (kTopLeft_GrSurfaceOrigin == origin) ? fCWFace : fCCWFace; } // Returns the stencil settings for triangles that wind counter-clockwise in "post-origin" // space. (i.e., the space that results after a potential y-axis flip on device space for // bottom-left origins.) const Face& postOriginCCWFace(GrSurfaceOrigin origin) const { SkASSERT(this->isTwoSided()); return (kTopLeft_GrSurfaceOrigin == origin) ? fCCWFace : fCWFace; } /** Gets the user stencil settings to directly set the clip bit. */ static const GrUserStencilSettings* SetClipBitSettings(bool setToInside); private: // Internal flag for backends to optionally mark their tracked stencil state as invalid. // NOTE: This value is outside the declared range of GrStencilFlags, but since that type is // explicitly backed by 'int', it can still represent this constant. clang 11 complains about // mixing enum types in bit operations, so this works around that. inline static constexpr GrStencilFlags kInvalid_PrivateFlag = static_cast(kLast_StencilFlag << 1); uint32_t fFlags; Face fCWFace; Face fCCWFace; }; #endif