aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ops/GrClearOp.h
blob: 4f51796e6c6dff15c8b9286e677b76c09b96346c (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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrClearOp_DEFINED
#define GrClearOp_DEFINED

#include "GrFixedClip.h"
#include "GrGpu.h"
#include "GrGpuCommandBuffer.h"
#include "GrOp.h"
#include "GrOpFlushState.h"
#include "GrRenderTarget.h"

class GrClearOp final : public GrOp {
public:
    DEFINE_OP_CLASS_ID

    // MDB TODO: replace the renderTargetContext with just the renderTargetProxy.
    // For now, we need the renderTargetContext for its accessRenderTarget powers.
    static std::unique_ptr<GrClearOp> Make(const GrFixedClip& clip, GrColor color,
                                           GrRenderTargetContext* rtc) {
        const SkIRect rtRect = SkIRect::MakeWH(rtc->width(), rtc->height());
        if (clip.scissorEnabled() && !SkIRect::Intersects(clip.scissorRect(), rtRect)) {
            return nullptr;
        }

        // MDB TODO: remove this. In this hybrid state we need to be sure the RT is instantiable
        // so it can carry the IO refs. In the future we will just get the proxy and
        // it carry the IO refs.
        if (!rtc->accessRenderTarget()) {
            return nullptr;
        }

        return std::unique_ptr<GrClearOp>(new GrClearOp(clip, color, rtc));
    }

    // MDB TODO: replace the renderTargetContext with just the renderTargetProxy.
    static std::unique_ptr<GrClearOp> Make(const SkIRect& rect, GrColor color,
                                           GrRenderTargetContext* rtc,
                                           bool fullScreen) {
        SkASSERT(fullScreen || !rect.isEmpty());

        // MDB TODO: remove this. See above comment.
        if (!rtc->accessRenderTarget()) {
            return nullptr;
        }

        return std::unique_ptr<GrClearOp>(new GrClearOp(rect, color, rtc, fullScreen));
    }

    const char* name() const override { return "Clear"; }

    SkString dumpInfo() const override {
        SkString string;
        string.append(INHERITED::dumpInfo());
        string.appendf("rtID: %d proxyID: %d Scissor [",
                       fRenderTarget.get()->uniqueID().asUInt(),
                       fProxyUniqueID.asUInt());
        if (fClip.scissorEnabled()) {
            const SkIRect& r = fClip.scissorRect();
            string.appendf("L: %d, T: %d, R: %d, B: %d", r.fLeft, r.fTop, r.fRight, r.fBottom);
        } else {
            string.append("disabled");
        }
        string.appendf("], Color: 0x%08x\n", fColor);
        return string;
    }

    GrColor color() const { return fColor; }
    void setColor(GrColor color) { fColor = color; }

private:
    GrClearOp(const GrFixedClip& clip, GrColor color, GrRenderTargetContext* rtc)
        : INHERITED(ClassID())
        , fClip(clip)
        , fColor(color)
        , fProxyUniqueID(rtc->asSurfaceProxy()->uniqueID()) {

        GrSurfaceProxy* proxy = rtc->asSurfaceProxy();
        const SkIRect rtRect = SkIRect::MakeWH(proxy->width(), proxy->height());
        if (fClip.scissorEnabled()) {
            // Don't let scissors extend outside the RT. This may improve op combining.
            if (!fClip.intersect(rtRect)) {
                SkASSERT(0);  // should be caught upstream
                fClip = GrFixedClip(SkIRect::MakeEmpty());
            }

            if (GrResourceProvider::IsFunctionallyExact(proxy) && fClip.scissorRect() == rtRect) {
                fClip.disableScissor();
            }
        }
        this->setBounds(SkRect::Make(fClip.scissorEnabled() ? fClip.scissorRect() : rtRect),
                        HasAABloat::kNo, IsZeroArea::kNo);
        fRenderTarget.reset(rtc->accessRenderTarget());
    }

    GrClearOp(const SkIRect& rect, GrColor color, GrRenderTargetContext* rtc, bool fullScreen)
        : INHERITED(ClassID())
        , fClip(GrFixedClip(rect))
        , fColor(color)
        , fProxyUniqueID(rtc->asSurfaceProxy()->uniqueID()) {

        if (fullScreen) {
            fClip.disableScissor();
        }
        this->setBounds(SkRect::Make(rect), HasAABloat::kNo, IsZeroArea::kNo);
        fRenderTarget.reset(rtc->accessRenderTarget());
    }

    bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
        // This could be much more complicated. Currently we look at cases where the new clear
        // contains the old clear, or when the new clear is a subset of the old clear and is the
        // same color.
        GrClearOp* cb = t->cast<GrClearOp>();
        SkASSERT(cb->fRenderTarget == fRenderTarget);
        SkASSERT(cb->fProxyUniqueID == fProxyUniqueID);
        if (fClip.windowRectsState() != cb->fClip.windowRectsState()) {
            return false;
        }
        if (cb->contains(this)) {
            fClip = cb->fClip;
            this->replaceBounds(*t);
            fColor = cb->fColor;
            return true;
        } else if (cb->fColor == fColor && this->contains(cb)) {
            return true;
        }
        return false;
    }

    bool contains(const GrClearOp* that) const {
        // The constructor ensures that scissor gets disabled on any clip that fills the entire RT.
        return !fClip.scissorEnabled() ||
               (that->fClip.scissorEnabled() &&
                fClip.scissorRect().contains(that->fClip.scissorRect()));
    }

    void onPrepare(GrOpFlushState*) override {}

    void onExecute(GrOpFlushState* state) override {
        // MDB TODO: instantiate the renderTarget from the proxy in here
        state->commandBuffer()->clear(fRenderTarget.get(), fClip, fColor);
    }

    GrFixedClip                                             fClip;
    GrColor                                                 fColor;

    // MDB TODO: remove this. When the renderTargetProxy carries the refs this will be redundant.
    GrSurfaceProxy::UniqueID                                fProxyUniqueID;
    GrPendingIOResource<GrRenderTarget, kWrite_GrIOType>    fRenderTarget;

    typedef GrOp INHERITED;
};

#endif