1 /* 2 * Copyright 2016 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 GrOpsRenderPass_DEFINED 9 #define GrOpsRenderPass_DEFINED 10 11 #include "include/core/SkBlurTypes.h" 12 #include "include/core/SkDrawable.h" 13 #include "src/gpu/GrDeferredUpload.h" 14 #include "src/gpu/GrPipeline.h" 15 16 class GrOpFlushState; 17 class GrGpu; 18 class GrPipeline; 19 class GrGeometryProcessor; 20 class GrProgramInfo; 21 class GrRenderTarget; 22 class GrScissorState; 23 class GrSemaphore; 24 struct SkIRect; 25 struct SkRect; 26 27 /** 28 * The GrOpsRenderPass is a series of commands (draws, clears, and discards), which all target the 29 * same render target. It is possible that these commands execute immediately (GL), or get buffered 30 * up for later execution (Vulkan). GrOps execute into a GrOpsRenderPass. 31 */ 32 class GrOpsRenderPass { 33 public: ~GrOpsRenderPass()34 virtual ~GrOpsRenderPass() {} 35 36 struct LoadAndStoreInfo { 37 GrLoadOp fLoadOp; 38 GrStoreOp fStoreOp; 39 std::array<float, 4> fClearColor; 40 }; 41 42 // Load-time clears of the stencil buffer are always to 0 so we don't store 43 // an 'fStencilClearValue' 44 struct StencilLoadAndStoreInfo { 45 GrLoadOp fLoadOp; 46 GrStoreOp fStoreOp; 47 }; 48 49 void begin(); 50 // Signals the end of recording to the GrOpsRenderPass and that it can now be submitted. 51 void end(); 52 53 // Updates the internal pipeline state for drawing with the provided GrProgramInfo. Enters an 54 // internal "bad" state if the pipeline could not be set. 55 void bindPipeline(const GrProgramInfo&, const SkRect& drawBounds); 56 57 // The scissor rect is always dynamic state and therefore not stored on GrPipeline. If scissor 58 // test is enabled on the current pipeline, then the client must call setScissorRect() before 59 // drawing. The scissor rect may also be updated between draws without having to bind a new 60 // pipeline. 61 void setScissorRect(const SkIRect&); 62 63 // Binds textures for the primitive processor and any FP on the GrPipeline. Texture bindings are 64 // dynamic state and therefore not set during bindPipeline(). If the current program uses 65 // textures, then the client must call bindTextures() before drawing. The primitive processor 66 // textures may also be updated between draws by calling bindTextures() again with a different 67 // array for primProcTextures. (On subsequent calls, if the backend is capable of updating the 68 // primitive processor textures independently, then it will automatically skip re-binding 69 // FP textures from GrPipeline.) 70 // 71 // If the current program does not use textures, this is a no-op. 72 void bindTextures(const GrGeometryProcessor&, 73 const GrSurfaceProxy* const geomProcTextures[], 74 const GrPipeline&); 75 76 void bindBuffers(sk_sp<const GrBuffer> indexBuffer, sk_sp<const GrBuffer> instanceBuffer, 77 sk_sp<const GrBuffer> vertexBuffer, GrPrimitiveRestart = GrPrimitiveRestart::kNo); 78 79 // The next several draw*() methods issue draws using the current pipeline state. Before 80 // drawing, the caller must configure the pipeline and dynamic state: 81 // 82 // - Call bindPipeline() 83 // - If the scissor test is enabled, call setScissorRect() 84 // - If the current program uses textures, call bindTextures() 85 // - Call bindBuffers() (even if all buffers are null) 86 void draw(int vertexCount, int baseVertex); 87 void drawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue, uint16_t maxIndexValue, 88 int baseVertex); 89 90 // Requires caps.drawInstancedSupport(). 91 void drawInstanced(int instanceCount, int baseInstance, int vertexCount, int baseVertex); 92 93 // Requires caps.drawInstancedSupport(). 94 void drawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance, 95 int baseVertex); 96 97 // Executes multiple draws from an array of GrDrawIndirectCommand in the provided buffer. 98 // 99 // Requires caps.drawInstancedSupport(). 100 // 101 // If caps.nativeDrawIndirectSupport() is unavailable, then 'drawIndirectBuffer' must be a 102 // GrCpuBuffer in order to polyfill. Performance may suffer in this scenario. 103 void drawIndirect(const GrBuffer* drawIndirectBuffer, size_t bufferOffset, int drawCount); 104 105 // Executes multiple draws from an array of GrDrawIndexedIndirectCommand in the provided buffer. 106 // 107 // Requires caps.drawInstancedSupport(). 108 // 109 // If caps.nativeDrawIndirectSupport() is unavailable, then 'drawIndirectBuffer' must be a 110 // GrCpuBuffer in order to polyfill. Performance may suffer in this scenario. 111 void drawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t bufferOffset, 112 int drawCount); 113 114 // This is a helper method for drawing a repeating pattern of vertices. The bound index buffer 115 // is understood to contain 'maxPatternRepetitionsInIndexBuffer' repetitions of the pattern. 116 // If more repetitions are required, then we loop. 117 void drawIndexPattern(int patternIndexCount, int patternRepeatCount, 118 int maxPatternRepetitionsInIndexBuffer, int patternVertexCount, 119 int baseVertex); 120 121 // Performs an upload of vertex data in the middle of a set of a set of draws 122 virtual void inlineUpload(GrOpFlushState*, GrDeferredTextureUploadFn&) = 0; 123 124 /** 125 * Clear the owned render target. Clears the full target if 'scissor' is disabled, otherwise it 126 * is restricted to 'scissor'. Must check caps.performPartialClearsAsDraws() before using an 127 * enabled scissor test; must check caps.performColorClearsAsDraws() before using this at all. 128 */ 129 void clear(const GrScissorState& scissor, std::array<float, 4> color); 130 131 /** 132 * Same as clear() but modifies the stencil; check caps.performStencilClearsAsDraws() and 133 * caps.performPartialClearsAsDraws(). 134 */ 135 void clearStencilClip(const GrScissorState& scissor, bool insideStencilMask); 136 137 /** 138 * Executes the SkDrawable object for the underlying backend. 139 */ 140 void executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>); 141 142 void drawBlurImage(const GrSurfaceProxyView& proxyView, SkBlurArg& blurArg); 143 144 protected: GrOpsRenderPass()145 GrOpsRenderPass() : fOrigin(kTopLeft_GrSurfaceOrigin), fRenderTarget(nullptr) {} 146 GrOpsRenderPass(GrRenderTarget * rt,GrSurfaceOrigin origin)147 GrOpsRenderPass(GrRenderTarget* rt, GrSurfaceOrigin origin) 148 : fOrigin(origin) 149 , fRenderTarget(rt) { 150 } 151 set(GrRenderTarget * rt,GrSurfaceOrigin origin)152 void set(GrRenderTarget* rt, GrSurfaceOrigin origin) { 153 SkASSERT(!fRenderTarget); 154 155 fRenderTarget = rt; 156 fOrigin = origin; 157 } 158 159 GrSurfaceOrigin fOrigin; 160 GrRenderTarget* fRenderTarget; 161 162 // Backends may defer binding of certain buffers if their draw API requires a buffer, or if 163 // their bind methods don't support base values. 164 sk_sp<const GrBuffer> fActiveIndexBuffer; 165 sk_sp<const GrBuffer> fActiveVertexBuffer; 166 sk_sp<const GrBuffer> fActiveInstanceBuffer; 167 168 private: 169 virtual GrGpu* gpu() = 0; 170 resetActiveBuffers()171 void resetActiveBuffers() { 172 fActiveIndexBuffer.reset(); 173 fActiveInstanceBuffer.reset(); 174 fActiveVertexBuffer.reset(); 175 } 176 177 bool prepareToDraw(); 178 179 // overridden by backend-specific derived class to perform the rendering command. onBegin()180 virtual void onBegin() {} onEnd()181 virtual void onEnd() {} 182 virtual bool onBindPipeline(const GrProgramInfo&, const SkRect& drawBounds) = 0; 183 virtual void onSetScissorRect(const SkIRect&) = 0; 184 virtual bool onBindTextures(const GrGeometryProcessor&, 185 const GrSurfaceProxy* const geomProcTextures[], 186 const GrPipeline&) = 0; 187 virtual void onBindBuffers(sk_sp<const GrBuffer> indexBuffer, sk_sp<const GrBuffer> instanceBuffer, 188 sk_sp<const GrBuffer> vertexBuffer, GrPrimitiveRestart) = 0; 189 virtual void onDraw(int vertexCount, int baseVertex) = 0; 190 virtual void onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue, 191 uint16_t maxIndexValue, int baseVertex) = 0; 192 virtual void onDrawInstanced(int instanceCount, int baseInstance, int vertexCount, 193 int baseVertex) = 0; 194 virtual void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, 195 int baseInstance, int baseVertex) = 0; onDrawIndirect(const GrBuffer *,size_t offset,int drawCount)196 virtual void onDrawIndirect(const GrBuffer*, size_t offset, int drawCount) { 197 SK_ABORT("Not implemented."); // Only called if caps.nativeDrawIndirectSupport(). 198 } onDrawIndexedIndirect(const GrBuffer *,size_t offset,int drawCount)199 virtual void onDrawIndexedIndirect(const GrBuffer*, size_t offset, int drawCount) { 200 SK_ABORT("Not implemented."); // Only called if caps.nativeDrawIndirectSupport(). 201 } 202 virtual void onClear(const GrScissorState&, std::array<float, 4> color) = 0; 203 virtual void onClearStencilClip(const GrScissorState&, bool insideStencilMask) = 0; onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>)204 virtual void onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) {} onDrawBlurImage(const GrSurfaceProxyView & proxyView,const SkBlurArg & blurArg)205 virtual void onDrawBlurImage(const GrSurfaceProxyView& proxyView, const SkBlurArg& blurArg) {}; 206 207 enum class DrawPipelineStatus { 208 kOk = 0, 209 kNotConfigured, 210 kFailedToBind 211 }; 212 213 DrawPipelineStatus fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured; 214 GrXferBarrierType fXferBarrierType; 215 216 #ifdef SK_DEBUG 217 enum class DynamicStateStatus { 218 kDisabled, 219 kUninitialized, 220 kConfigured 221 }; 222 223 DynamicStateStatus fScissorStatus; 224 DynamicStateStatus fTextureBindingStatus; 225 bool fHasIndexBuffer; 226 DynamicStateStatus fInstanceBufferStatus; 227 DynamicStateStatus fVertexBufferStatus; 228 #endif 229 230 using INHERITED = GrOpsRenderPass; 231 }; 232 233 #endif 234