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