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