1 /* 2 * Copyright 2019 Google LLC 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 GrRenderTask_DEFINED 9 #define GrRenderTask_DEFINED 10 11 #include "include/core/SkRefCnt.h" 12 #include "include/private/SkColorData.h" 13 #include "include/private/SkTDArray.h" 14 #include "src/gpu/GrSurfaceProxyView.h" 15 #include "src/gpu/GrTextureProxy.h" 16 #include "src/gpu/GrTextureResolveManager.h" 17 #include "src/gpu/ops/GrOp.h" 18 19 class GrOpFlushState; 20 class GrOpsTask; 21 class GrResourceAllocator; 22 class GrTextureResolveRenderTask; 23 24 // This class abstracts a task that targets a single GrSurfaceProxy, participates in the 25 // GrDrawingManager's DAG, and implements the onExecute method to modify its target proxy's 26 // contents. (e.g., an opsTask that executes a command buffer, a task to regenerate mipmaps, etc.) 27 class GrRenderTask : public SkRefCnt { 28 public: 29 GrRenderTask(); 30 SkDEBUGCODE(~GrRenderTask() override); 31 32 void makeClosed(const GrCaps&); 33 prePrepare(GrRecordingContext * context)34 void prePrepare(GrRecordingContext* context) { this->onPrePrepare(context); } 35 36 // These two methods are only invoked at flush time 37 void prepare(GrOpFlushState* flushState); execute(GrOpFlushState * flushState)38 bool execute(GrOpFlushState* flushState) { return this->onExecute(flushState); } 39 40 // Called when this class will survive a flush and needs to truncate its ops and start over. 41 // TODO: ultimately it should be invalid for an op list to survive a flush. 42 // https://bugs.chromium.org/p/skia/issues/detail?id=7111 endFlush(GrDrawingManager *)43 virtual void endFlush(GrDrawingManager*) {} 44 45 // This method "disowns" all the GrSurfaceProxies this RenderTask modifies. In 46 // practice this just means telling the drawingManager to forget the relevant 47 // mappings from surface proxy to last modifying rendertask. 48 virtual void disown(GrDrawingManager*); 49 isClosed()50 bool isClosed() const { return this->isSetFlag(kClosed_Flag); } 51 52 /* 53 * Notify this GrRenderTask that it relies on the contents of 'dependedOn' 54 */ 55 void addDependency(GrDrawingManager*, GrSurfaceProxy* dependedOn, GrMipmapped, 56 GrTextureResolveManager, const GrCaps& caps); 57 58 /* 59 * Notify this GrRenderTask that it relies on the contents of all GrRenderTasks which otherTask 60 * depends on. 61 */ 62 void addDependenciesFromOtherTask(GrRenderTask* otherTask); 63 64 /* 65 * Does this renderTask depend on 'dependedOn'? 66 */ 67 bool dependsOn(const GrRenderTask* dependedOn) const; 68 uniqueID()69 uint32_t uniqueID() const { return fUniqueID; } numTargets()70 int numTargets() const { return fTargets.count(); } target(int i)71 const GrSurfaceProxyView& target(int i) const { return fTargets[i]; } 72 73 /* 74 * Safely cast this GrRenderTask to a GrOpsTask (if possible). 75 */ asOpsTask()76 virtual GrOpsTask* asOpsTask() { return nullptr; } 77 78 #if GR_TEST_UTILS 79 /* 80 * Dump out the GrRenderTask dependency DAG 81 */ 82 virtual void dump(bool printDependencies) const; 83 virtual const char* name() const = 0; 84 #endif 85 86 #ifdef SK_DEBUG numClips()87 virtual int numClips() const { return 0; } 88 89 virtual void visitProxies_debugOnly(const GrOp::VisitProxyFunc&) const = 0; 90 visitTargetAndSrcProxies_debugOnly(const GrOp::VisitProxyFunc & fn)91 void visitTargetAndSrcProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const { 92 this->visitProxies_debugOnly(fn); 93 for (int i = 0; i < this->numTargets(); ++i) { 94 fn(this->target(i).proxy(), GrMipmapped::kNo); 95 } 96 } 97 #endif 98 99 protected: 100 // In addition to just the GrSurface being allocated, has the stencil buffer been allocated (if 101 // it is required)? 102 bool isInstantiated() const; 103 104 SkDEBUGCODE(bool deferredProxiesAreInstantiated() const;) 105 106 // Add a target surface proxy to the list of targets for this task. 107 // This also informs the drawing manager to update the lastRenderTask association. 108 void addTarget(GrDrawingManager*, GrSurfaceProxyView); 109 110 enum class ExpectedOutcome : bool { 111 kTargetUnchanged, 112 kTargetDirty, 113 }; 114 115 // Performs any work to finalize this renderTask prior to execution. If returning 116 // ExpectedOutcome::kTargetDiry, the caller is also responsible to fill out the area it will 117 // modify in targetUpdateBounds. 118 // 119 // targetUpdateBounds must not extend beyond the proxy bounds. 120 virtual ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect* targetUpdateBounds) = 0; 121 122 SkSTArray<1, GrSurfaceProxyView> fTargets; 123 124 // List of texture proxies whose contents are being prepared on a worker thread 125 // TODO: this list exists so we can fire off the proper upload when an renderTask begins 126 // executing. Can this be replaced? 127 SkTArray<GrTextureProxy*, true> fDeferredProxies; 128 129 private: 130 // for resetFlag, TopoSortTraits, gatherProxyIntervals, handleInternalAllocationFailure 131 friend class GrDrawingManager; 132 133 // Drops any pending operations that reference proxies that are not instantiated. 134 // NOTE: Derived classes don't need to check targets. That is handled when the 135 // drawingManager calls isInstantiated. 136 virtual void handleInternalAllocationFailure() = 0; 137 138 // Derived classes can override to indicate usage of proxies _other than target proxies_. 139 // GrRenderTask itself will handle checking the target proxies. 140 virtual bool onIsUsed(GrSurfaceProxy*) const = 0; 141 isUsed(GrSurfaceProxy * proxy)142 bool isUsed(GrSurfaceProxy* proxy) const { 143 for (const GrSurfaceProxyView& target : fTargets) { 144 if (target.proxy() == proxy) { 145 return true; 146 } 147 } 148 149 return this->onIsUsed(proxy); 150 } 151 152 void addDependency(GrRenderTask* dependedOn); 153 void addDependent(GrRenderTask* dependent); 154 SkDEBUGCODE(bool isDependedent(const GrRenderTask* dependent) const;) 155 SkDEBUGCODE(void validate() const;) 156 void closeThoseWhoDependOnMe(const GrCaps&); 157 158 // Feed proxy usage intervals to the GrResourceAllocator class 159 virtual void gatherProxyIntervals(GrResourceAllocator*) const = 0; 160 161 static uint32_t CreateUniqueID(); 162 163 enum Flags { 164 kClosed_Flag = 0x01, //!< This task can't accept any more dependencies. 165 kDisowned_Flag = 0x02, //!< This task is disowned by its creating GrDrawingManager. 166 167 kWasOutput_Flag = 0x04, //!< Flag for topological sorting 168 kTempMark_Flag = 0x08, //!< Flag for topological sorting 169 }; 170 setFlag(uint32_t flag)171 void setFlag(uint32_t flag) { 172 fFlags |= flag; 173 } 174 resetFlag(uint32_t flag)175 void resetFlag(uint32_t flag) { 176 fFlags &= ~flag; 177 } 178 isSetFlag(uint32_t flag)179 bool isSetFlag(uint32_t flag) const { 180 return SkToBool(fFlags & flag); 181 } 182 183 struct TopoSortTraits { OutputTopoSortTraits184 static void Output(GrRenderTask* renderTask, int /* index */) { 185 renderTask->setFlag(kWasOutput_Flag); 186 } WasOutputTopoSortTraits187 static bool WasOutput(const GrRenderTask* renderTask) { 188 return renderTask->isSetFlag(kWasOutput_Flag); 189 } SetTempMarkTopoSortTraits190 static void SetTempMark(GrRenderTask* renderTask) { 191 renderTask->setFlag(kTempMark_Flag); 192 } ResetTempMarkTopoSortTraits193 static void ResetTempMark(GrRenderTask* renderTask) { 194 renderTask->resetFlag(kTempMark_Flag); 195 } IsTempMarkedTopoSortTraits196 static bool IsTempMarked(const GrRenderTask* renderTask) { 197 return renderTask->isSetFlag(kTempMark_Flag); 198 } NumDependenciesTopoSortTraits199 static int NumDependencies(const GrRenderTask* renderTask) { 200 return renderTask->fDependencies.count(); 201 } DependencyTopoSortTraits202 static GrRenderTask* Dependency(GrRenderTask* renderTask, int index) { 203 return renderTask->fDependencies[index]; 204 } 205 }; 206 207 // Only the GrOpsTask currently overrides this virtual onPrePrepare(GrRecordingContext *)208 virtual void onPrePrepare(GrRecordingContext*) {} onPrepare(GrOpFlushState *)209 virtual void onPrepare(GrOpFlushState*) {} // Only the GrOpsTask overrides this virtual 210 virtual bool onExecute(GrOpFlushState* flushState) = 0; 211 212 const uint32_t fUniqueID; 213 uint32_t fFlags; 214 215 // 'this' GrRenderTask relies on the output of the GrRenderTasks in 'fDependencies' 216 SkSTArray<1, GrRenderTask*, true> fDependencies; 217 // 'this' GrRenderTask's output is relied on by the GrRenderTasks in 'fDependents' 218 SkSTArray<1, GrRenderTask*, true> fDependents; 219 220 // For performance reasons, we should perform texture resolves back-to-back as much as possible. 221 // (http://skbug.com/9406). To accomplish this, we make and reuse one single resolve task for 222 // each render task, then add it as a dependency during makeClosed(). 223 GrTextureResolveRenderTask* fTextureResolveTask = nullptr; 224 225 SkDEBUGCODE(GrDrawingManager *fDrawingMgr = nullptr;) 226 }; 227 228 #endif 229