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
15class GrOpFlushState;
16class GrFixedClip;
17class GrGpu;
18class GrPipeline;
19class GrPrimitiveProcessor;
20class GrProgramInfo;
21class GrRenderTarget;
22class GrSemaphore;
23struct SkIRect;
24struct 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 */
31class GrOpsRenderPass {
32public:
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
134protected:
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
158private:
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