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