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