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