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