1 /*
2 * Copyright 2017 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 #include "src/gpu/ganesh/gl/GrGLOpsRenderPass.h"
9
10 #include "src/gpu/ganesh/GrProgramInfo.h"
11 #include "src/gpu/ganesh/GrRenderTarget.h"
12
13 #ifdef SK_DEBUG
14 #include "include/gpu/GrDirectContext.h"
15 #include "src/gpu/ganesh/GrDirectContextPriv.h"
16 #endif
17
18 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
19
set(GrRenderTarget * rt,bool useMSAASurface,const SkIRect & contentBounds,GrSurfaceOrigin origin,const LoadAndStoreInfo & colorInfo,const StencilLoadAndStoreInfo & stencilInfo)20 void GrGLOpsRenderPass::set(GrRenderTarget* rt, bool useMSAASurface, const SkIRect& contentBounds,
21 GrSurfaceOrigin origin, const LoadAndStoreInfo& colorInfo,
22 const StencilLoadAndStoreInfo& stencilInfo) {
23 SkASSERT(fGpu);
24 SkASSERT(!fRenderTarget);
25 SkASSERT(fGpu == rt->getContext()->priv().getGpu());
26
27 this->INHERITED::set(rt, origin);
28 fUseMultisampleFBO = useMSAASurface;
29 fContentBounds = contentBounds;
30 fColorLoadAndStoreInfo = colorInfo;
31 fStencilLoadAndStoreInfo = stencilInfo;
32 }
33
dmsaaLoadStoreBounds() const34 GrNativeRect GrGLOpsRenderPass::dmsaaLoadStoreBounds() const {
35 if (fGpu->glCaps().framebufferResolvesMustBeFullSize()) {
36 // If frambeffer resolves have to be full size, then resolve the entire render target during
37 // load and store both, even if we will be doing so with a draw. We do this because we will
38 // have no other choice than to do a full size resolve at the end of the render pass, so the
39 // full DMSAA attachment needs to have valid content.
40 return GrNativeRect::MakeRelativeTo(fOrigin, fRenderTarget->height(),
41 SkIRect::MakeSize(fRenderTarget->dimensions()));
42 } else {
43 return GrNativeRect::MakeRelativeTo(fOrigin, fRenderTarget->height(), fContentBounds);
44 }
45 }
46
onBegin()47 void GrGLOpsRenderPass::onBegin() {
48 auto glRT = static_cast<GrGLRenderTarget*>(fRenderTarget);
49 if (fUseMultisampleFBO &&
50 fColorLoadAndStoreInfo.fLoadOp == GrLoadOp::kLoad &&
51 glRT->hasDynamicMSAAAttachment()) {
52 // Load the single sample fbo into the dmsaa attachment.
53 if (fGpu->glCaps().canResolveSingleToMSAA()) {
54 fGpu->resolveRenderFBOs(glRT, this->dmsaaLoadStoreBounds().asSkIRect(),
55 GrGLGpu::ResolveDirection::kSingleToMSAA);
56 } else {
57 fGpu->drawSingleIntoMSAAFBO(glRT, this->dmsaaLoadStoreBounds().asSkIRect());
58 }
59 }
60
61 fGpu->beginCommandBuffer(glRT, fUseMultisampleFBO, fContentBounds, fOrigin,
62 fColorLoadAndStoreInfo, fStencilLoadAndStoreInfo);
63 }
64
onEnd()65 void GrGLOpsRenderPass::onEnd() {
66 auto glRT = static_cast<GrGLRenderTarget*>(fRenderTarget);
67 fGpu->endCommandBuffer(glRT, fUseMultisampleFBO, fColorLoadAndStoreInfo,
68 fStencilLoadAndStoreInfo);
69
70 if (fUseMultisampleFBO &&
71 fColorLoadAndStoreInfo.fStoreOp == GrStoreOp::kStore &&
72 glRT->hasDynamicMSAAAttachment()) {
73 // Blit the msaa attachment into the single sample fbo.
74 fGpu->resolveRenderFBOs(glRT, this->dmsaaLoadStoreBounds().asSkIRect(),
75 GrGLGpu::ResolveDirection::kMSAAToSingle,
76 true /*invalidateReadBufferAfterBlit*/);
77 }
78 }
79
onBindPipeline(const GrProgramInfo & programInfo,const SkRect & drawBounds)80 bool GrGLOpsRenderPass::onBindPipeline(const GrProgramInfo& programInfo,
81 const SkRect& drawBounds) {
82 fPrimitiveType = programInfo.primitiveType();
83 return fGpu->flushGLState(fRenderTarget, fUseMultisampleFBO, programInfo);
84 }
85
onSetScissorRect(const SkIRect & scissor)86 void GrGLOpsRenderPass::onSetScissorRect(const SkIRect& scissor) {
87 fGpu->flushScissorRect(scissor, fRenderTarget->height(), fOrigin);
88 }
89
onBindTextures(const GrGeometryProcessor & geomProc,const GrSurfaceProxy * const geomProcTextures[],const GrPipeline & pipeline)90 bool GrGLOpsRenderPass::onBindTextures(const GrGeometryProcessor& geomProc,
91 const GrSurfaceProxy* const geomProcTextures[],
92 const GrPipeline& pipeline) {
93 GrGLProgram* program = fGpu->currentProgram();
94 SkASSERT(program);
95 program->bindTextures(geomProc, geomProcTextures, pipeline);
96 return true;
97 }
98
onBindBuffers(sk_sp<const GrBuffer> indexBuffer,sk_sp<const GrBuffer> instanceBuffer,sk_sp<const GrBuffer> vertexBuffer,GrPrimitiveRestart primitiveRestart)99 void GrGLOpsRenderPass::onBindBuffers(sk_sp<const GrBuffer> indexBuffer,
100 sk_sp<const GrBuffer> instanceBuffer,
101 sk_sp<const GrBuffer> vertexBuffer,
102 GrPrimitiveRestart primitiveRestart) {
103 SkASSERT((primitiveRestart == GrPrimitiveRestart::kNo) || indexBuffer);
104 GrGLProgram* program = fGpu->currentProgram();
105 SkASSERT(program);
106
107 #ifdef SK_DEBUG
108 fDidBindInstanceBuffer = false;
109 fDidBindVertexBuffer = false;
110 #endif
111
112 int numAttribs = program->numVertexAttributes() + program->numInstanceAttributes();
113 fAttribArrayState = fGpu->bindInternalVertexArray(indexBuffer.get(), numAttribs,
114 primitiveRestart);
115
116 if (indexBuffer) {
117 if (indexBuffer->isCpuBuffer()) {
118 auto* cpuIndexBuffer = static_cast<const GrCpuBuffer*>(indexBuffer.get());
119 fIndexPointer = reinterpret_cast<const uint16_t*>(cpuIndexBuffer->data());
120 } else {
121 fIndexPointer = nullptr;
122 }
123 }
124
125 // If this platform does not support baseInstance, defer binding of the instance buffer.
126 if (fGpu->glCaps().baseVertexBaseInstanceSupport()) {
127 this->bindInstanceBuffer(instanceBuffer.get(), 0);
128 SkDEBUGCODE(fDidBindInstanceBuffer = true;)
129 }
130 fActiveInstanceBuffer = std::move(instanceBuffer);
131
132 // We differ binding the vertex buffer for one of two situations:
133 // 1) This platform does not support baseVertex with indexed draws.
134 // 2) There is a driver bug affecting glDrawArrays.
135 if ((indexBuffer && fGpu->glCaps().baseVertexBaseInstanceSupport()) ||
136 (!indexBuffer && !fGpu->glCaps().drawArraysBaseVertexIsBroken())) {
137 this->bindVertexBuffer(vertexBuffer.get(), 0);
138 SkDEBUGCODE(fDidBindVertexBuffer = true;)
139 }
140 fActiveVertexBuffer = std::move(vertexBuffer);
141 fActiveIndexBuffer = std::move(indexBuffer);
142 }
143
bindInstanceBuffer(const GrBuffer * instanceBuffer,int baseInstance)144 void GrGLOpsRenderPass::bindInstanceBuffer(const GrBuffer* instanceBuffer, int baseInstance) {
145 GrGLProgram* program = fGpu->currentProgram();
146 SkASSERT(program);
147 if (int instanceStride = program->instanceStride()) {
148 SkASSERT(instanceBuffer);
149 SkASSERT(instanceBuffer->isCpuBuffer() ||
150 !static_cast<const GrGpuBuffer*>(instanceBuffer)->isMapped());
151 size_t bufferOffset = baseInstance * static_cast<size_t>(instanceStride);
152 int attribIdx = program->numVertexAttributes();
153 for (int i = 0; i < program->numInstanceAttributes(); ++i, ++attribIdx) {
154 const auto& attrib = program->instanceAttribute(i);
155 static constexpr int kDivisor = 1;
156 fAttribArrayState->set(fGpu, attrib.fLocation, instanceBuffer, attrib.fCPUType,
157 attrib.fGPUType, instanceStride, bufferOffset + attrib.fOffset,
158 kDivisor);
159 }
160 }
161 }
162
bindVertexBuffer(const GrBuffer * vertexBuffer,int baseVertex)163 void GrGLOpsRenderPass::bindVertexBuffer(const GrBuffer* vertexBuffer, int baseVertex) {
164 GrGLProgram* program = fGpu->currentProgram();
165 SkASSERT(program);
166 if (int vertexStride = program->vertexStride()) {
167 SkASSERT(vertexBuffer);
168 SkASSERT(vertexBuffer->isCpuBuffer() ||
169 !static_cast<const GrGpuBuffer*>(vertexBuffer)->isMapped());
170 size_t bufferOffset = baseVertex * static_cast<size_t>(vertexStride);
171 for (int i = 0; i < program->numVertexAttributes(); ++i) {
172 const auto& attrib = program->vertexAttribute(i);
173 static constexpr int kDivisor = 0;
174 fAttribArrayState->set(fGpu, attrib.fLocation, vertexBuffer, attrib.fCPUType,
175 attrib.fGPUType, vertexStride, bufferOffset + attrib.fOffset,
176 kDivisor);
177 }
178 }
179 }
180
onDraw(int vertexCount,int baseVertex)181 void GrGLOpsRenderPass::onDraw(int vertexCount, int baseVertex) {
182 SkASSERT(fDidBindVertexBuffer || fGpu->glCaps().drawArraysBaseVertexIsBroken());
183 GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
184 if (fGpu->glCaps().drawArraysBaseVertexIsBroken()) {
185 this->bindVertexBuffer(fActiveVertexBuffer.get(), baseVertex);
186 baseVertex = 0;
187 }
188 GL_CALL(DrawArrays(glPrimType, baseVertex, vertexCount));
189 fGpu->didDrawTo(fRenderTarget);
190 }
191
onDrawIndexed(int indexCount,int baseIndex,uint16_t minIndexValue,uint16_t maxIndexValue,int baseVertex)192 void GrGLOpsRenderPass::onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
193 uint16_t maxIndexValue, int baseVertex) {
194 GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
195 if (fGpu->glCaps().baseVertexBaseInstanceSupport()) {
196 SkASSERT(fGpu->glCaps().drawInstancedSupport());
197 SkASSERT(fDidBindVertexBuffer);
198 if (baseVertex != 0) {
199 GL_CALL(DrawElementsInstancedBaseVertexBaseInstance(
200 glPrimType, indexCount, GR_GL_UNSIGNED_SHORT,
201 this->offsetForBaseIndex(baseIndex), 1, baseVertex, 0));
202 return;
203 }
204 } else {
205 this->bindVertexBuffer(fActiveVertexBuffer.get(), baseVertex);
206 }
207
208 if (fGpu->glCaps().drawRangeElementsSupport()) {
209 GL_CALL(DrawRangeElements(glPrimType, minIndexValue, maxIndexValue, indexCount,
210 GR_GL_UNSIGNED_SHORT, this->offsetForBaseIndex(baseIndex)));
211 } else {
212 GL_CALL(DrawElements(glPrimType, indexCount, GR_GL_UNSIGNED_SHORT,
213 this->offsetForBaseIndex(baseIndex)));
214 }
215 fGpu->didDrawTo(fRenderTarget);
216 }
217
onDrawInstanced(int instanceCount,int baseInstance,int vertexCount,int baseVertex)218 void GrGLOpsRenderPass::onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
219 int baseVertex) {
220 SkASSERT(fDidBindVertexBuffer || fGpu->glCaps().drawArraysBaseVertexIsBroken());
221 if (fGpu->glCaps().drawArraysBaseVertexIsBroken()) {
222 // We weren't able to bind the vertex buffer during onBindBuffers because of a driver bug
223 // affecting glDrawArrays.
224 this->bindVertexBuffer(fActiveVertexBuffer.get(), 0);
225 }
226 int maxInstances = fGpu->glCaps().maxInstancesPerDrawWithoutCrashing(instanceCount);
227 for (int i = 0; i < instanceCount; i += maxInstances) {
228 GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
229 int instanceCountForDraw = std::min(instanceCount - i, maxInstances);
230 int baseInstanceForDraw = baseInstance + i;
231 if (fGpu->glCaps().baseVertexBaseInstanceSupport()) {
232 SkASSERT(fDidBindInstanceBuffer);
233 GL_CALL(DrawArraysInstancedBaseInstance(glPrimType, baseVertex, vertexCount,
234 instanceCountForDraw, baseInstanceForDraw));
235 } else {
236 this->bindInstanceBuffer(fActiveInstanceBuffer.get(), baseInstanceForDraw);
237 GL_CALL(DrawArraysInstanced(glPrimType, baseVertex, vertexCount, instanceCountForDraw));
238 }
239 }
240 fGpu->didDrawTo(fRenderTarget);
241 }
242
onDrawIndexedInstanced(int indexCount,int baseIndex,int instanceCount,int baseInstance,int baseVertex)243 void GrGLOpsRenderPass::onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
244 int baseInstance, int baseVertex) {
245 int maxInstances = fGpu->glCaps().maxInstancesPerDrawWithoutCrashing(instanceCount);
246 for (int i = 0; i < instanceCount; i += maxInstances) {
247 GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
248 int instanceCountForDraw = std::min(instanceCount - i, maxInstances);
249 int baseInstanceForDraw = baseInstance + i;
250 if (fGpu->glCaps().baseVertexBaseInstanceSupport()) {
251 SkASSERT(fDidBindInstanceBuffer);
252 SkASSERT(fDidBindVertexBuffer);
253 GL_CALL(DrawElementsInstancedBaseVertexBaseInstance(
254 glPrimType, indexCount, GR_GL_UNSIGNED_SHORT,
255 this->offsetForBaseIndex(baseIndex), instanceCountForDraw, baseVertex,
256 baseInstanceForDraw));
257 } else {
258 this->bindInstanceBuffer(fActiveInstanceBuffer.get(), baseInstanceForDraw);
259 this->bindVertexBuffer(fActiveVertexBuffer.get(), baseVertex);
260 GL_CALL(DrawElementsInstanced(glPrimType, indexCount, GR_GL_UNSIGNED_SHORT,
261 this->offsetForBaseIndex(baseIndex), instanceCountForDraw));
262 }
263 }
264 fGpu->didDrawTo(fRenderTarget);
265 }
266
buffer_offset_to_gl_address(const GrBuffer * drawIndirectBuffer,size_t offset)267 static const void* buffer_offset_to_gl_address(const GrBuffer* drawIndirectBuffer, size_t offset) {
268 if (drawIndirectBuffer->isCpuBuffer()) {
269 return static_cast<const GrCpuBuffer*>(drawIndirectBuffer)->data() + offset;
270 } else {
271 return (offset) ? reinterpret_cast<const void*>(offset) : nullptr;
272 }
273 }
274
onDrawIndirect(const GrBuffer * drawIndirectBuffer,size_t offset,int drawCount)275 void GrGLOpsRenderPass::onDrawIndirect(const GrBuffer* drawIndirectBuffer, size_t offset,
276 int drawCount) {
277 using MultiDrawType = GrGLCaps::MultiDrawType;
278
279 SkASSERT(fGpu->caps()->nativeDrawIndirectSupport());
280 SkASSERT(fGpu->glCaps().baseVertexBaseInstanceSupport());
281 SkASSERT(fDidBindVertexBuffer || fGpu->glCaps().drawArraysBaseVertexIsBroken());
282
283 if (fGpu->glCaps().drawArraysBaseVertexIsBroken()) {
284 // We weren't able to bind the vertex buffer during onBindBuffers because of a driver bug
285 // affecting glDrawArrays.
286 this->bindVertexBuffer(fActiveVertexBuffer.get(), 0);
287 }
288
289 if (fGpu->glCaps().multiDrawType() == MultiDrawType::kANGLEOrWebGL) {
290 // ANGLE and WebGL don't support glDrawElementsIndirect. We draw everything as a multi draw.
291 this->multiDrawArraysANGLEOrWebGL(drawIndirectBuffer, offset, drawCount);
292 return;
293 }
294
295 fGpu->bindBuffer(GrGpuBufferType::kDrawIndirect, drawIndirectBuffer);
296
297 if (drawCount > 1 && fGpu->glCaps().multiDrawType() == MultiDrawType::kMultiDrawIndirect) {
298 GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
299 GL_CALL(MultiDrawArraysIndirect(glPrimType,
300 buffer_offset_to_gl_address(drawIndirectBuffer, offset),
301 drawCount, sizeof(GrDrawIndirectCommand)));
302 return;
303 }
304
305 for (int i = 0; i < drawCount; ++i) {
306 GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
307 GL_CALL(DrawArraysIndirect(glPrimType,
308 buffer_offset_to_gl_address(drawIndirectBuffer, offset)));
309 offset += sizeof(GrDrawIndirectCommand);
310 }
311 fGpu->didDrawTo(fRenderTarget);
312 }
313
multiDrawArraysANGLEOrWebGL(const GrBuffer * drawIndirectBuffer,size_t offset,int drawCount)314 void GrGLOpsRenderPass::multiDrawArraysANGLEOrWebGL(const GrBuffer* drawIndirectBuffer,
315 size_t offset, int drawCount) {
316 SkASSERT(fGpu->glCaps().multiDrawType() == GrGLCaps::MultiDrawType::kANGLEOrWebGL);
317 SkASSERT(drawIndirectBuffer->isCpuBuffer());
318
319 constexpr static int kMaxDrawCountPerBatch = 128;
320 GrGLint fFirsts[kMaxDrawCountPerBatch];
321 GrGLsizei fCounts[kMaxDrawCountPerBatch];
322 GrGLsizei fInstanceCounts[kMaxDrawCountPerBatch];
323 GrGLuint fBaseInstances[kMaxDrawCountPerBatch];
324
325 GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
326 auto* cpuBuffer = static_cast<const GrCpuBuffer*>(drawIndirectBuffer);
327 auto* cmds = reinterpret_cast<const GrDrawIndirectCommand*>(cpuBuffer->data() + offset);
328
329 while (drawCount) {
330 int countInBatch = std::min(drawCount, kMaxDrawCountPerBatch);
331 for (int i = 0; i < countInBatch; ++i) {
332 auto [vertexCount, instanceCount, baseVertex, baseInstance] = cmds[i];
333 fFirsts[i] = baseVertex;
334 fCounts[i] = vertexCount;
335 fInstanceCounts[i] = instanceCount;
336 fBaseInstances[i] = baseInstance;
337 }
338 if (countInBatch == 1) {
339 GL_CALL(DrawArraysInstancedBaseInstance(glPrimType, fFirsts[0], fCounts[0],
340 fInstanceCounts[0], fBaseInstances[0]));
341 } else {
342 GL_CALL(MultiDrawArraysInstancedBaseInstance(glPrimType, fFirsts, fCounts,
343 fInstanceCounts, fBaseInstances,
344 countInBatch));
345 }
346 drawCount -= countInBatch;
347 cmds += countInBatch;
348 }
349 fGpu->didDrawTo(fRenderTarget);
350 }
351
onDrawIndexedIndirect(const GrBuffer * drawIndirectBuffer,size_t offset,int drawCount)352 void GrGLOpsRenderPass::onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t offset,
353 int drawCount) {
354 using MultiDrawType = GrGLCaps::MultiDrawType;
355
356 SkASSERT(fGpu->caps()->nativeDrawIndirectSupport());
357 SkASSERT(!fGpu->caps()->nativeDrawIndexedIndirectIsBroken());
358 SkASSERT(fGpu->glCaps().baseVertexBaseInstanceSupport());
359 // The vertex buffer should have already gotten bound (as opposed us stashing it away during
360 // onBindBuffers and not expecting to bind it until this point).
361 SkASSERT(fDidBindVertexBuffer);
362
363 if (fGpu->glCaps().multiDrawType() == MultiDrawType::kANGLEOrWebGL) {
364 // ANGLE and WebGL don't support glDrawElementsIndirect. We draw everything as a multi draw.
365 this->multiDrawElementsANGLEOrWebGL(drawIndirectBuffer, offset, drawCount);
366 return;
367 }
368
369 fGpu->bindBuffer(GrGpuBufferType::kDrawIndirect, drawIndirectBuffer);
370
371 if (drawCount > 1 && fGpu->glCaps().multiDrawType() == MultiDrawType::kMultiDrawIndirect) {
372 GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
373 GL_CALL(MultiDrawElementsIndirect(glPrimType, GR_GL_UNSIGNED_SHORT,
374 buffer_offset_to_gl_address(drawIndirectBuffer, offset),
375 drawCount, sizeof(GrDrawIndexedIndirectCommand)));
376 return;
377 }
378
379 for (int i = 0; i < drawCount; ++i) {
380 GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
381 GL_CALL(DrawElementsIndirect(glPrimType, GR_GL_UNSIGNED_SHORT,
382 buffer_offset_to_gl_address(drawIndirectBuffer, offset)));
383 offset += sizeof(GrDrawIndexedIndirectCommand);
384 }
385 fGpu->didDrawTo(fRenderTarget);
386 }
387
multiDrawElementsANGLEOrWebGL(const GrBuffer * drawIndirectBuffer,size_t offset,int drawCount)388 void GrGLOpsRenderPass::multiDrawElementsANGLEOrWebGL(const GrBuffer* drawIndirectBuffer,
389 size_t offset, int drawCount) {
390 SkASSERT(fGpu->glCaps().multiDrawType() == GrGLCaps::MultiDrawType::kANGLEOrWebGL);
391 SkASSERT(drawIndirectBuffer->isCpuBuffer());
392
393 constexpr static int kMaxDrawCountPerBatch = 128;
394 GrGLint fCounts[kMaxDrawCountPerBatch];
395 const void* fIndices[kMaxDrawCountPerBatch];
396 GrGLsizei fInstanceCounts[kMaxDrawCountPerBatch];
397 GrGLint fBaseVertices[kMaxDrawCountPerBatch];
398 GrGLuint fBaseInstances[kMaxDrawCountPerBatch];
399
400 GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
401 auto* cpuBuffer = static_cast<const GrCpuBuffer*>(drawIndirectBuffer);
402 auto* cmds = reinterpret_cast<const GrDrawIndexedIndirectCommand*>(cpuBuffer->data() + offset);
403
404 while (drawCount) {
405 int countInBatch = std::min(drawCount, kMaxDrawCountPerBatch);
406 for (int i = 0; i < countInBatch; ++i) {
407 auto [indexCount, instanceCount, baseIndex, baseVertex, baseInstance] = cmds[i];
408 fCounts[i] = indexCount;
409 fIndices[i] = this->offsetForBaseIndex(baseIndex);
410 fInstanceCounts[i] = instanceCount;
411 fBaseVertices[i] = baseVertex;
412 fBaseInstances[i] = baseInstance;
413 }
414 if (countInBatch == 1) {
415 GL_CALL(DrawElementsInstancedBaseVertexBaseInstance(glPrimType, fCounts[0],
416 GR_GL_UNSIGNED_SHORT, fIndices[0],
417 fInstanceCounts[0],
418 fBaseVertices[0],
419 fBaseInstances[0]));
420 } else {
421 GL_CALL(MultiDrawElementsInstancedBaseVertexBaseInstance(glPrimType, fCounts,
422 GR_GL_UNSIGNED_SHORT, fIndices,
423 fInstanceCounts, fBaseVertices,
424 fBaseInstances, countInBatch));
425 }
426 drawCount -= countInBatch;
427 cmds += countInBatch;
428 }
429 fGpu->didDrawTo(fRenderTarget);
430 }
431
onClear(const GrScissorState & scissor,std::array<float,4> color)432 void GrGLOpsRenderPass::onClear(const GrScissorState& scissor, std::array<float, 4> color) {
433 fGpu->clear(scissor, color, fRenderTarget, fUseMultisampleFBO, fOrigin);
434 }
435
onClearStencilClip(const GrScissorState & scissor,bool insideStencilMask)436 void GrGLOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) {
437 fGpu->clearStencilClip(scissor, insideStencilMask, fRenderTarget, fUseMultisampleFBO, fOrigin);
438 }
439