• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ContextGL:
7 //   OpenGL-specific functionality associated with a GL Context.
8 //
9 
10 #include "libANGLE/renderer/gl/ContextGL.h"
11 
12 #include "libANGLE/Context.h"
13 #include "libANGLE/Context.inl.h"
14 #include "libANGLE/PixelLocalStorage.h"
15 #include "libANGLE/renderer/OverlayImpl.h"
16 #include "libANGLE/renderer/gl/BufferGL.h"
17 #include "libANGLE/renderer/gl/CompilerGL.h"
18 #include "libANGLE/renderer/gl/FenceNVGL.h"
19 #include "libANGLE/renderer/gl/FramebufferGL.h"
20 #include "libANGLE/renderer/gl/FunctionsGL.h"
21 #include "libANGLE/renderer/gl/MemoryObjectGL.h"
22 #include "libANGLE/renderer/gl/PLSProgramCache.h"
23 #include "libANGLE/renderer/gl/ProgramGL.h"
24 #include "libANGLE/renderer/gl/ProgramPipelineGL.h"
25 #include "libANGLE/renderer/gl/QueryGL.h"
26 #include "libANGLE/renderer/gl/RenderbufferGL.h"
27 #include "libANGLE/renderer/gl/RendererGL.h"
28 #include "libANGLE/renderer/gl/SamplerGL.h"
29 #include "libANGLE/renderer/gl/SemaphoreGL.h"
30 #include "libANGLE/renderer/gl/ShaderGL.h"
31 #include "libANGLE/renderer/gl/StateManagerGL.h"
32 #include "libANGLE/renderer/gl/SyncGL.h"
33 #include "libANGLE/renderer/gl/TextureGL.h"
34 #include "libANGLE/renderer/gl/TransformFeedbackGL.h"
35 #include "libANGLE/renderer/gl/VertexArrayGL.h"
36 
37 namespace rx
38 {
39 
ContextGL(const gl::State & state,gl::ErrorSet * errorSet,const std::shared_ptr<RendererGL> & renderer,RobustnessVideoMemoryPurgeStatus robustnessVideoMemoryPurgeStatus)40 ContextGL::ContextGL(const gl::State &state,
41                      gl::ErrorSet *errorSet,
42                      const std::shared_ptr<RendererGL> &renderer,
43                      RobustnessVideoMemoryPurgeStatus robustnessVideoMemoryPurgeStatus)
44     : ContextImpl(state, errorSet),
45       mRenderer(renderer),
46       mRobustnessVideoMemoryPurgeStatus(robustnessVideoMemoryPurgeStatus)
47 {}
48 
~ContextGL()49 ContextGL::~ContextGL() {}
50 
initialize()51 angle::Result ContextGL::initialize()
52 {
53     return angle::Result::Continue;
54 }
55 
createCompiler()56 CompilerImpl *ContextGL::createCompiler()
57 {
58     return new CompilerGL(this);
59 }
60 
createShader(const gl::ShaderState & data)61 ShaderImpl *ContextGL::createShader(const gl::ShaderState &data)
62 {
63     const FunctionsGL *functions = getFunctions();
64     GLuint shader                = functions->createShader(ToGLenum(data.getShaderType()));
65 
66     return new ShaderGL(data, shader, mRenderer->getMultiviewImplementationType(), mRenderer);
67 }
68 
createProgram(const gl::ProgramState & data)69 ProgramImpl *ContextGL::createProgram(const gl::ProgramState &data)
70 {
71     return new ProgramGL(data, getFunctions(), getFeaturesGL(), getStateManager(), mRenderer);
72 }
73 
createFramebuffer(const gl::FramebufferState & data)74 FramebufferImpl *ContextGL::createFramebuffer(const gl::FramebufferState &data)
75 {
76     const FunctionsGL *funcs = getFunctions();
77 
78     GLuint fbo = 0;
79     if (!data.isDefault())
80     {
81         funcs->genFramebuffers(1, &fbo);
82     }
83 
84     return new FramebufferGL(data, fbo, false);
85 }
86 
createTexture(const gl::TextureState & state)87 TextureImpl *ContextGL::createTexture(const gl::TextureState &state)
88 {
89     const FunctionsGL *functions = getFunctions();
90     StateManagerGL *stateManager = getStateManager();
91 
92     GLuint texture = 0;
93     functions->genTextures(1, &texture);
94     stateManager->bindTexture(state.getType(), texture);
95 
96     return new TextureGL(state, texture);
97 }
98 
createRenderbuffer(const gl::RenderbufferState & state)99 RenderbufferImpl *ContextGL::createRenderbuffer(const gl::RenderbufferState &state)
100 {
101     const FunctionsGL *functions = getFunctions();
102     StateManagerGL *stateManager = getStateManager();
103 
104     GLuint renderbuffer = 0;
105     functions->genRenderbuffers(1, &renderbuffer);
106     stateManager->bindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
107 
108     return new RenderbufferGL(state, renderbuffer);
109 }
110 
createBuffer(const gl::BufferState & state)111 BufferImpl *ContextGL::createBuffer(const gl::BufferState &state)
112 {
113     const FunctionsGL *functions = getFunctions();
114 
115     GLuint buffer = 0;
116     functions->genBuffers(1, &buffer);
117 
118     return new BufferGL(state, buffer);
119 }
120 
createVertexArray(const gl::VertexArrayState & data)121 VertexArrayImpl *ContextGL::createVertexArray(const gl::VertexArrayState &data)
122 {
123     const angle::FeaturesGL &features = getFeaturesGL();
124 
125     if (features.syncVertexArraysToDefault.enabled)
126     {
127         StateManagerGL *stateManager = getStateManager();
128 
129         return new VertexArrayGL(data, stateManager->getDefaultVAO(),
130                                  stateManager->getDefaultVAOState());
131     }
132     else
133     {
134         const FunctionsGL *functions = getFunctions();
135 
136         GLuint vao = 0;
137         functions->genVertexArrays(1, &vao);
138         return new VertexArrayGL(data, vao);
139     }
140 }
141 
createQuery(gl::QueryType type)142 QueryImpl *ContextGL::createQuery(gl::QueryType type)
143 {
144     switch (type)
145     {
146         case gl::QueryType::CommandsCompleted:
147             return new SyncQueryGL(type, getFunctions());
148 
149         default:
150             return new StandardQueryGL(type, getFunctions(), getStateManager());
151     }
152 }
153 
createFenceNV()154 FenceNVImpl *ContextGL::createFenceNV()
155 {
156     const FunctionsGL *functions = getFunctions();
157     if (FenceNVGL::Supported(functions))
158     {
159         return new FenceNVGL(functions);
160     }
161     else
162     {
163         ASSERT(FenceNVSyncGL::Supported(functions));
164         return new FenceNVSyncGL(functions);
165     }
166 }
167 
createSync()168 SyncImpl *ContextGL::createSync()
169 {
170     return new SyncGL(getFunctions());
171 }
172 
createTransformFeedback(const gl::TransformFeedbackState & state)173 TransformFeedbackImpl *ContextGL::createTransformFeedback(const gl::TransformFeedbackState &state)
174 {
175     return new TransformFeedbackGL(state, getFunctions(), getStateManager());
176 }
177 
createSampler(const gl::SamplerState & state)178 SamplerImpl *ContextGL::createSampler(const gl::SamplerState &state)
179 {
180     return new SamplerGL(state, getFunctions(), getStateManager());
181 }
182 
createProgramPipeline(const gl::ProgramPipelineState & data)183 ProgramPipelineImpl *ContextGL::createProgramPipeline(const gl::ProgramPipelineState &data)
184 {
185     return new ProgramPipelineGL(data, getFunctions());
186 }
187 
createMemoryObject()188 MemoryObjectImpl *ContextGL::createMemoryObject()
189 {
190     const FunctionsGL *functions = getFunctions();
191 
192     GLuint memoryObject = 0;
193     functions->createMemoryObjectsEXT(1, &memoryObject);
194 
195     return new MemoryObjectGL(memoryObject);
196 }
197 
createSemaphore()198 SemaphoreImpl *ContextGL::createSemaphore()
199 {
200     const FunctionsGL *functions = getFunctions();
201 
202     GLuint semaphore = 0;
203     functions->genSemaphoresEXT(1, &semaphore);
204 
205     return new SemaphoreGL(semaphore);
206 }
207 
createOverlay(const gl::OverlayState & state)208 OverlayImpl *ContextGL::createOverlay(const gl::OverlayState &state)
209 {
210     // Not implemented.
211     return new OverlayImpl(state);
212 }
213 
flush(const gl::Context * context)214 angle::Result ContextGL::flush(const gl::Context *context)
215 {
216     return mRenderer->flush();
217 }
218 
finish(const gl::Context * context)219 angle::Result ContextGL::finish(const gl::Context *context)
220 {
221     return mRenderer->finish();
222 }
223 
setDrawArraysState(const gl::Context * context,GLint first,GLsizei count,GLsizei instanceCount)224 ANGLE_INLINE angle::Result ContextGL::setDrawArraysState(const gl::Context *context,
225                                                          GLint first,
226                                                          GLsizei count,
227                                                          GLsizei instanceCount)
228 {
229     const angle::FeaturesGL &features = getFeaturesGL();
230     if (context->getStateCache().hasAnyActiveClientAttrib() ||
231         (features.shiftInstancedArrayDataWithOffset.enabled && first > 0))
232     {
233         const gl::State &glState                = context->getState();
234         const gl::ProgramExecutable *executable = getState().getProgramExecutable();
235         const gl::VertexArray *vao              = glState.getVertexArray();
236         const VertexArrayGL *vaoGL              = GetImplAs<VertexArrayGL>(vao);
237 
238         ANGLE_TRY(vaoGL->syncClientSideData(context, executable->getActiveAttribLocationsMask(),
239                                             first, count, instanceCount));
240 
241 #if defined(ANGLE_STATE_VALIDATION_ENABLED)
242         ANGLE_TRY(vaoGL->validateState(context));
243 #endif  // ANGLE_STATE_VALIDATION_ENABLED
244     }
245     else if (features.shiftInstancedArrayDataWithOffset.enabled && first == 0)
246     {
247         // There could be previous draw call that has modified the attributes
248         // Instead of forcefully streaming attributes, we just rebind the original ones
249         const gl::State &glState   = context->getState();
250         const gl::VertexArray *vao = glState.getVertexArray();
251         const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
252         ANGLE_TRY(vaoGL->recoverForcedStreamingAttributesForDrawArraysInstanced(context));
253     }
254 
255     if (features.setPrimitiveRestartFixedIndexForDrawArrays.enabled)
256     {
257         StateManagerGL *stateManager           = getStateManager();
258         constexpr GLuint primitiveRestartIndex = gl::GetPrimitiveRestartIndexFromType<GLuint>();
259         ANGLE_TRY(stateManager->setPrimitiveRestartIndex(context, primitiveRestartIndex));
260     }
261 
262     return angle::Result::Continue;
263 }
264 
setDrawElementsState(const gl::Context * context,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instanceCount,const void ** outIndices)265 ANGLE_INLINE angle::Result ContextGL::setDrawElementsState(const gl::Context *context,
266                                                            GLsizei count,
267                                                            gl::DrawElementsType type,
268                                                            const void *indices,
269                                                            GLsizei instanceCount,
270                                                            const void **outIndices)
271 {
272     const gl::State &glState                = context->getState();
273     const gl::ProgramExecutable *executable = getState().getProgramExecutable();
274     const gl::VertexArray *vao              = glState.getVertexArray();
275     const gl::StateCache &stateCache        = context->getStateCache();
276 
277     const angle::FeaturesGL &features = getFeaturesGL();
278     if (features.shiftInstancedArrayDataWithOffset.enabled)
279     {
280         // There might be instanced arrays that are forced streaming for drawArraysInstanced
281         // They cannot be ELEMENT_ARRAY_BUFFER
282         const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
283         ANGLE_TRY(vaoGL->recoverForcedStreamingAttributesForDrawArraysInstanced(context));
284     }
285 
286     if (stateCache.hasAnyActiveClientAttrib() || vao->getElementArrayBuffer() == nullptr)
287     {
288         const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
289         ANGLE_TRY(vaoGL->syncDrawElementsState(context, executable->getActiveAttribLocationsMask(),
290                                                count, type, indices, instanceCount,
291                                                glState.isPrimitiveRestartEnabled(), outIndices));
292     }
293     else
294     {
295         *outIndices = indices;
296     }
297 
298     if (glState.isPrimitiveRestartEnabled() && features.emulatePrimitiveRestartFixedIndex.enabled)
299     {
300         StateManagerGL *stateManager = getStateManager();
301 
302         GLuint primitiveRestartIndex = gl::GetPrimitiveRestartIndex(type);
303         ANGLE_TRY(stateManager->setPrimitiveRestartIndex(context, primitiveRestartIndex));
304     }
305 
306 #if defined(ANGLE_STATE_VALIDATION_ENABLED)
307     const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
308     ANGLE_TRY(vaoGL->validateState(context));
309 #endif  // ANGLE_STATE_VALIDATION_ENABLED
310 
311     return angle::Result::Continue;
312 }
313 
drawArrays(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count)314 angle::Result ContextGL::drawArrays(const gl::Context *context,
315                                     gl::PrimitiveMode mode,
316                                     GLint first,
317                                     GLsizei count)
318 {
319     const gl::Program *program  = context->getState().getProgram();
320     const bool usesMultiview    = program->usesMultiview();
321     const GLsizei instanceCount = usesMultiview ? program->getNumViews() : 0;
322 
323 #if defined(ANGLE_STATE_VALIDATION_ENABLED)
324     validateState();
325 #endif
326 
327     ANGLE_TRY(setDrawArraysState(context, first, count, instanceCount));
328     if (!usesMultiview)
329     {
330         ANGLE_GL_TRY(context, getFunctions()->drawArrays(ToGLenum(mode), first, count));
331     }
332     else
333     {
334         ANGLE_GL_TRY(context, getFunctions()->drawArraysInstanced(ToGLenum(mode), first, count,
335                                                                   instanceCount));
336     }
337     mRenderer->markWorkSubmitted();
338 
339     return angle::Result::Continue;
340 }
341 
drawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instanceCount)342 angle::Result ContextGL::drawArraysInstanced(const gl::Context *context,
343                                              gl::PrimitiveMode mode,
344                                              GLint first,
345                                              GLsizei count,
346                                              GLsizei instanceCount)
347 {
348     GLsizei adjustedInstanceCount = instanceCount;
349     const gl::Program *program    = context->getState().getProgram();
350     if (program->usesMultiview())
351     {
352         adjustedInstanceCount *= program->getNumViews();
353     }
354 
355     ANGLE_TRY(setDrawArraysState(context, first, count, adjustedInstanceCount));
356     ANGLE_GL_TRY(context, getFunctions()->drawArraysInstanced(ToGLenum(mode), first, count,
357                                                               adjustedInstanceCount));
358     mRenderer->markWorkSubmitted();
359 
360     return angle::Result::Continue;
361 }
362 
updateAttributesForBaseInstance(const gl::Program * program,GLuint baseInstance)363 gl::AttributesMask ContextGL::updateAttributesForBaseInstance(const gl::Program *program,
364                                                               GLuint baseInstance)
365 {
366     const gl::ProgramExecutable *executable = getState().getProgramExecutable();
367     gl::AttributesMask attribToUpdateMask;
368 
369     if (baseInstance != 0)
370     {
371         const FunctionsGL *functions = getFunctions();
372         const auto &attribs          = mState.getVertexArray()->getVertexAttributes();
373         const auto &bindings         = mState.getVertexArray()->getVertexBindings();
374         for (GLuint attribIndex = 0; attribIndex < attribs.size(); attribIndex++)
375         {
376             const gl::VertexAttribute &attrib = attribs[attribIndex];
377             const gl::VertexBinding &binding  = bindings[attrib.bindingIndex];
378             if (executable->isAttribLocationActive(attribIndex) && binding.getDivisor() != 0)
379             {
380                 attribToUpdateMask.set(attribIndex);
381                 const char *p             = static_cast<const char *>(attrib.pointer);
382                 const size_t sourceStride = gl::ComputeVertexAttributeStride(attrib, binding);
383                 const void *newPointer    = p + sourceStride * baseInstance;
384 
385                 const BufferGL *buffer = GetImplAs<BufferGL>(binding.getBuffer().get());
386                 // We often stream data from scratch buffers when client side data is being used
387                 // and that information is in VertexArrayGL.
388                 // Assert that the buffer is non-null because this case isn't handled.
389                 ASSERT(buffer);
390                 getStateManager()->bindBuffer(gl::BufferBinding::Array, buffer->getBufferID());
391                 if (attrib.format->isPureInt())
392                 {
393                     functions->vertexAttribIPointer(attribIndex, attrib.format->channelCount,
394                                                     gl::ToGLenum(attrib.format->vertexAttribType),
395                                                     attrib.vertexAttribArrayStride, newPointer);
396                 }
397                 else
398                 {
399                     functions->vertexAttribPointer(attribIndex, attrib.format->channelCount,
400                                                    gl::ToGLenum(attrib.format->vertexAttribType),
401                                                    attrib.format->isNorm(),
402                                                    attrib.vertexAttribArrayStride, newPointer);
403                 }
404             }
405         }
406     }
407 
408     return attribToUpdateMask;
409 }
410 
resetUpdatedAttributes(gl::AttributesMask attribMask)411 void ContextGL::resetUpdatedAttributes(gl::AttributesMask attribMask)
412 {
413     const FunctionsGL *functions = getFunctions();
414     for (size_t attribIndex : attribMask)
415     {
416         const gl::VertexAttribute &attrib =
417             mState.getVertexArray()->getVertexAttributes()[attribIndex];
418         const gl::VertexBinding &binding =
419             (mState.getVertexArray()->getVertexBindings())[attrib.bindingIndex];
420         getStateManager()->bindBuffer(
421             gl::BufferBinding::Array,
422             GetImplAs<BufferGL>(binding.getBuffer().get())->getBufferID());
423         if (attrib.format->isPureInt())
424         {
425             functions->vertexAttribIPointer(static_cast<GLuint>(attribIndex),
426                                             attrib.format->channelCount,
427                                             gl::ToGLenum(attrib.format->vertexAttribType),
428                                             attrib.vertexAttribArrayStride, attrib.pointer);
429         }
430         else
431         {
432             functions->vertexAttribPointer(
433                 static_cast<GLuint>(attribIndex), attrib.format->channelCount,
434                 gl::ToGLenum(attrib.format->vertexAttribType), attrib.format->isNorm(),
435                 attrib.vertexAttribArrayStride, attrib.pointer);
436         }
437     }
438 }
439 
drawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instanceCount,GLuint baseInstance)440 angle::Result ContextGL::drawArraysInstancedBaseInstance(const gl::Context *context,
441                                                          gl::PrimitiveMode mode,
442                                                          GLint first,
443                                                          GLsizei count,
444                                                          GLsizei instanceCount,
445                                                          GLuint baseInstance)
446 {
447     GLsizei adjustedInstanceCount = instanceCount;
448     const gl::Program *program    = context->getState().getProgram();
449     if (program->usesMultiview())
450     {
451         adjustedInstanceCount *= program->getNumViews();
452     }
453 
454     ANGLE_TRY(setDrawArraysState(context, first, count, adjustedInstanceCount));
455 
456     const FunctionsGL *functions = getFunctions();
457 
458     if (functions->drawArraysInstancedBaseInstance)
459     {
460         // GL 4.2+ or GL_EXT_base_instance
461         ANGLE_GL_TRY(context,
462                      functions->drawArraysInstancedBaseInstance(
463                          ToGLenum(mode), first, count, adjustedInstanceCount, baseInstance));
464     }
465     else
466     {
467         // GL 3.3+ or GLES 3.2+
468         // TODO(http://anglebug.com/3910): This is a temporary solution by setting and resetting
469         // pointer offset calling vertexAttribPointer Will refactor stateCache and pass baseInstance
470         // to setDrawArraysState to set pointer offset
471 
472         gl::AttributesMask attribToResetMask =
473             updateAttributesForBaseInstance(program, baseInstance);
474 
475         ANGLE_GL_TRY(context, functions->drawArraysInstanced(ToGLenum(mode), first, count,
476                                                              adjustedInstanceCount));
477 
478         resetUpdatedAttributes(attribToResetMask);
479     }
480 
481     mRenderer->markWorkSubmitted();
482 
483     return angle::Result::Continue;
484 }
485 
drawElements(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices)486 angle::Result ContextGL::drawElements(const gl::Context *context,
487                                       gl::PrimitiveMode mode,
488                                       GLsizei count,
489                                       gl::DrawElementsType type,
490                                       const void *indices)
491 {
492     const gl::State &glState    = context->getState();
493     const gl::Program *program  = glState.getProgram();
494     const bool usesMultiview    = program->usesMultiview();
495     const GLsizei instanceCount = usesMultiview ? program->getNumViews() : 0;
496     const void *drawIndexPtr    = nullptr;
497 
498 #if defined(ANGLE_STATE_VALIDATION_ENABLED)
499     validateState();
500 #endif  // ANGLE_STATE_VALIDATION_ENABLED
501 
502     ANGLE_TRY(setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPtr));
503     if (!usesMultiview)
504     {
505         ANGLE_GL_TRY(context, getFunctions()->drawElements(ToGLenum(mode), count, ToGLenum(type),
506                                                            drawIndexPtr));
507     }
508     else
509     {
510         ANGLE_GL_TRY(context,
511                      getFunctions()->drawElementsInstanced(ToGLenum(mode), count, ToGLenum(type),
512                                                            drawIndexPtr, instanceCount));
513     }
514     mRenderer->markWorkSubmitted();
515 
516     return angle::Result::Continue;
517 }
518 
drawElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)519 angle::Result ContextGL::drawElementsBaseVertex(const gl::Context *context,
520                                                 gl::PrimitiveMode mode,
521                                                 GLsizei count,
522                                                 gl::DrawElementsType type,
523                                                 const void *indices,
524                                                 GLint baseVertex)
525 {
526     const gl::State &glState    = context->getState();
527     const gl::Program *program  = glState.getProgram();
528     const bool usesMultiview    = program->usesMultiview();
529     const GLsizei instanceCount = usesMultiview ? program->getNumViews() : 0;
530     const void *drawIndexPtr    = nullptr;
531 
532 #if defined(ANGLE_STATE_VALIDATION_ENABLED)
533     validateState();
534 #endif  // ANGLE_STATE_VALIDATION_ENABLED
535 
536     ANGLE_TRY(setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPtr));
537     if (!usesMultiview)
538     {
539         ANGLE_GL_TRY(context, getFunctions()->drawElementsBaseVertex(
540                                   ToGLenum(mode), count, ToGLenum(type), drawIndexPtr, baseVertex));
541     }
542     else
543     {
544         ANGLE_GL_TRY(context, getFunctions()->drawElementsInstancedBaseVertex(
545                                   ToGLenum(mode), count, ToGLenum(type), drawIndexPtr,
546                                   instanceCount, baseVertex));
547     }
548     mRenderer->markWorkSubmitted();
549 
550     return angle::Result::Continue;
551 }
552 
drawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances)553 angle::Result ContextGL::drawElementsInstanced(const gl::Context *context,
554                                                gl::PrimitiveMode mode,
555                                                GLsizei count,
556                                                gl::DrawElementsType type,
557                                                const void *indices,
558                                                GLsizei instances)
559 {
560     GLsizei adjustedInstanceCount = instances;
561     const gl::Program *program    = context->getState().getProgram();
562     if (program->usesMultiview())
563     {
564         adjustedInstanceCount *= program->getNumViews();
565     }
566     const void *drawIndexPointer = nullptr;
567 
568     ANGLE_TRY(setDrawElementsState(context, count, type, indices, adjustedInstanceCount,
569                                    &drawIndexPointer));
570     ANGLE_GL_TRY(context,
571                  getFunctions()->drawElementsInstanced(ToGLenum(mode), count, ToGLenum(type),
572                                                        drawIndexPointer, adjustedInstanceCount));
573     return angle::Result::Continue;
574 }
575 
drawElementsInstancedBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex)576 angle::Result ContextGL::drawElementsInstancedBaseVertex(const gl::Context *context,
577                                                          gl::PrimitiveMode mode,
578                                                          GLsizei count,
579                                                          gl::DrawElementsType type,
580                                                          const void *indices,
581                                                          GLsizei instances,
582                                                          GLint baseVertex)
583 {
584     GLsizei adjustedInstanceCount = instances;
585     const gl::Program *program    = context->getState().getProgram();
586     if (program->usesMultiview())
587     {
588         adjustedInstanceCount *= program->getNumViews();
589     }
590     const void *drawIndexPointer = nullptr;
591 
592     ANGLE_TRY(setDrawElementsState(context, count, type, indices, adjustedInstanceCount,
593                                    &drawIndexPointer));
594     ANGLE_GL_TRY(context, getFunctions()->drawElementsInstancedBaseVertex(
595                               ToGLenum(mode), count, ToGLenum(type), drawIndexPointer,
596                               adjustedInstanceCount, baseVertex));
597     mRenderer->markWorkSubmitted();
598 
599     return angle::Result::Continue;
600 }
601 
drawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex,GLuint baseInstance)602 angle::Result ContextGL::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
603                                                                      gl::PrimitiveMode mode,
604                                                                      GLsizei count,
605                                                                      gl::DrawElementsType type,
606                                                                      const void *indices,
607                                                                      GLsizei instances,
608                                                                      GLint baseVertex,
609                                                                      GLuint baseInstance)
610 {
611     GLsizei adjustedInstanceCount = instances;
612     const gl::Program *program    = context->getState().getProgram();
613     if (program->usesMultiview())
614     {
615         adjustedInstanceCount *= program->getNumViews();
616     }
617     const void *drawIndexPointer = nullptr;
618 
619     ANGLE_TRY(setDrawElementsState(context, count, type, indices, adjustedInstanceCount,
620                                    &drawIndexPointer));
621 
622     const FunctionsGL *functions = getFunctions();
623 
624     if (functions->drawElementsInstancedBaseVertexBaseInstance)
625     {
626         // GL 4.2+ or GL_EXT_base_instance
627         ANGLE_GL_TRY(context, functions->drawElementsInstancedBaseVertexBaseInstance(
628                                   ToGLenum(mode), count, ToGLenum(type), drawIndexPointer,
629                                   adjustedInstanceCount, baseVertex, baseInstance));
630     }
631     else
632     {
633         // GL 3.3+ or GLES 3.2+
634         // TODO(http://anglebug.com/3910): same as above
635         gl::AttributesMask attribToResetMask =
636             updateAttributesForBaseInstance(program, baseInstance);
637 
638         ANGLE_GL_TRY(context, functions->drawElementsInstancedBaseVertex(
639                                   ToGLenum(mode), count, ToGLenum(type), drawIndexPointer,
640                                   adjustedInstanceCount, baseVertex));
641 
642         resetUpdatedAttributes(attribToResetMask);
643     }
644 
645     mRenderer->markWorkSubmitted();
646 
647     return angle::Result::Continue;
648 }
649 
drawRangeElements(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices)650 angle::Result ContextGL::drawRangeElements(const gl::Context *context,
651                                            gl::PrimitiveMode mode,
652                                            GLuint start,
653                                            GLuint end,
654                                            GLsizei count,
655                                            gl::DrawElementsType type,
656                                            const void *indices)
657 {
658     const gl::Program *program   = context->getState().getProgram();
659     const bool usesMultiview     = program->usesMultiview();
660     const GLsizei instanceCount  = usesMultiview ? program->getNumViews() : 0;
661     const void *drawIndexPointer = nullptr;
662 
663     ANGLE_TRY(
664         setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPointer));
665     if (!usesMultiview)
666     {
667         ANGLE_GL_TRY(context, getFunctions()->drawRangeElements(ToGLenum(mode), start, end, count,
668                                                                 ToGLenum(type), drawIndexPointer));
669     }
670     else
671     {
672         ANGLE_GL_TRY(context,
673                      getFunctions()->drawElementsInstanced(ToGLenum(mode), count, ToGLenum(type),
674                                                            drawIndexPointer, instanceCount));
675     }
676     mRenderer->markWorkSubmitted();
677 
678     return angle::Result::Continue;
679 }
680 
drawRangeElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)681 angle::Result ContextGL::drawRangeElementsBaseVertex(const gl::Context *context,
682                                                      gl::PrimitiveMode mode,
683                                                      GLuint start,
684                                                      GLuint end,
685                                                      GLsizei count,
686                                                      gl::DrawElementsType type,
687                                                      const void *indices,
688                                                      GLint baseVertex)
689 {
690     const gl::Program *program   = context->getState().getProgram();
691     const bool usesMultiview     = program->usesMultiview();
692     const GLsizei instanceCount  = usesMultiview ? program->getNumViews() : 0;
693     const void *drawIndexPointer = nullptr;
694 
695     ANGLE_TRY(
696         setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPointer));
697     if (!usesMultiview)
698     {
699         ANGLE_GL_TRY(context, getFunctions()->drawRangeElementsBaseVertex(
700                                   ToGLenum(mode), start, end, count, ToGLenum(type),
701                                   drawIndexPointer, baseVertex));
702     }
703     else
704     {
705         ANGLE_GL_TRY(context, getFunctions()->drawElementsInstancedBaseVertex(
706                                   ToGLenum(mode), count, ToGLenum(type), drawIndexPointer,
707                                   instanceCount, baseVertex));
708     }
709     mRenderer->markWorkSubmitted();
710 
711     return angle::Result::Continue;
712 }
713 
drawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect)714 angle::Result ContextGL::drawArraysIndirect(const gl::Context *context,
715                                             gl::PrimitiveMode mode,
716                                             const void *indirect)
717 {
718     ANGLE_GL_TRY(context, getFunctions()->drawArraysIndirect(ToGLenum(mode), indirect));
719     mRenderer->markWorkSubmitted();
720 
721     return angle::Result::Continue;
722 }
723 
drawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect)724 angle::Result ContextGL::drawElementsIndirect(const gl::Context *context,
725                                               gl::PrimitiveMode mode,
726                                               gl::DrawElementsType type,
727                                               const void *indirect)
728 {
729     ANGLE_GL_TRY(context,
730                  getFunctions()->drawElementsIndirect(ToGLenum(mode), ToGLenum(type), indirect));
731     return angle::Result::Continue;
732 }
733 
multiDrawArrays(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)734 angle::Result ContextGL::multiDrawArrays(const gl::Context *context,
735                                          gl::PrimitiveMode mode,
736                                          const GLint *firsts,
737                                          const GLsizei *counts,
738                                          GLsizei drawcount)
739 {
740     mRenderer->markWorkSubmitted();
741 
742     return rx::MultiDrawArraysGeneral(this, context, mode, firsts, counts, drawcount);
743 }
744 
multiDrawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)745 angle::Result ContextGL::multiDrawArraysInstanced(const gl::Context *context,
746                                                   gl::PrimitiveMode mode,
747                                                   const GLint *firsts,
748                                                   const GLsizei *counts,
749                                                   const GLsizei *instanceCounts,
750                                                   GLsizei drawcount)
751 {
752     mRenderer->markWorkSubmitted();
753 
754     return rx::MultiDrawArraysInstancedGeneral(this, context, mode, firsts, counts, instanceCounts,
755                                                drawcount);
756 }
757 
multiDrawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect,GLsizei drawcount,GLsizei stride)758 angle::Result ContextGL::multiDrawArraysIndirect(const gl::Context *context,
759                                                  gl::PrimitiveMode mode,
760                                                  const void *indirect,
761                                                  GLsizei drawcount,
762                                                  GLsizei stride)
763 {
764     mRenderer->markWorkSubmitted();
765 
766     return rx::MultiDrawArraysIndirectGeneral(this, context, mode, indirect, drawcount, stride);
767 }
768 
multiDrawElements(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,GLsizei drawcount)769 angle::Result ContextGL::multiDrawElements(const gl::Context *context,
770                                            gl::PrimitiveMode mode,
771                                            const GLsizei *counts,
772                                            gl::DrawElementsType type,
773                                            const GLvoid *const *indices,
774                                            GLsizei drawcount)
775 {
776     mRenderer->markWorkSubmitted();
777 
778     return rx::MultiDrawElementsGeneral(this, context, mode, counts, type, indices, drawcount);
779 }
780 
multiDrawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,GLsizei drawcount)781 angle::Result ContextGL::multiDrawElementsInstanced(const gl::Context *context,
782                                                     gl::PrimitiveMode mode,
783                                                     const GLsizei *counts,
784                                                     gl::DrawElementsType type,
785                                                     const GLvoid *const *indices,
786                                                     const GLsizei *instanceCounts,
787                                                     GLsizei drawcount)
788 {
789     mRenderer->markWorkSubmitted();
790 
791     return rx::MultiDrawElementsInstancedGeneral(this, context, mode, counts, type, indices,
792                                                  instanceCounts, drawcount);
793 }
794 
multiDrawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect,GLsizei drawcount,GLsizei stride)795 angle::Result ContextGL::multiDrawElementsIndirect(const gl::Context *context,
796                                                    gl::PrimitiveMode mode,
797                                                    gl::DrawElementsType type,
798                                                    const void *indirect,
799                                                    GLsizei drawcount,
800                                                    GLsizei stride)
801 {
802     mRenderer->markWorkSubmitted();
803 
804     return rx::MultiDrawElementsIndirectGeneral(this, context, mode, type, indirect, drawcount,
805                                                 stride);
806 }
807 
multiDrawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)808 angle::Result ContextGL::multiDrawArraysInstancedBaseInstance(const gl::Context *context,
809                                                               gl::PrimitiveMode mode,
810                                                               const GLint *firsts,
811                                                               const GLsizei *counts,
812                                                               const GLsizei *instanceCounts,
813                                                               const GLuint *baseInstances,
814                                                               GLsizei drawcount)
815 {
816     mRenderer->markWorkSubmitted();
817 
818     return rx::MultiDrawArraysInstancedBaseInstanceGeneral(
819         this, context, mode, firsts, counts, instanceCounts, baseInstances, drawcount);
820 }
821 
multiDrawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,const GLint * baseVertices,const GLuint * baseInstances,GLsizei drawcount)822 angle::Result ContextGL::multiDrawElementsInstancedBaseVertexBaseInstance(
823     const gl::Context *context,
824     gl::PrimitiveMode mode,
825     const GLsizei *counts,
826     gl::DrawElementsType type,
827     const GLvoid *const *indices,
828     const GLsizei *instanceCounts,
829     const GLint *baseVertices,
830     const GLuint *baseInstances,
831     GLsizei drawcount)
832 {
833     mRenderer->markWorkSubmitted();
834 
835     return rx::MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(
836         this, context, mode, counts, type, indices, instanceCounts, baseVertices, baseInstances,
837         drawcount);
838 }
839 
getResetStatus()840 gl::GraphicsResetStatus ContextGL::getResetStatus()
841 {
842     gl::GraphicsResetStatus resetStatus = mRenderer->getResetStatus();
843     if (resetStatus == gl::GraphicsResetStatus::PurgedContextResetNV)
844     {
845         if (mRobustnessVideoMemoryPurgeStatus == RobustnessVideoMemoryPurgeStatus::NOT_REQUESTED)
846         {
847             resetStatus = gl::GraphicsResetStatus::UnknownContextReset;
848         }
849     }
850     return resetStatus;
851 }
852 
insertEventMarker(GLsizei length,const char * marker)853 angle::Result ContextGL::insertEventMarker(GLsizei length, const char *marker)
854 {
855     mRenderer->insertEventMarker(length, marker);
856     return angle::Result::Continue;
857 }
858 
pushGroupMarker(GLsizei length,const char * marker)859 angle::Result ContextGL::pushGroupMarker(GLsizei length, const char *marker)
860 {
861     mRenderer->pushGroupMarker(length, marker);
862     return angle::Result::Continue;
863 }
864 
popGroupMarker()865 angle::Result ContextGL::popGroupMarker()
866 {
867     mRenderer->popGroupMarker();
868     return angle::Result::Continue;
869 }
870 
pushDebugGroup(const gl::Context * context,GLenum source,GLuint id,const std::string & message)871 angle::Result ContextGL::pushDebugGroup(const gl::Context *context,
872                                         GLenum source,
873                                         GLuint id,
874                                         const std::string &message)
875 {
876     mRenderer->pushDebugGroup(source, id, message);
877     return angle::Result::Continue;
878 }
879 
popDebugGroup(const gl::Context * context)880 angle::Result ContextGL::popDebugGroup(const gl::Context *context)
881 {
882     mRenderer->popDebugGroup();
883     return angle::Result::Continue;
884 }
885 
syncState(const gl::Context * context,const gl::state::DirtyBits dirtyBits,const gl::state::DirtyBits bitMask,const gl::state::ExtendedDirtyBits extendedDirtyBits,const gl::state::ExtendedDirtyBits extendedBitMask,gl::Command command)886 angle::Result ContextGL::syncState(const gl::Context *context,
887                                    const gl::state::DirtyBits dirtyBits,
888                                    const gl::state::DirtyBits bitMask,
889                                    const gl::state::ExtendedDirtyBits extendedDirtyBits,
890                                    const gl::state::ExtendedDirtyBits extendedBitMask,
891                                    gl::Command command)
892 {
893     return mRenderer->getStateManager()->syncState(context, dirtyBits, bitMask, extendedDirtyBits,
894                                                    extendedBitMask);
895 }
896 
getGPUDisjoint()897 GLint ContextGL::getGPUDisjoint()
898 {
899     return mRenderer->getGPUDisjoint();
900 }
901 
getTimestamp()902 GLint64 ContextGL::getTimestamp()
903 {
904     return mRenderer->getTimestamp();
905 }
906 
onMakeCurrent(const gl::Context * context)907 angle::Result ContextGL::onMakeCurrent(const gl::Context *context)
908 {
909     // Queries need to be paused/resumed on context switches
910     return mRenderer->getStateManager()->onMakeCurrent(context);
911 }
912 
onUnMakeCurrent(const gl::Context * context)913 angle::Result ContextGL::onUnMakeCurrent(const gl::Context *context)
914 {
915     ANGLE_TRY(flush(context));
916     if (getFeaturesGL().unbindFBOBeforeSwitchingContext.enabled)
917     {
918         mRenderer->getStateManager()->bindFramebuffer(GL_FRAMEBUFFER, 0);
919     }
920     return ContextImpl::onUnMakeCurrent(context);
921 }
922 
getNativeCaps() const923 gl::Caps ContextGL::getNativeCaps() const
924 {
925     return mRenderer->getNativeCaps();
926 }
927 
getNativeTextureCaps() const928 const gl::TextureCapsMap &ContextGL::getNativeTextureCaps() const
929 {
930     return mRenderer->getNativeTextureCaps();
931 }
932 
getNativeExtensions() const933 const gl::Extensions &ContextGL::getNativeExtensions() const
934 {
935     return mRenderer->getNativeExtensions();
936 }
937 
getNativeLimitations() const938 const gl::Limitations &ContextGL::getNativeLimitations() const
939 {
940     return mRenderer->getNativeLimitations();
941 }
942 
getNativePixelLocalStorageOptions() const943 const ShPixelLocalStorageOptions &ContextGL::getNativePixelLocalStorageOptions() const
944 {
945     return mRenderer->getNativePixelLocalStorageOptions();
946 }
947 
getStateManager()948 StateManagerGL *ContextGL::getStateManager()
949 {
950     return mRenderer->getStateManager();
951 }
952 
getFeaturesGL() const953 const angle::FeaturesGL &ContextGL::getFeaturesGL() const
954 {
955     return mRenderer->getFeatures();
956 }
957 
getBlitter() const958 BlitGL *ContextGL::getBlitter() const
959 {
960     return mRenderer->getBlitter();
961 }
962 
getMultiviewClearer() const963 ClearMultiviewGL *ContextGL::getMultiviewClearer() const
964 {
965     return mRenderer->getMultiviewClearer();
966 }
967 
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)968 angle::Result ContextGL::dispatchCompute(const gl::Context *context,
969                                          GLuint numGroupsX,
970                                          GLuint numGroupsY,
971                                          GLuint numGroupsZ)
972 {
973     return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ);
974 }
975 
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)976 angle::Result ContextGL::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
977 {
978     return mRenderer->dispatchComputeIndirect(context, indirect);
979 }
980 
memoryBarrier(const gl::Context * context,GLbitfield barriers)981 angle::Result ContextGL::memoryBarrier(const gl::Context *context, GLbitfield barriers)
982 {
983     return mRenderer->memoryBarrier(barriers);
984 }
memoryBarrierByRegion(const gl::Context * context,GLbitfield barriers)985 angle::Result ContextGL::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
986 {
987     return mRenderer->memoryBarrierByRegion(barriers);
988 }
989 
framebufferFetchBarrier()990 void ContextGL::framebufferFetchBarrier()
991 {
992     mRenderer->framebufferFetchBarrier();
993 }
994 
setMaxShaderCompilerThreads(GLuint count)995 void ContextGL::setMaxShaderCompilerThreads(GLuint count)
996 {
997     mRenderer->setMaxShaderCompilerThreads(count);
998 }
999 
invalidateTexture(gl::TextureType target)1000 void ContextGL::invalidateTexture(gl::TextureType target)
1001 {
1002     mRenderer->getStateManager()->invalidateTexture(target);
1003 }
1004 
validateState() const1005 void ContextGL::validateState() const
1006 {
1007     const StateManagerGL *stateManager = mRenderer->getStateManager();
1008     stateManager->validateState();
1009 }
1010 
setNeedsFlushBeforeDeleteTextures()1011 void ContextGL::setNeedsFlushBeforeDeleteTextures()
1012 {
1013     mRenderer->setNeedsFlushBeforeDeleteTextures();
1014 }
1015 
flushIfNecessaryBeforeDeleteTextures()1016 void ContextGL::flushIfNecessaryBeforeDeleteTextures()
1017 {
1018     mRenderer->flushIfNecessaryBeforeDeleteTextures();
1019 }
1020 
markWorkSubmitted()1021 void ContextGL::markWorkSubmitted()
1022 {
1023     mRenderer->markWorkSubmitted();
1024 }
1025 
resetDrawStateForPixelLocalStorageEXT(const gl::Context * context)1026 void ContextGL::resetDrawStateForPixelLocalStorageEXT(const gl::Context *context)
1027 {
1028     // Since our load/store shaders require shader images, this extension should only be used if the
1029     // context version is 3.1+.
1030     ASSERT(getFunctions()->isAtLeastGLES(gl::Version(3, 1)));
1031     StateManagerGL *stateMgr = getStateManager();
1032     stateMgr->setCullFaceEnabled(false);
1033     stateMgr->setDepthTestEnabled(false);
1034     stateMgr->setFramebufferSRGBEnabled(context, false);
1035     stateMgr->setPolygonMode(gl::PolygonMode::Fill);
1036     stateMgr->setPolygonOffsetPointEnabled(false);
1037     stateMgr->setPolygonOffsetLineEnabled(false);
1038     stateMgr->setPolygonOffsetFillEnabled(false);
1039     stateMgr->setRasterizerDiscardEnabled(false);
1040     stateMgr->setSampleAlphaToCoverageEnabled(false);
1041     stateMgr->setSampleCoverageEnabled(false);
1042     stateMgr->setScissorTestEnabled(false);
1043     stateMgr->setStencilTestEnabled(false);
1044     stateMgr->setSampleMaskEnabled(false);
1045     stateMgr->setViewport({0, 0, mState.getDrawFramebuffer()->getDefaultWidth(),
1046                            mState.getDrawFramebuffer()->getDefaultHeight()});
1047     // Color mask, dither, and blend don't affect EXT_shader_pixel_local_storage or shader images.
1048 }
1049 
drawPixelLocalStorageEXTEnable(gl::Context * context,GLsizei n,const gl::PixelLocalStoragePlane planes[],const GLenum loadops[])1050 angle::Result ContextGL::drawPixelLocalStorageEXTEnable(gl::Context *context,
1051                                                         GLsizei n,
1052                                                         const gl::PixelLocalStoragePlane planes[],
1053                                                         const GLenum loadops[])
1054 {
1055     ASSERT(getNativePixelLocalStorageOptions().type ==
1056            ShPixelLocalStorageType::PixelLocalStorageEXT);
1057 
1058     getFunctions()->enable(GL_SHADER_PIXEL_LOCAL_STORAGE_EXT);
1059 
1060     PLSProgramKeyBuilder b;
1061     for (GLsizei i = n - 1; i >= 0; --i)
1062     {
1063         const gl::PixelLocalStoragePlane &plane = planes[i];
1064         GLenum loadop                           = loadops[i];
1065         bool preserved                          = loadop == GL_LOAD_OP_LOAD_ANGLE;
1066         b.prependPlane(plane.getInternalformat(), preserved);
1067         if (preserved)
1068         {
1069             const gl::ImageIndex &idx = plane.getTextureImageIndex();
1070             getStateManager()->bindImageTexture(i, plane.getBackingTexture(context)->getNativeID(),
1071                                                 idx.getLevelIndex(), GL_FALSE, idx.getLayerIndex(),
1072                                                 GL_READ_ONLY, plane.getInternalformat());
1073         }
1074     }
1075     PLSProgramKey key = b.finish(PLSProgramType::Load);
1076 
1077     PLSProgramCache *cache       = mRenderer->getPLSProgramCache();
1078     const PLSProgram *plsProgram = cache->getProgram(key);
1079     getStateManager()->forceUseProgram(plsProgram->getProgramID());
1080     plsProgram->setClearValues(planes, loadops);
1081     getStateManager()->bindVertexArray(cache->getEmptyVAO(), cache->getEmptyVAOState());
1082     resetDrawStateForPixelLocalStorageEXT(context);
1083 
1084     ANGLE_GL_TRY(context, getFunctions()->drawArrays(GL_TRIANGLE_STRIP, 0, 4));
1085     mRenderer->markWorkSubmitted();
1086 
1087     return angle::Result::Continue;
1088 }
1089 
drawPixelLocalStorageEXTDisable(gl::Context * context,const gl::PixelLocalStoragePlane planes[],const GLenum storeops[])1090 angle::Result ContextGL::drawPixelLocalStorageEXTDisable(gl::Context *context,
1091                                                          const gl::PixelLocalStoragePlane planes[],
1092                                                          const GLenum storeops[])
1093 {
1094     ASSERT(getNativePixelLocalStorageOptions().type ==
1095            ShPixelLocalStorageType::PixelLocalStorageEXT);
1096 
1097     GLsizei n = context->getState().getPixelLocalStorageActivePlanes();
1098 
1099     PLSProgramKeyBuilder b;
1100     for (GLsizei i = n - 1; i >= 0; --i)
1101     {
1102         const gl::PixelLocalStoragePlane &plane = planes[i];
1103         bool preserved =
1104             plane.isActive() && !plane.isMemoryless() && storeops[i] == GL_STORE_OP_STORE_ANGLE;
1105         b.prependPlane(plane.isActive() ? plane.getInternalformat() : GL_NONE, preserved);
1106         if (preserved)
1107         {
1108             const gl::ImageIndex &idx = plane.getTextureImageIndex();
1109             getStateManager()->bindImageTexture(i, plane.getBackingTexture(context)->getNativeID(),
1110                                                 idx.getLevelIndex(), GL_FALSE, idx.getLayerIndex(),
1111                                                 GL_WRITE_ONLY, plane.getInternalformat());
1112         }
1113     }
1114     PLSProgramKey key = b.finish(PLSProgramType::Store);
1115 
1116     if (key.areAnyPreserved())
1117     {
1118         PLSProgramCache *cache       = mRenderer->getPLSProgramCache();
1119         const PLSProgram *plsProgram = cache->getProgram(key);
1120         getStateManager()->forceUseProgram(plsProgram->getProgramID());
1121         getStateManager()->bindVertexArray(cache->getEmptyVAO(), cache->getEmptyVAOState());
1122         resetDrawStateForPixelLocalStorageEXT(context);
1123 
1124         ANGLE_GL_TRY(context, getFunctions()->drawArrays(GL_TRIANGLE_STRIP, 0, 4));
1125         mRenderer->markWorkSubmitted();
1126     }
1127 
1128     getFunctions()->disable(GL_SHADER_PIXEL_LOCAL_STORAGE_EXT);
1129 
1130     return angle::Result::Continue;
1131 }
1132 
1133 }  // namespace rx
1134