/*
 * 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<GrStencilTest, GrStencilOp> {
        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<GrStencilFlags>(kLast_StencilFlag << 1);

    uint32_t   fFlags;
    Face       fCWFace;
    Face       fCCWFace;
};

#endif
