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 addWaitOp(std::unique_ptr<GrOp> op,const GrCaps & caps)75 void addWaitOp(std::unique_ptr<GrOp> op, const GrCaps& caps) { 76 fHasWaitOp= true; 77 this->addOp(std::move(op), caps); 78 } 79 addDrawOp(std::unique_ptr<GrDrawOp> op,const GrProcessorSet::Analysis & processorAnalysis,GrAppliedClip && clip,const DstProxy & dstProxy,const GrCaps & caps)80 void addDrawOp(std::unique_ptr<GrDrawOp> op, const GrProcessorSet::Analysis& processorAnalysis, 81 GrAppliedClip&& clip, const DstProxy& dstProxy, const GrCaps& caps) { 82 auto addDependency = [ &caps, this ] (GrSurfaceProxy* p) { 83 this->addDependency(p, caps); 84 }; 85 86 op->visitProxies(addDependency); 87 clip.visitProxies(addDependency); 88 if (dstProxy.proxy()) { 89 addDependency(dstProxy.proxy()); 90 } 91 92 this->recordOp(std::move(op), processorAnalysis, clip.doesClip() ? &clip : nullptr, 93 &dstProxy, caps); 94 } 95 96 void discard(); 97 98 /** 99 * Copies a pixel rectangle from one surface to another. This call may finalize 100 * reserved vertex/index data (as though a draw call was made). The src pixels 101 * copied are specified by srcRect. They are copied to a rect of the same 102 * size in dst with top left at dstPoint. If the src rect is clipped by the 103 * src bounds then pixel values in the dst rect corresponding to area clipped 104 * by the src rect are not overwritten. This method is not guaranteed to succeed 105 * depending on the type of surface, configs, etc, and the backend-specific 106 * limitations. 107 */ 108 bool copySurface(GrRecordingContext*, 109 GrSurfaceProxy* dst, 110 GrSurfaceProxy* src, 111 const SkIRect& srcRect, 112 const SkIPoint& dstPoint) 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 // Must only be called if native stencil buffer clearing is enabled 130 void setStencilLoadOp(GrLoadOp op); 131 // Must only be called if native color buffer clearing is enabled. 132 void setColorLoadOp(GrLoadOp op, const SkPMColor4f& color); 133 // Sets the clear color to transparent black setColorLoadOp(GrLoadOp op)134 void setColorLoadOp(GrLoadOp op) { 135 static const SkPMColor4f kDefaultClearColor = {0.f, 0.f, 0.f, 0.f}; 136 this->setColorLoadOp(op, kDefaultClearColor); 137 } 138 139 // Perform book-keeping for a fullscreen clear, regardless of how the clear is implemented later 140 // (i.e. setColorLoadOp(), adding a ClearOp, or adding a GrFillRectOp that covers the device). 141 // Returns true if the clear can be converted into a load op (barring device caps). 142 bool resetForFullscreenClear(); 143 144 void deleteOps(); 145 146 class OpChain { 147 public: 148 OpChain(const OpChain&) = delete; 149 OpChain& operator=(const OpChain&) = delete; 150 OpChain(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*, const DstProxy*); 151 ~OpChain()152 ~OpChain() { 153 // The ops are stored in a GrMemoryPool and must be explicitly deleted via the pool. 154 SkASSERT(fList.empty()); 155 } 156 157 void visitProxies(const GrOp::VisitProxyFunc&, GrOp::VisitorType) const; 158 head()159 GrOp* head() const { return fList.head(); } 160 appliedClip()161 GrAppliedClip* appliedClip() const { return fAppliedClip; } dstProxy()162 const DstProxy& dstProxy() const { return fDstProxy; } bounds()163 const SkRect& bounds() const { return fBounds; } 164 165 // Deletes all the ops in the chain via the pool. 166 void deleteOps(GrOpMemoryPool* pool); 167 168 // Attempts to move the ops from the passed chain to this chain at the head. Also attempts 169 // to merge ops between the chains. Upon success the passed chain is empty. 170 // Fails when the chains aren't of the same op type, have different clips or dst proxies. 171 bool prependChain(OpChain*, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*); 172 173 // Attempts to add 'op' to this chain either by merging or adding to the tail. Returns 174 // 'op' to the caller upon failure, otherwise null. Fails when the op and chain aren't of 175 // the same op type, have different clips or dst proxies. 176 std::unique_ptr<GrOp> appendOp(std::unique_ptr<GrOp> op, GrProcessorSet::Analysis, 177 const DstProxy*, const GrAppliedClip*, const GrCaps&, 178 GrOpMemoryPool*, GrAuditTrail*); 179 180 private: 181 class List { 182 public: 183 List() = default; 184 List(std::unique_ptr<GrOp>); 185 List(List&&); 186 List& operator=(List&& that); 187 empty()188 bool empty() const { return !SkToBool(fHead); } head()189 GrOp* head() const { return fHead.get(); } tail()190 GrOp* tail() const { return fTail; } 191 192 std::unique_ptr<GrOp> popHead(); 193 std::unique_ptr<GrOp> removeOp(GrOp* op); 194 void pushHead(std::unique_ptr<GrOp> op); 195 void pushTail(std::unique_ptr<GrOp>); 196 197 void validate() const; 198 199 private: 200 std::unique_ptr<GrOp> fHead; 201 GrOp* fTail = nullptr; 202 }; 203 204 void validate() const; 205 206 bool tryConcat(List*, GrProcessorSet::Analysis, const DstProxy&, const GrAppliedClip*, 207 const SkRect& bounds, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*); 208 static List DoConcat(List, List, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*); 209 210 List fList; 211 GrProcessorSet::Analysis fProcessorAnalysis; 212 DstProxy fDstProxy; 213 GrAppliedClip* fAppliedClip; 214 SkRect fBounds; 215 }; 216 217 void purgeOpsWithUninstantiatedProxies() override; 218 219 void gatherProxyIntervals(GrResourceAllocator*) const override; 220 221 void recordOp(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*, const DstProxy*, 222 const GrCaps& caps); 223 224 void forwardCombine(const GrCaps&); 225 226 uint32_t fLastClipStackGenID; 227 SkIRect fLastDevClipBounds; 228 int fLastClipNumAnalyticFPs; 229 230 // We must track if we have a wait op so that we don't delete the op when we have a full clear. 231 bool fHasWaitOp = false;; 232 233 // For ops/opList we have mean: 5 stdDev: 28 234 SkSTArray<25, OpChain, true> fOpChains; 235 236 // MDB TODO: 4096 for the first allocation of the clip space will be huge overkill. 237 // Gather statistics to determine the correct size. 238 SkArenaAlloc fClipAllocator{4096}; 239 SkDEBUGCODE(int fNumClips;) 240 241 typedef GrOpList INHERITED; 242 }; 243 244 #endif 245