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