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 GrFixedClip; |
17 | class GrGpu; |
18 | class GrPipeline; |
19 | class GrPrimitiveProcessor; |
20 | class GrProgramInfo; |
21 | class GrRenderTarget; |
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(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer, |
75 | 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. Ignores the draw state and clip. |
124 | */ |
125 | void clear(const GrFixedClip&, const SkPMColor4f&); |
126 | |
127 | void clearStencilClip(const GrFixedClip&, bool insideStencilMask); |
128 | |
129 | /** |
130 | * Executes the SkDrawable object for the underlying backend. |
131 | */ |
132 | void executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>); |
133 | |
134 | protected: |
135 | GrOpsRenderPass() : fOrigin(kTopLeft_GrSurfaceOrigin), fRenderTarget(nullptr) {} |
136 | |
137 | GrOpsRenderPass(GrRenderTarget* rt, GrSurfaceOrigin origin) |
138 | : fOrigin(origin) |
139 | , fRenderTarget(rt) { |
140 | } |
141 | |
142 | void set(GrRenderTarget* rt, GrSurfaceOrigin origin) { |
143 | SkASSERT(!fRenderTarget); |
144 | |
145 | fRenderTarget = rt; |
146 | fOrigin = origin; |
147 | } |
148 | |
149 | GrSurfaceOrigin fOrigin; |
150 | GrRenderTarget* fRenderTarget; |
151 | |
152 | // Backends may defer binding of certain buffers if their draw API requires a buffer, or if |
153 | // their bind methods don't support base values. |
154 | sk_sp<const GrBuffer> fActiveIndexBuffer; |
155 | sk_sp<const GrBuffer> fActiveVertexBuffer; |
156 | sk_sp<const GrBuffer> fActiveInstanceBuffer; |
157 | |
158 | private: |
159 | virtual GrGpu* gpu() = 0; |
160 | |
161 | void resetActiveBuffers() { |
162 | fActiveIndexBuffer.reset(); |
163 | fActiveInstanceBuffer.reset(); |
164 | fActiveVertexBuffer.reset(); |
165 | } |
166 | |
167 | bool prepareToDraw(); |
168 | |
169 | // overridden by backend-specific derived class to perform the rendering command. |
170 | virtual void onBegin() {} |
171 | virtual void onEnd() {} |
172 | virtual bool onBindPipeline(const GrProgramInfo&, const SkRect& drawBounds) = 0; |
173 | virtual void onSetScissorRect(const SkIRect&) = 0; |
174 | virtual bool onBindTextures(const GrPrimitiveProcessor&, |
175 | const GrSurfaceProxy* const primProcTextures[], |
176 | const GrPipeline&) = 0; |
177 | virtual void onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer, |
178 | const GrBuffer* vertexBuffer, GrPrimitiveRestart) = 0; |
179 | virtual void onDraw(int vertexCount, int baseVertex) = 0; |
180 | virtual void onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue, |
181 | uint16_t maxIndexValue, int baseVertex) = 0; |
182 | virtual void onDrawInstanced(int instanceCount, int baseInstance, int vertexCount, |
183 | int baseVertex) = 0; |
184 | virtual void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, |
185 | int baseInstance, int baseVertex) = 0; |
186 | virtual void onDrawIndirect(const GrBuffer*, size_t offset, int drawCount) { |
187 | SK_ABORT("Not implemented." ); // Only called if caps.nativeDrawIndirectSupport(). |
188 | } |
189 | virtual void onDrawIndexedIndirect(const GrBuffer*, size_t offset, int drawCount) { |
190 | SK_ABORT("Not implemented." ); // Only called if caps.nativeDrawIndirectSupport(). |
191 | } |
192 | virtual void onClear(const GrFixedClip&, const SkPMColor4f&) = 0; |
193 | virtual void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) = 0; |
194 | virtual void onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) {} |
195 | |
196 | enum class DrawPipelineStatus { |
197 | kOk = 0, |
198 | kNotConfigured, |
199 | kFailedToBind |
200 | }; |
201 | |
202 | DrawPipelineStatus fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured; |
203 | GrXferBarrierType fXferBarrierType; |
204 | |
205 | #ifdef SK_DEBUG |
206 | enum class DynamicStateStatus { |
207 | kDisabled, |
208 | kUninitialized, |
209 | kConfigured |
210 | }; |
211 | |
212 | DynamicStateStatus fScissorStatus; |
213 | DynamicStateStatus fTextureBindingStatus; |
214 | bool fHasIndexBuffer; |
215 | DynamicStateStatus fInstanceBufferStatus; |
216 | DynamicStateStatus fVertexBufferStatus; |
217 | #endif |
218 | |
219 | typedef GrOpsRenderPass INHERITED; |
220 | }; |
221 | |
222 | #endif |
223 | |