1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2016 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef GrStencilSettings_DEFINED
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define GrStencilSettings_DEFINED
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrUserStencilSettings.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRegion.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrProcessorKeyBuilder;
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotenum class GrStencilTest : uint16_t {
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kAlways,
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kNever,
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kGreater,
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kGEqual,
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kLess,
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kLEqual,
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kEqual,
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kNotEqual
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic constexpr int kGrStencilTestCount = 1 + (int)GrStencilTest::kNotEqual;
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotenum class GrStencilOp : uint8_t {
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kKeep,
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kZero,
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kReplace, // Replace stencil value with fRef (only the bits enabled in fWriteMask).
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kInvert,
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kIncWrap,
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kDecWrap,
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // NOTE: clamping occurs before the write mask. So if the MSB is zero and masked out, stencil
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // values will still wrap when using clamping ops.
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kIncClamp,
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kDecClamp
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic constexpr int kGrStencilOpCount = 1 + (int)GrStencilOp::kDecClamp;
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/**
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * This class defines concrete stencil settings that map directly to the underlying hardware. It
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * is deduced from user stencil settings, stencil clip status, and the number of bits in the
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * target stencil buffer.
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrStencilSettings {
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrStencilSettings() { this->setDisabled(); }
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrStencilSettings(const GrUserStencilSettings& user, bool hasStencilClip, int numStencilBits) {
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->reset(user, hasStencilClip, numStencilBits);
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrStencilSettings(const GrStencilSettings& that) { this->reset(that); }
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrStencilSettings& operator=(const GrStencilSettings& that) { this->reset(that); return *this; }
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void invalidate() { fFlags |= kInvalid_PrivateFlag; }
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void setDisabled() { fFlags = kAll_StencilFlags; }
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void reset(const GrUserStencilSettings&, bool hasStencilClip, int numStencilBits);
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void reset(const GrStencilSettings&);
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool isValid() const { return !(fFlags & kInvalid_PrivateFlag); }
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool isDisabled() const { SkASSERT(this->isValid()); return fFlags & kDisabled_StencilFlag; }
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool doesWrite() const { SkASSERT(this->isValid());
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                             return !(fFlags & kNoModifyStencil_StencilFlag); }
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool isTwoSided() const { SkASSERT(this->isValid());
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                              return !(fFlags & kSingleSided_StencilFlag); }
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool usesWrapOp() const { SkASSERT(this->isValid());
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                              return !(fFlags & kNoWrapOps_StencilFlag); }
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void genKey(GrProcessorKeyBuilder* b) const;
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool operator!=(const GrStencilSettings& that) const { return !(*this == that); }
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool operator==(const GrStencilSettings&) const;
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    struct Face : public GrTStencilFaceSettings<GrStencilTest, GrStencilOp> {
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void reset(const GrUserStencilSettings::Face&, bool useStencilClip, int numStencilBits);
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void setDisabled();
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const Face& front() const { SkASSERT(!this->isDisabled()); return fFront; }
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const Face& back() const { SkASSERT(this->isTwoSided()); return fBack; }
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Given a thing to draw into the stencil clip, a fill type, and a set op
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * this function determines:
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *      1. Whether the thing can be draw directly to the stencil clip or
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *      needs to be drawn to the client portion of the stencil first.
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *      2. How many passes are needed.
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *      3. What those passes are.
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * @param op                the set op to combine this element with the existing clip
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * @param canBeDirect       can the caller draw this element directly (without using stencil)?
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * @param invertedFill      is this path inverted
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * @param drawDirectToClip  out: true if caller should draw the element directly, false if it
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *                          should draw it into the user stencil bits first.
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * @return a null-terminated array of settings for stencil passes.
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *         If drawDirectToClip is false, the caller must first draw the element into the user
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *         stencil bits, and then cover the clip area with multiple passes using the returned
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *         stencil settings.
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *         If drawDirectToClip is true, the returned array will only have one pass and the
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *         caller should use those stencil settings while drawing the element directly.
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static GrUserStencilSettings const* const* GetClipPasses(SkRegion::Op op,
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                             bool canBeDirect,
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                             bool invertedFill,
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                             bool* drawDirectToClip);
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /** Gets the user stencil settings to directly set the clip bit. */
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const GrUserStencilSettings* SetClipBitSettings(bool setToInside);
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Internal flag for backends to optionally mark their tracked stencil state as invalid.
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum { kInvalid_PrivateFlag = (kLast_StencilFlag << 1) };
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint32_t   fFlags;
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Face       fFront;
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Face       fBack;
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
125