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