193a379bd4d6b30d86c270b879cf172d80172a72bcdalton/*
293a379bd4d6b30d86c270b879cf172d80172a72bcdalton * Copyright 2016 Google Inc.
393a379bd4d6b30d86c270b879cf172d80172a72bcdalton *
493a379bd4d6b30d86c270b879cf172d80172a72bcdalton * Use of this source code is governed by a BSD-style license that can be
593a379bd4d6b30d86c270b879cf172d80172a72bcdalton * found in the LICENSE file.
693a379bd4d6b30d86c270b879cf172d80172a72bcdalton */
793a379bd4d6b30d86c270b879cf172d80172a72bcdalton
893a379bd4d6b30d86c270b879cf172d80172a72bcdalton
993a379bd4d6b30d86c270b879cf172d80172a72bcdalton#ifndef GrStencilSettings_DEFINED
1093a379bd4d6b30d86c270b879cf172d80172a72bcdalton#define GrStencilSettings_DEFINED
1193a379bd4d6b30d86c270b879cf172d80172a72bcdalton
1293a379bd4d6b30d86c270b879cf172d80172a72bcdalton#include "GrUserStencilSettings.h"
1393a379bd4d6b30d86c270b879cf172d80172a72bcdalton#include "SkRegion.h"
1493a379bd4d6b30d86c270b879cf172d80172a72bcdalton
1593a379bd4d6b30d86c270b879cf172d80172a72bcdaltonclass GrProcessorKeyBuilder;
1693a379bd4d6b30d86c270b879cf172d80172a72bcdalton
1793a379bd4d6b30d86c270b879cf172d80172a72bcdaltonenum class GrStencilTest : uint16_t {
1893a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kAlways,
1993a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kNever,
2093a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kGreater,
2193a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kGEqual,
2293a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kLess,
2393a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kLEqual,
2493a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kEqual,
2593a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kNotEqual
2693a379bd4d6b30d86c270b879cf172d80172a72bcdalton};
2793a379bd4d6b30d86c270b879cf172d80172a72bcdaltonstatic constexpr int kGrStencilTestCount = 1 + (int)GrStencilTest::kNotEqual;
2893a379bd4d6b30d86c270b879cf172d80172a72bcdalton
2993a379bd4d6b30d86c270b879cf172d80172a72bcdaltonenum class GrStencilOp : uint8_t {
3093a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kKeep,
3193a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kZero,
3293a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kReplace, // Replace stencil value with fRef (only the bits enabled in fWriteMask).
3393a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kInvert,
3493a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kIncWrap,
3593a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kDecWrap,
3693a379bd4d6b30d86c270b879cf172d80172a72bcdalton    // NOTE: clamping occurs before the write mask. So if the MSB is zero and masked out, stencil
3793a379bd4d6b30d86c270b879cf172d80172a72bcdalton    // values will still wrap when using clamping ops.
3893a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kIncClamp,
3993a379bd4d6b30d86c270b879cf172d80172a72bcdalton    kDecClamp
4093a379bd4d6b30d86c270b879cf172d80172a72bcdalton};
4193a379bd4d6b30d86c270b879cf172d80172a72bcdaltonstatic constexpr int kGrStencilOpCount = 1 + (int)GrStencilOp::kDecClamp;
4293a379bd4d6b30d86c270b879cf172d80172a72bcdalton
4393a379bd4d6b30d86c270b879cf172d80172a72bcdalton/**
4493a379bd4d6b30d86c270b879cf172d80172a72bcdalton * This class defines concrete stencil settings that map directly to the underlying hardware. It
4593a379bd4d6b30d86c270b879cf172d80172a72bcdalton * is deduced from user stencil settings, stencil clip status, and the number of bits in the
4693a379bd4d6b30d86c270b879cf172d80172a72bcdalton * target stencil buffer.
4793a379bd4d6b30d86c270b879cf172d80172a72bcdalton */
4893a379bd4d6b30d86c270b879cf172d80172a72bcdaltonclass GrStencilSettings {
4993a379bd4d6b30d86c270b879cf172d80172a72bcdaltonpublic:
5093a379bd4d6b30d86c270b879cf172d80172a72bcdalton    GrStencilSettings() { this->setDisabled(); }
5193a379bd4d6b30d86c270b879cf172d80172a72bcdalton    GrStencilSettings(const GrUserStencilSettings& user, bool hasStencilClip, int numStencilBits) {
5293a379bd4d6b30d86c270b879cf172d80172a72bcdalton        this->reset(user, hasStencilClip, numStencilBits);
5393a379bd4d6b30d86c270b879cf172d80172a72bcdalton    }
5493a379bd4d6b30d86c270b879cf172d80172a72bcdalton    GrStencilSettings(const GrStencilSettings& that) { this->reset(that); }
5593a379bd4d6b30d86c270b879cf172d80172a72bcdalton    GrStencilSettings& operator=(const GrStencilSettings& that) { this->reset(that); return *this; }
5693a379bd4d6b30d86c270b879cf172d80172a72bcdalton
5793a379bd4d6b30d86c270b879cf172d80172a72bcdalton    void invalidate() { fFlags |= kInvalid_PrivateFlag; }
5893a379bd4d6b30d86c270b879cf172d80172a72bcdalton    void setDisabled() { fFlags = kAll_StencilFlags; }
5993a379bd4d6b30d86c270b879cf172d80172a72bcdalton    void reset(const GrUserStencilSettings&, bool hasStencilClip, int numStencilBits);
6093a379bd4d6b30d86c270b879cf172d80172a72bcdalton    void reset(const GrStencilSettings&);
6193a379bd4d6b30d86c270b879cf172d80172a72bcdalton
6293a379bd4d6b30d86c270b879cf172d80172a72bcdalton    bool isValid() const { return !(fFlags & kInvalid_PrivateFlag); }
6393a379bd4d6b30d86c270b879cf172d80172a72bcdalton    bool isDisabled() const { SkASSERT(this->isValid()); return fFlags & kDisabled_StencilFlag; }
6493a379bd4d6b30d86c270b879cf172d80172a72bcdalton    bool doesWrite() const { SkASSERT(this->isValid());
6593a379bd4d6b30d86c270b879cf172d80172a72bcdalton                             return !(fFlags & kNoModifyStencil_StencilFlag); }
6693a379bd4d6b30d86c270b879cf172d80172a72bcdalton    bool isTwoSided() const { SkASSERT(this->isValid());
6793a379bd4d6b30d86c270b879cf172d80172a72bcdalton                              return !(fFlags & kSingleSided_StencilFlag); }
6893a379bd4d6b30d86c270b879cf172d80172a72bcdalton    bool usesWrapOp() const { SkASSERT(this->isValid());
6993a379bd4d6b30d86c270b879cf172d80172a72bcdalton                              return !(fFlags & kNoWrapOps_StencilFlag); }
7093a379bd4d6b30d86c270b879cf172d80172a72bcdalton
7193a379bd4d6b30d86c270b879cf172d80172a72bcdalton    void genKey(GrProcessorKeyBuilder* b) const;
7293a379bd4d6b30d86c270b879cf172d80172a72bcdalton
7393a379bd4d6b30d86c270b879cf172d80172a72bcdalton    bool operator!=(const GrStencilSettings& that) const { return !(*this == that); }
7493a379bd4d6b30d86c270b879cf172d80172a72bcdalton    bool operator==(const GrStencilSettings&) const;
7593a379bd4d6b30d86c270b879cf172d80172a72bcdalton
7693a379bd4d6b30d86c270b879cf172d80172a72bcdalton    struct Face : public GrTStencilFaceSettings<GrStencilTest, GrStencilOp> {
7793a379bd4d6b30d86c270b879cf172d80172a72bcdalton        void reset(const GrUserStencilSettings::Face&, bool useStencilClip, int numStencilBits);
7893a379bd4d6b30d86c270b879cf172d80172a72bcdalton        void setDisabled();
7993a379bd4d6b30d86c270b879cf172d80172a72bcdalton    };
8093a379bd4d6b30d86c270b879cf172d80172a72bcdalton
8193a379bd4d6b30d86c270b879cf172d80172a72bcdalton    const Face& front() const { SkASSERT(!this->isDisabled()); return fFront; }
8293a379bd4d6b30d86c270b879cf172d80172a72bcdalton    const Face& back() const { SkASSERT(this->isTwoSided()); return fBack; }
8393a379bd4d6b30d86c270b879cf172d80172a72bcdalton
8493a379bd4d6b30d86c270b879cf172d80172a72bcdalton    /**
8593a379bd4d6b30d86c270b879cf172d80172a72bcdalton     * Given a thing to draw into the stencil clip, a fill type, and a set op
8693a379bd4d6b30d86c270b879cf172d80172a72bcdalton     * this function determines:
8793a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *      1. Whether the thing can be draw directly to the stencil clip or
8893a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *      needs to be drawn to the client portion of the stencil first.
8993a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *      2. How many passes are needed.
9093a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *      3. What those passes are.
9193a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *
9293a379bd4d6b30d86c270b879cf172d80172a72bcdalton     * @param op                the set op to combine this element with the existing clip
9393a379bd4d6b30d86c270b879cf172d80172a72bcdalton     * @param canBeDirect       can the caller draw this element directly (without using stencil)?
9493a379bd4d6b30d86c270b879cf172d80172a72bcdalton     * @param invertedFill      is this path inverted
9593a379bd4d6b30d86c270b879cf172d80172a72bcdalton     * @param drawDirectToClip  out: true if caller should draw the element directly, false if it
9693a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *                          should draw it into the user stencil bits first.
9793a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *
9893a379bd4d6b30d86c270b879cf172d80172a72bcdalton     * @return a null-terminated array of settings for stencil passes.
9993a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *
10093a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *         If drawDirectToClip is false, the caller must first draw the element into the user
10193a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *         stencil bits, and then cover the clip area with multiple passes using the returned
10293a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *         stencil settings.
10393a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *
10493a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *         If drawDirectToClip is true, the returned array will only have one pass and the
10593a379bd4d6b30d86c270b879cf172d80172a72bcdalton     *         caller should use those stencil settings while drawing the element directly.
10693a379bd4d6b30d86c270b879cf172d80172a72bcdalton     */
10793a379bd4d6b30d86c270b879cf172d80172a72bcdalton    static GrUserStencilSettings const* const* GetClipPasses(SkRegion::Op op,
10893a379bd4d6b30d86c270b879cf172d80172a72bcdalton                                                             bool canBeDirect,
10993a379bd4d6b30d86c270b879cf172d80172a72bcdalton                                                             bool invertedFill,
11093a379bd4d6b30d86c270b879cf172d80172a72bcdalton                                                             bool* drawDirectToClip);
11193a379bd4d6b30d86c270b879cf172d80172a72bcdalton
11231550dbc9804dafb18a71c968deb513cc8857cf3Mike Klein    /** Gets the user stencil settings to directly set the clip bit. */
11331550dbc9804dafb18a71c968deb513cc8857cf3Mike Klein    static const GrUserStencilSettings* SetClipBitSettings(bool setToInside);
11431550dbc9804dafb18a71c968deb513cc8857cf3Mike Klein
11593a379bd4d6b30d86c270b879cf172d80172a72bcdaltonprivate:
11693a379bd4d6b30d86c270b879cf172d80172a72bcdalton    // Internal flag for backends to optionally mark their tracked stencil state as invalid.
11793a379bd4d6b30d86c270b879cf172d80172a72bcdalton    enum { kInvalid_PrivateFlag = (kLast_StencilFlag << 1) };
11893a379bd4d6b30d86c270b879cf172d80172a72bcdalton
11993a379bd4d6b30d86c270b879cf172d80172a72bcdalton    uint32_t   fFlags;
12093a379bd4d6b30d86c270b879cf172d80172a72bcdalton    Face       fFront;
12193a379bd4d6b30d86c270b879cf172d80172a72bcdalton    Face       fBack;
12293a379bd4d6b30d86c270b879cf172d80172a72bcdalton};
12393a379bd4d6b30d86c270b879cf172d80172a72bcdalton
12493a379bd4d6b30d86c270b879cf172d80172a72bcdalton#endif
125