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