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
160
161
162
163
164
165
166
167
168
169
170
171
172
|
/*
* Copyright 2010 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrRenderTargetOpList_DEFINED
#define GrRenderTargetOpList_DEFINED
#include "GrAppliedClip.h"
#include "GrOpList.h"
#include "GrPathRendering.h"
#include "GrPrimitiveProcessor.h"
#include "ops/GrOp.h"
#include "SkArenaAlloc.h"
#include "SkClipStack.h"
#include "SkMatrix.h"
#include "SkStringUtils.h"
#include "SkStrokeRec.h"
#include "SkTArray.h"
#include "SkTLazy.h"
#include "SkTypes.h"
class GrAuditTrail;
class GrClearOp;
class GrCaps;
class GrRenderTargetProxy;
class GrRenderTargetOpList final : public GrOpList {
private:
using DstProxy = GrXferProcessor::DstProxy;
public:
GrRenderTargetOpList(GrRenderTargetProxy*, GrGpu*, GrAuditTrail*);
~GrRenderTargetOpList() override;
void makeClosed(const GrCaps& caps) override {
if (this->isClosed()) {
return;
}
this->forwardCombine(caps);
INHERITED::makeClosed(caps);
}
bool isEmpty() const { return fRecordedOps.empty(); }
/**
* Empties the draw buffer of any queued up draws.
*/
void endFlush() override;
/**
* Together these two functions flush all queued up draws to GrCommandBuffer. The return value
* of executeOps() indicates whether any commands were actually issued to the GPU.
*/
void onPrepare(GrOpFlushState* flushState) override;
bool onExecute(GrOpFlushState* flushState) override;
uint32_t addOp(std::unique_ptr<GrOp> op, const GrCaps& caps) {
auto addDependency = [ &caps, this ] (GrSurfaceProxy* p) {
this->addDependency(p, caps);
};
op->visitProxies(addDependency);
this->recordOp(std::move(op), caps);
return this->uniqueID();
}
uint32_t addOp(std::unique_ptr<GrOp> op, const GrCaps& caps,
GrAppliedClip&& clip, const DstProxy& dstProxy) {
auto addDependency = [ &caps, this ] (GrSurfaceProxy* p) {
this->addDependency(p, caps);
};
op->visitProxies(addDependency);
clip.visitProxies(addDependency);
this->recordOp(std::move(op), caps, clip.doesClip() ? &clip : nullptr, &dstProxy);
return this->uniqueID();
}
void discard();
/** Clears the entire render target */
void fullClear(const GrCaps& caps, GrColor color);
/**
* Copies a pixel rectangle from one surface to another. This call may finalize
* reserved vertex/index data (as though a draw call was made). The src pixels
* copied are specified by srcRect. They are copied to a rect of the same
* size in dst with top left at dstPoint. If the src rect is clipped by the
* src bounds then pixel values in the dst rect corresponding to area clipped
* by the src rect are not overwritten. This method is not guaranteed to succeed
* depending on the type of surface, configs, etc, and the backend-specific
* limitations.
*/
bool copySurface(const GrCaps& caps,
GrSurfaceProxy* dst,
GrSurfaceProxy* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint) override;
GrRenderTargetOpList* asRenderTargetOpList() override { return this; }
SkDEBUGCODE(void dump() const override;)
SkDEBUGCODE(int numOps() const override { return fRecordedOps.count(); })
SkDEBUGCODE(int numClips() const override { return fNumClips; })
SkDEBUGCODE(void visitProxies_debugOnly(const GrOp::VisitProxyFunc&) const;)
private:
friend class GrRenderTargetContextPriv; // for stencil clip state. TODO: this is invasive
struct RecordedOp {
RecordedOp(std::unique_ptr<GrOp> op, GrAppliedClip* appliedClip, const DstProxy* dstProxy)
: fOp(std::move(op)), fAppliedClip(appliedClip) {
if (dstProxy) {
fDstProxy = *dstProxy;
}
}
void visitProxies(const GrOp::VisitProxyFunc& func) const {
if (fOp) {
fOp->visitProxies(func);
}
if (fDstProxy.proxy()) {
func(fDstProxy.proxy());
}
if (fAppliedClip) {
fAppliedClip->visitProxies(func);
}
}
std::unique_ptr<GrOp> fOp;
DstProxy fDstProxy;
GrAppliedClip* fAppliedClip;
};
void gatherProxyIntervals(GrResourceAllocator*) const override;
void recordOp(std::unique_ptr<GrOp>, const GrCaps& caps,
GrAppliedClip* = nullptr, const DstProxy* = nullptr);
void forwardCombine(const GrCaps&);
// If this returns true then b has been merged into a's op.
bool combineIfPossible(const RecordedOp& a, GrOp* b, const GrAppliedClip* bClip,
const DstProxy* bDstTexture, const GrCaps&);
uint32_t fLastClipStackGenID;
SkIRect fLastDevClipBounds;
int fLastClipNumAnalyticFPs;
// For ops/opList we have mean: 5 stdDev: 28
SkSTArray<5, RecordedOp, true> fRecordedOps;
// MDB TODO: 4096 for the first allocation of the clip space will be huge overkill.
// Gather statistics to determine the correct size.
SkArenaAlloc fClipAllocator{4096};
SkDEBUGCODE(int fNumClips;)
typedef GrOpList INHERITED;
};
#endif
|