• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef GrRenderTargetOpList_DEFINED
9 #define GrRenderTargetOpList_DEFINED
10 
11 #include "include/core/SkMatrix.h"
12 #include "include/core/SkStrokeRec.h"
13 #include "include/core/SkTypes.h"
14 #include "include/private/SkTArray.h"
15 #include "src/core/SkArenaAlloc.h"
16 #include "src/core/SkClipStack.h"
17 #include "src/core/SkStringUtils.h"
18 #include "src/core/SkTLazy.h"
19 #include "src/gpu/GrAppliedClip.h"
20 #include "src/gpu/GrOpList.h"
21 #include "src/gpu/GrPathRendering.h"
22 #include "src/gpu/GrPrimitiveProcessor.h"
23 #include "src/gpu/ops/GrDrawOp.h"
24 #include "src/gpu/ops/GrOp.h"
25 
26 class GrAuditTrail;
27 class GrClearOp;
28 class GrCaps;
29 class GrRenderTargetProxy;
30 
31 class GrRenderTargetOpList final : public GrOpList {
32 private:
33     using DstProxy = GrXferProcessor::DstProxy;
34 
35 public:
36     GrRenderTargetOpList(sk_sp<GrOpMemoryPool>, sk_sp<GrRenderTargetProxy>, GrAuditTrail*);
37 
38     ~GrRenderTargetOpList() override;
39 
makeClosed(const GrCaps & caps)40     void makeClosed(const GrCaps& caps) override {
41         if (this->isClosed()) {
42             return;
43         }
44 
45         this->forwardCombine(caps);
46 
47         INHERITED::makeClosed(caps);
48     }
49 
isEmpty()50     bool isEmpty() const { return fOpChains.empty(); }
51 
52     /**
53      * Empties the draw buffer of any queued up draws.
54      */
55     void endFlush() override;
56 
57     /**
58      * Together these two functions flush all queued up draws to GrCommandBuffer. The return value
59      * of executeOps() indicates whether any commands were actually issued to the GPU.
60      */
61     void onPrepare(GrOpFlushState* flushState) override;
62     bool onExecute(GrOpFlushState* flushState) override;
63 
addOp(std::unique_ptr<GrOp> op,GrTextureResolveManager textureResolveManager,const GrCaps & caps)64     void addOp(std::unique_ptr<GrOp> op, GrTextureResolveManager textureResolveManager,
65                const GrCaps& caps) {
66         auto addDependency = [ textureResolveManager, &caps, this ] (
67                 GrSurfaceProxy* p, GrMipMapped mipmapped) {
68             this->addDependency(p, mipmapped, textureResolveManager, caps);
69         };
70 
71         op->visitProxies(addDependency);
72 
73         this->recordOp(std::move(op), GrProcessorSet::EmptySetAnalysis(), nullptr, nullptr, caps);
74     }
75 
addWaitOp(std::unique_ptr<GrOp> op,GrTextureResolveManager textureResolveManager,const GrCaps & caps)76     void addWaitOp(std::unique_ptr<GrOp> op, GrTextureResolveManager textureResolveManager,
77                    const GrCaps& caps) {
78         fHasWaitOp = true;
79         this->addOp(std::move(op), textureResolveManager, caps);
80     }
81 
addDrawOp(std::unique_ptr<GrDrawOp> op,const GrProcessorSet::Analysis & processorAnalysis,GrAppliedClip && clip,const DstProxy & dstProxy,GrTextureResolveManager textureResolveManager,const GrCaps & caps)82     void addDrawOp(std::unique_ptr<GrDrawOp> op, const GrProcessorSet::Analysis& processorAnalysis,
83                    GrAppliedClip&& clip, const DstProxy& dstProxy,
84                    GrTextureResolveManager textureResolveManager, const GrCaps& caps) {
85         auto addDependency = [ textureResolveManager, &caps, this ] (
86                 GrSurfaceProxy* p, GrMipMapped mipmapped) {
87             this->addDependency(p, mipmapped, textureResolveManager, caps);
88         };
89 
90         op->visitProxies(addDependency);
91         clip.visitProxies(addDependency);
92         if (dstProxy.proxy()) {
93             addDependency(dstProxy.proxy(), GrMipMapped::kNo);
94         }
95 
96         this->recordOp(std::move(op), processorAnalysis, clip.doesClip() ? &clip : nullptr,
97                        &dstProxy, caps);
98     }
99 
100     void discard();
101 
102     bool copySurface(GrRecordingContext*,
103                      GrSurfaceProxy* src,
104                      const SkIRect& srcRect,
105                      const SkIPoint& dstPoint) override;
106 
107     void transferFrom(GrRecordingContext*,
108                       const SkIRect& srcRect,
109                       GrColorType surfaceColorType,
110                       GrColorType dstColorType,
111                       sk_sp<GrGpuBuffer> dst,
112                       size_t dstOffset) override;
113 
asRenderTargetOpList()114     GrRenderTargetOpList* asRenderTargetOpList() override { return this; }
115 
116     SkDEBUGCODE(void dump(bool printDependencies) const override;)
117     SkDEBUGCODE(int numClips() const override { return fNumClips; })
118     SkDEBUGCODE(void visitProxies_debugOnly(const GrOp::VisitProxyFunc&) const;)
119 
120 private:
121     friend class GrRenderTargetContextPriv; // for stencil clip state. TODO: this is invasive
122 
123     // The RTC and RTOpList have to work together to handle buffer clears. In most cases, buffer
124     // clearing can be done natively, in which case the op list's load ops are sufficient. In other
125     // cases, draw ops must be used, which makes the RTC the best place for those decisions. This,
126     // however, requires that the RTC be able to coordinate with the op list to achieve similar ends
127     friend class GrRenderTargetContext;
128 
129     bool onIsUsed(GrSurfaceProxy*) const override;
130 
131     // Must only be called if native stencil buffer clearing is enabled
setStencilLoadOp(GrLoadOp op)132     void setStencilLoadOp(GrLoadOp op) { fStencilLoadOp = op; }
133     // Must only be called if native color buffer clearing is enabled.
134     void setColorLoadOp(GrLoadOp op, const SkPMColor4f& color);
135     // Sets the clear color to transparent black
setColorLoadOp(GrLoadOp op)136     void setColorLoadOp(GrLoadOp op) {
137         static const SkPMColor4f kDefaultClearColor = {0.f, 0.f, 0.f, 0.f};
138         this->setColorLoadOp(op, kDefaultClearColor);
139     }
140 
141     enum class CanDiscardPreviousOps : bool {
142         kYes = true,
143         kNo = false
144     };
145 
146     // Perform book-keeping for a fullscreen clear, regardless of how the clear is implemented later
147     // (i.e. setColorLoadOp(), adding a ClearOp, or adding a GrFillRectOp that covers the device).
148     // Returns true if the clear can be converted into a load op (barring device caps).
149     bool resetForFullscreenClear(CanDiscardPreviousOps);
150 
151     void deleteOps();
152 
153     class OpChain {
154     public:
155         OpChain(const OpChain&) = delete;
156         OpChain& operator=(const OpChain&) = delete;
157         OpChain(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*, const DstProxy*);
158 
~OpChain()159         ~OpChain() {
160             // The ops are stored in a GrMemoryPool and must be explicitly deleted via the pool.
161             SkASSERT(fList.empty());
162         }
163 
164         void visitProxies(const GrOp::VisitProxyFunc&) const;
165 
head()166         GrOp* head() const { return fList.head(); }
167 
appliedClip()168         GrAppliedClip* appliedClip() const { return fAppliedClip; }
dstProxy()169         const DstProxy& dstProxy() const { return fDstProxy; }
bounds()170         const SkRect& bounds() const { return fBounds; }
171 
172         // Deletes all the ops in the chain via the pool.
173         void deleteOps(GrOpMemoryPool* pool);
174 
175         // Attempts to move the ops from the passed chain to this chain at the head. Also attempts
176         // to merge ops between the chains. Upon success the passed chain is empty.
177         // Fails when the chains aren't of the same op type, have different clips or dst proxies.
178         bool prependChain(OpChain*, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*);
179 
180         // Attempts to add 'op' to this chain either by merging or adding to the tail. Returns
181         // 'op' to the caller upon failure, otherwise null. Fails when the op and chain aren't of
182         // the same op type, have different clips or dst proxies.
183         std::unique_ptr<GrOp> appendOp(std::unique_ptr<GrOp> op, GrProcessorSet::Analysis,
184                                        const DstProxy*, const GrAppliedClip*, const GrCaps&,
185                                        GrOpMemoryPool*, GrAuditTrail*);
186 
187     private:
188         class List {
189         public:
190             List() = default;
191             List(std::unique_ptr<GrOp>);
192             List(List&&);
193             List& operator=(List&& that);
194 
empty()195             bool empty() const { return !SkToBool(fHead); }
head()196             GrOp* head() const { return fHead.get(); }
tail()197             GrOp* tail() const { return fTail; }
198 
199             std::unique_ptr<GrOp> popHead();
200             std::unique_ptr<GrOp> removeOp(GrOp* op);
201             void pushHead(std::unique_ptr<GrOp> op);
202             void pushTail(std::unique_ptr<GrOp>);
203 
204             void validate() const;
205 
206         private:
207             std::unique_ptr<GrOp> fHead;
208             GrOp* fTail = nullptr;
209         };
210 
211         void validate() const;
212 
213         bool tryConcat(List*, GrProcessorSet::Analysis, const DstProxy&, const GrAppliedClip*,
214                        const SkRect& bounds, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*);
215         static List DoConcat(List, List, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*);
216 
217         List fList;
218         GrProcessorSet::Analysis fProcessorAnalysis;
219         DstProxy fDstProxy;
220         GrAppliedClip* fAppliedClip;
221         SkRect fBounds;
222     };
223 
224     void handleInternalAllocationFailure() override;
225 
226     void gatherProxyIntervals(GrResourceAllocator*) const override;
227 
228     void recordOp(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*, const DstProxy*,
229                   const GrCaps& caps);
230 
231     void forwardCombine(const GrCaps&);
232 
233     uint32_t                       fLastClipStackGenID;
234     SkIRect                        fLastDevClipBounds;
235     int                            fLastClipNumAnalyticFPs;
236 
237     // We must track if we have a wait op so that we don't delete the op when we have a full clear.
238     bool fHasWaitOp = false;;
239 
240     // For ops/opList we have mean: 5 stdDev: 28
241     SkSTArray<25, OpChain, true> fOpChains;
242 
243     // MDB TODO: 4096 for the first allocation of the clip space will be huge overkill.
244     // Gather statistics to determine the correct size.
245     SkArenaAlloc                   fClipAllocator{4096};
246     SkDEBUGCODE(int                fNumClips;)
247 
248     typedef GrOpList INHERITED;
249 };
250 
251 #endif
252