• 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 "GrAppliedClip.h"
12 #include "GrOpList.h"
13 #include "GrPathRendering.h"
14 #include "GrPrimitiveProcessor.h"
15 #include "ops/GrOp.h"
16 #include "ops/GrDrawOp.h"
17 #include "SkArenaAlloc.h"
18 #include "SkClipStack.h"
19 #include "SkMatrix.h"
20 #include "SkStringUtils.h"
21 #include "SkStrokeRec.h"
22 #include "SkTArray.h"
23 #include "SkTLazy.h"
24 #include "SkTypes.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(GrResourceProvider*, sk_sp<GrOpMemoryPool>,
37                          GrRenderTargetProxy*, GrAuditTrail*);
38 
39     ~GrRenderTargetOpList() override;
40 
makeClosed(const GrCaps & caps)41     void makeClosed(const GrCaps& caps) override {
42         if (this->isClosed()) {
43             return;
44         }
45 
46         this->forwardCombine(caps);
47 
48         INHERITED::makeClosed(caps);
49     }
50 
isEmpty()51     bool isEmpty() const { return fOpChains.empty(); }
52 
53     /**
54      * Empties the draw buffer of any queued up draws.
55      */
56     void endFlush() override;
57 
58     /**
59      * Together these two functions flush all queued up draws to GrCommandBuffer. The return value
60      * of executeOps() indicates whether any commands were actually issued to the GPU.
61      */
62     void onPrepare(GrOpFlushState* flushState) override;
63     bool onExecute(GrOpFlushState* flushState) override;
64 
addOp(std::unique_ptr<GrOp> op,const GrCaps & caps)65     void addOp(std::unique_ptr<GrOp> op, const GrCaps& caps) {
66         auto addDependency = [ &caps, this ] (GrSurfaceProxy* p) {
67             this->addDependency(p, caps);
68         };
69 
70         op->visitProxies(addDependency);
71 
72         this->recordOp(std::move(op), GrProcessorSet::EmptySetAnalysis(), nullptr, nullptr, caps);
73     }
74 
addDrawOp(std::unique_ptr<GrDrawOp> op,const GrProcessorSet::Analysis & processorAnalysis,GrAppliedClip && clip,const DstProxy & dstProxy,const GrCaps & caps)75     void addDrawOp(std::unique_ptr<GrDrawOp> op, const GrProcessorSet::Analysis& processorAnalysis,
76                    GrAppliedClip&& clip, const DstProxy& dstProxy, const GrCaps& caps) {
77         auto addDependency = [ &caps, this ] (GrSurfaceProxy* p) {
78             this->addDependency(p, caps);
79         };
80 
81         op->visitProxies(addDependency);
82         clip.visitProxies(addDependency);
83         if (dstProxy.proxy()) {
84             addDependency(dstProxy.proxy());
85         }
86 
87         this->recordOp(std::move(op), processorAnalysis, clip.doesClip() ? &clip : nullptr,
88                        &dstProxy, caps);
89     }
90 
91     void discard();
92 
93     /**
94      * Copies a pixel rectangle from one surface to another. This call may finalize
95      * reserved vertex/index data (as though a draw call was made). The src pixels
96      * copied are specified by srcRect. They are copied to a rect of the same
97      * size in dst with top left at dstPoint. If the src rect is clipped by the
98      * src bounds then  pixel values in the dst rect corresponding to area clipped
99      * by the src rect are not overwritten. This method is not guaranteed to succeed
100      * depending on the type of surface, configs, etc, and the backend-specific
101      * limitations.
102      */
103     bool copySurface(GrContext*,
104                      GrSurfaceProxy* dst,
105                      GrSurfaceProxy* src,
106                      const SkIRect& srcRect,
107                      const SkIPoint& dstPoint) override;
108 
asRenderTargetOpList()109     GrRenderTargetOpList* asRenderTargetOpList() override { return this; }
110 
111     SkDEBUGCODE(void dump(bool printDependencies) const override;)
112     SkDEBUGCODE(int numClips() const override { return fNumClips; })
113     SkDEBUGCODE(void visitProxies_debugOnly(const GrOp::VisitProxyFunc&) const;)
114 
115 private:
116     friend class GrRenderTargetContextPriv; // for stencil clip state. TODO: this is invasive
117 
118     // The RTC and RTOpList have to work together to handle buffer clears. In most cases, buffer
119     // clearing can be done natively, in which case the op list's load ops are sufficient. In other
120     // cases, draw ops must be used, which makes the RTC the best place for those decisions. This,
121     // however, requires that the RTC be able to coordinate with the op list to achieve similar ends
122     friend class GrRenderTargetContext;
123 
124     // Must only be called if native stencil buffer clearing is enabled
125     void setStencilLoadOp(GrLoadOp op);
126     // Must only be called if native color buffer clearing is enabled.
127     void setColorLoadOp(GrLoadOp op, const SkPMColor4f& color);
128     // Sets the clear color to transparent black
setColorLoadOp(GrLoadOp op)129     void setColorLoadOp(GrLoadOp op) {
130         static const SkPMColor4f kDefaultClearColor = {0.f, 0.f, 0.f, 0.f};
131         this->setColorLoadOp(op, kDefaultClearColor);
132     }
133 
134     // Perform book-keeping for a fullscreen clear, regardless of how the clear is implemented later
135     // (i.e. setColorLoadOp(), adding a ClearOp, or adding a GrFillRectOp that covers the device).
136     // Returns true if the clear can be converted into a load op (barring device caps).
137     bool resetForFullscreenClear();
138 
139     void deleteOps();
140 
141     class OpChain {
142     public:
143         OpChain(const OpChain&) = delete;
144         OpChain& operator=(const OpChain&) = delete;
145         OpChain(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*, const DstProxy*);
146 
~OpChain()147         ~OpChain() {
148             // The ops are stored in a GrMemoryPool and must be explicitly deleted via the pool.
149             SkASSERT(fList.empty());
150         }
151 
152         void visitProxies(const GrOp::VisitProxyFunc&, GrOp::VisitorType) const;
153 
head()154         GrOp* head() const { return fList.head(); }
155 
appliedClip()156         GrAppliedClip* appliedClip() const { return fAppliedClip; }
dstProxy()157         const DstProxy& dstProxy() const { return fDstProxy; }
bounds()158         const SkRect& bounds() const { return fBounds; }
159 
160         // Deletes all the ops in the chain via the pool.
161         void deleteOps(GrOpMemoryPool* pool);
162 
163         // Attempts to move the ops from the passed chain to this chain at the head. Also attempts
164         // to merge ops between the chains. Upon success the passed chain is empty.
165         // Fails when the chains aren't of the same op type, have different clips or dst proxies.
166         bool prependChain(OpChain*, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*);
167 
168         // Attempts to add 'op' to this chain either by merging or adding to the tail. Returns
169         // 'op' to the caller upon failure, otherwise null. Fails when the op and chain aren't of
170         // the same op type, have different clips or dst proxies.
171         std::unique_ptr<GrOp> appendOp(std::unique_ptr<GrOp> op, GrProcessorSet::Analysis,
172                                        const DstProxy*, const GrAppliedClip*, const GrCaps&,
173                                        GrOpMemoryPool*, GrAuditTrail*);
174 
175     private:
176         class List {
177         public:
178             List() = default;
179             List(std::unique_ptr<GrOp>);
180             List(List&&);
181             List& operator=(List&& that);
182 
empty()183             bool empty() const { return !SkToBool(fHead); }
head()184             GrOp* head() const { return fHead.get(); }
tail()185             GrOp* tail() const { return fTail; }
186 
187             std::unique_ptr<GrOp> popHead();
188             std::unique_ptr<GrOp> removeOp(GrOp* op);
189             void pushHead(std::unique_ptr<GrOp> op);
190             void pushTail(std::unique_ptr<GrOp>);
191 
192             void validate() const;
193 
194         private:
195             std::unique_ptr<GrOp> fHead;
196             GrOp* fTail = nullptr;
197         };
198 
199         void validate() const;
200 
201         bool tryConcat(List*, GrProcessorSet::Analysis, const DstProxy&, const GrAppliedClip*,
202                        const SkRect& bounds, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*);
203         static List DoConcat(List, List, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*);
204 
205         List fList;
206         GrProcessorSet::Analysis fProcessorAnalysis;
207         DstProxy fDstProxy;
208         GrAppliedClip* fAppliedClip;
209         SkRect fBounds;
210     };
211 
212     void purgeOpsWithUninstantiatedProxies() override;
213 
214     void gatherProxyIntervals(GrResourceAllocator*) const override;
215 
216     void recordOp(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*, const DstProxy*,
217                   const GrCaps& caps);
218 
219     void forwardCombine(const GrCaps&);
220 
221     uint32_t                       fLastClipStackGenID;
222     SkIRect                        fLastDevClipBounds;
223     int                            fLastClipNumAnalyticFPs;
224 
225     // For ops/opList we have mean: 5 stdDev: 28
226     SkSTArray<25, OpChain, true> fOpChains;
227 
228     // MDB TODO: 4096 for the first allocation of the clip space will be huge overkill.
229     // Gather statistics to determine the correct size.
230     SkArenaAlloc                   fClipAllocator{4096};
231     SkDEBUGCODE(int                fNumClips;)
232 
233     typedef GrOpList INHERITED;
234 };
235 
236 #endif
237