aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrAppliedClip.h
blob: bfe3383e16b9d57fa37f7c79f13dc3aedfc52b9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
 * 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 GrAppliedClip_DEFINED
#define GrAppliedClip_DEFINED

#include "GrFragmentProcessor.h"
#include "GrScissorState.h"
#include "GrWindowRectsState.h"

#include "SkClipStack.h"


/**
 * Produced by GrHardClip. It provides a set of modifications to the hardware drawing state that
 * implement the clip.
 */
class GrAppliedHardClip {
public:
    GrAppliedHardClip() = default;
    GrAppliedHardClip(GrAppliedHardClip&& that) = default;
    GrAppliedHardClip(const GrAppliedHardClip&) = delete;

    const GrScissorState& scissorState() const { return fScissorState; }
    const GrWindowRectsState& windowRectsState() const { return fWindowRectsState; }
    uint32_t stencilStackID() const { return fStencilStackID; }
    bool hasStencilClip() const { return SkClipStack::kInvalidGenID != fStencilStackID; }

    /**
     * Intersects the applied clip with the provided rect. Returns false if the draw became empty.
     * 'clippedDrawBounds' will be intersected with 'irect'. This returns false if the clip becomes
     * empty or the draw no longer intersects the clip. In either case the draw can be skipped.
     */
    bool addScissor(const SkIRect& irect, SkRect* clippedDrawBounds) {
        return fScissorState.intersect(irect) && clippedDrawBounds->intersect(SkRect::Make(irect));
    }

    void addWindowRectangles(const GrWindowRectsState& windowState) {
        SkASSERT(!fWindowRectsState.enabled());
        fWindowRectsState = windowState;
    }

    void addWindowRectangles(const GrWindowRectangles& windows, GrWindowRectsState::Mode mode) {
        SkASSERT(!fWindowRectsState.enabled());
        fWindowRectsState.set(windows, mode);
    }

    void addStencilClip(uint32_t stencilStackID) {
        SkASSERT(SkClipStack::kInvalidGenID == fStencilStackID);
        fStencilStackID = stencilStackID;
    }

    bool doesClip() const {
        return fScissorState.enabled() || this->hasStencilClip() || fWindowRectsState.enabled();
    }

    bool operator==(const GrAppliedHardClip& that) const {
        return fScissorState == that.fScissorState &&
               fWindowRectsState == that.fWindowRectsState &&
               fStencilStackID == that.fStencilStackID;
    }
    bool operator!=(const GrAppliedHardClip& that) const { return !(*this == that); }

private:
    GrScissorState             fScissorState;
    GrWindowRectsState         fWindowRectsState;
    uint32_t                   fStencilStackID = SkClipStack::kInvalidGenID;
};

/**
 * Produced by GrClip. It provides a set of modifications to GrPipeline that implement the clip.
 */
class GrAppliedClip {
public:
    GrAppliedClip() = default;
    GrAppliedClip(GrAppliedClip&& that) = default;
    GrAppliedClip(const GrAppliedClip&) = delete;

    const GrScissorState& scissorState() const { return fHardClip.scissorState(); }
    const GrWindowRectsState& windowRectsState() const { return fHardClip.windowRectsState(); }
    uint32_t stencilStackID() const { return fHardClip.stencilStackID(); }
    bool hasStencilClip() const { return fHardClip.hasStencilClip(); }
    int numClipCoverageFragmentProcessors() const { return fClipCoverageFPs.count(); }
    const GrFragmentProcessor* clipCoverageFragmentProcessor(int i) const {
        SkASSERT(fClipCoverageFPs[i]);
        return fClipCoverageFPs[i].get();
    }
    std::unique_ptr<const GrFragmentProcessor> detachClipCoverageFragmentProcessor(int i) {
        SkASSERT(fClipCoverageFPs[i]);
        return std::move(fClipCoverageFPs[i]);
    }

    GrAppliedHardClip& hardClip() { return fHardClip; }

    void addCoverageFP(std::unique_ptr<GrFragmentProcessor> fp) {
        SkASSERT(fp);
        fClipCoverageFPs.push_back(std::move(fp));
    }

    bool doesClip() const {
        return fHardClip.doesClip() || !fClipCoverageFPs.empty();
    }

    bool operator==(const GrAppliedClip& that) const {
        if (fHardClip != that.fHardClip ||
            fClipCoverageFPs.count() != that.fClipCoverageFPs.count()) {
            return false;
        }
        for (int i = 0; i < fClipCoverageFPs.count(); ++i) {
            if (!fClipCoverageFPs[i] || !that.fClipCoverageFPs[i]) {
                if (fClipCoverageFPs[i] == that.fClipCoverageFPs[i]) {
                    continue; // Both are null.
                }
                return false;
            }
            if (!fClipCoverageFPs[i]->isEqual(*that.fClipCoverageFPs[i])) {
                return false;
            }
        }
        return true;
    }
    bool operator!=(const GrAppliedClip& that) const { return !(*this == that); }

    void visitProxies(const std::function<void(GrSurfaceProxy*)>& func) const {
        for (const std::unique_ptr<GrFragmentProcessor>& fp : fClipCoverageFPs) {
            if (fp) { // This might be called after detach.
                fp->visitProxies(func);
            }
        }
    }

private:
    GrAppliedHardClip fHardClip;
    SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> fClipCoverageFPs;
};

#endif