• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 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 
7 // StateManagerGL.h: Defines a class for caching applied OpenGL state
8 
9 #include "libANGLE/renderer/gl/StateManagerGL.h"
10 
11 #include <string.h>
12 #include <algorithm>
13 #include <limits>
14 
15 #include "anglebase/numerics/safe_conversions.h"
16 #include "common/bitset_utils.h"
17 #include "common/mathutil.h"
18 #include "common/matrix_utils.h"
19 #include "libANGLE/Context.h"
20 #include "libANGLE/Framebuffer.h"
21 #include "libANGLE/Query.h"
22 #include "libANGLE/TransformFeedback.h"
23 #include "libANGLE/VertexArray.h"
24 #include "libANGLE/renderer/gl/BufferGL.h"
25 #include "libANGLE/renderer/gl/FramebufferGL.h"
26 #include "libANGLE/renderer/gl/FunctionsGL.h"
27 #include "libANGLE/renderer/gl/ProgramGL.h"
28 #include "libANGLE/renderer/gl/QueryGL.h"
29 #include "libANGLE/renderer/gl/SamplerGL.h"
30 #include "libANGLE/renderer/gl/TextureGL.h"
31 #include "libANGLE/renderer/gl/TransformFeedbackGL.h"
32 #include "libANGLE/renderer/gl/VertexArrayGL.h"
33 
34 namespace rx
35 {
36 
37 namespace
38 {
39 
ValidateStateHelper(const FunctionsGL * functions,const GLuint localValue,const GLenum pname,const char * localName,const char * driverName)40 static void ValidateStateHelper(const FunctionsGL *functions,
41                                 const GLuint localValue,
42                                 const GLenum pname,
43                                 const char *localName,
44                                 const char *driverName)
45 {
46     GLint queryValue;
47     functions->getIntegerv(pname, &queryValue);
48     if (localValue != static_cast<GLuint>(queryValue))
49     {
50         WARN() << localName << " (" << localValue << ") != " << driverName << " (" << queryValue
51                << ")";
52         // Re-add ASSERT: http://anglebug.com/3900
53         // ASSERT(false);
54     }
55 }
56 
57 }  // anonymous namespace
58 
IndexedBufferBinding()59 StateManagerGL::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0) {}
60 
StateManagerGL(const FunctionsGL * functions,const gl::Caps & rendererCaps,const gl::Extensions & extensions,const angle::FeaturesGL & features)61 StateManagerGL::StateManagerGL(const FunctionsGL *functions,
62                                const gl::Caps &rendererCaps,
63                                const gl::Extensions &extensions,
64                                const angle::FeaturesGL &features)
65     : mFunctions(functions),
66       mFeatures(features),
67       mProgram(0),
68       mVAO(0),
69       mVertexAttribCurrentValues(rendererCaps.maxVertexAttributes),
70       mBuffers(),
71       mIndexedBuffers(),
72       mTextureUnitIndex(0),
73       mTextures{},
74       mSamplers{},
75       mImages(rendererCaps.maxImageUnits, ImageUnitBinding()),
76       mTransformFeedback(0),
77       mCurrentTransformFeedback(nullptr),
78       mQueries(),
79       mPrevDrawContext(0),
80       mUnpackAlignment(4),
81       mUnpackRowLength(0),
82       mUnpackSkipRows(0),
83       mUnpackSkipPixels(0),
84       mUnpackImageHeight(0),
85       mUnpackSkipImages(0),
86       mPackAlignment(4),
87       mPackRowLength(0),
88       mPackSkipRows(0),
89       mPackSkipPixels(0),
90       mFramebuffers(angle::FramebufferBindingSingletonMax, 0),
91       mRenderbuffer(0),
92       mScissorTestEnabled(false),
93       mScissor(0, 0, 0, 0),
94       mViewport(0, 0, 0, 0),
95       mNear(0.0f),
96       mFar(1.0f),
97       mBlendColor(0, 0, 0, 0),
98       mBlendStateExt(rendererCaps.maxDrawBuffers),
99       mIndependentBlendStates(extensions.drawBuffersIndexedAny()),
100       mSampleAlphaToCoverageEnabled(false),
101       mSampleCoverageEnabled(false),
102       mSampleCoverageValue(1.0f),
103       mSampleCoverageInvert(false),
104       mSampleMaskEnabled(false),
105       mDepthTestEnabled(false),
106       mDepthFunc(GL_LESS),
107       mDepthMask(true),
108       mStencilTestEnabled(false),
109       mStencilFrontFunc(GL_ALWAYS),
110       mStencilFrontRef(0),
111       mStencilFrontValueMask(static_cast<GLuint>(-1)),
112       mStencilFrontStencilFailOp(GL_KEEP),
113       mStencilFrontStencilPassDepthFailOp(GL_KEEP),
114       mStencilFrontStencilPassDepthPassOp(GL_KEEP),
115       mStencilFrontWritemask(static_cast<GLuint>(-1)),
116       mStencilBackFunc(GL_ALWAYS),
117       mStencilBackRef(0),
118       mStencilBackValueMask(static_cast<GLuint>(-1)),
119       mStencilBackStencilFailOp(GL_KEEP),
120       mStencilBackStencilPassDepthFailOp(GL_KEEP),
121       mStencilBackStencilPassDepthPassOp(GL_KEEP),
122       mStencilBackWritemask(static_cast<GLuint>(-1)),
123       mCullFaceEnabled(false),
124       mCullFace(gl::CullFaceMode::Back),
125       mFrontFace(GL_CCW),
126       mPolygonOffsetFillEnabled(false),
127       mPolygonOffsetFactor(0.0f),
128       mPolygonOffsetUnits(0.0f),
129       mRasterizerDiscardEnabled(false),
130       mLineWidth(1.0f),
131       mPrimitiveRestartEnabled(false),
132       mPrimitiveRestartIndex(0),
133       mClearColor(0.0f, 0.0f, 0.0f, 0.0f),
134       mClearDepth(1.0f),
135       mClearStencil(0),
136       mFramebufferSRGBAvailable(extensions.sRGBWriteControl),
137       mFramebufferSRGBEnabled(false),
138       mDitherEnabled(true),
139       mTextureCubemapSeamlessEnabled(false),
140       mMultisamplingEnabled(true),
141       mSampleAlphaToOneEnabled(false),
142       mCoverageModulation(GL_NONE),
143       mIsMultiviewEnabled(extensions.multiview || extensions.multiview2),
144       mProvokingVertex(GL_LAST_VERTEX_CONVENTION),
145       mMaxClipDistances(rendererCaps.maxClipDistances),
146       mLocalDirtyBits()
147 {
148     ASSERT(mFunctions);
149     ASSERT(extensions.maxViews >= 1u);
150 
151     mIndexedBuffers[gl::BufferBinding::Uniform].resize(rendererCaps.maxUniformBufferBindings);
152     mIndexedBuffers[gl::BufferBinding::AtomicCounter].resize(
153         rendererCaps.maxAtomicCounterBufferBindings);
154     mIndexedBuffers[gl::BufferBinding::ShaderStorage].resize(
155         rendererCaps.maxShaderStorageBufferBindings);
156 
157     mSampleMaskValues.fill(~GLbitfield(0));
158 
159     mQueries.fill(nullptr);
160     mTemporaryPausedQueries.fill(nullptr);
161 
162     // Initialize point sprite state for desktop GL
163     if (mFunctions->standard == STANDARD_GL_DESKTOP)
164     {
165         mFunctions->enable(GL_PROGRAM_POINT_SIZE);
166 
167         // GL_POINT_SPRITE was deprecated in the core profile. Point rasterization is always
168         // performed
169         // as though POINT_SPRITE were enabled.
170         if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) == 0)
171         {
172             mFunctions->enable(GL_POINT_SPRITE);
173         }
174     }
175 
176     if (features.emulatePrimitiveRestartFixedIndex.enabled)
177     {
178         // There is no consistent default value for primitive restart index. Set it to UINT -1.
179         constexpr GLuint primitiveRestartIndex = gl::GetPrimitiveRestartIndexFromType<GLuint>();
180         mFunctions->primitiveRestartIndex(primitiveRestartIndex);
181         mPrimitiveRestartIndex = primitiveRestartIndex;
182     }
183 }
184 
~StateManagerGL()185 StateManagerGL::~StateManagerGL() {}
186 
deleteProgram(GLuint program)187 void StateManagerGL::deleteProgram(GLuint program)
188 {
189     if (program != 0)
190     {
191         if (mProgram == program)
192         {
193             useProgram(0);
194         }
195 
196         mFunctions->deleteProgram(program);
197     }
198 }
199 
deleteVertexArray(GLuint vao)200 void StateManagerGL::deleteVertexArray(GLuint vao)
201 {
202     if (vao != 0)
203     {
204         if (mVAO == vao)
205         {
206             bindVertexArray(0, 0);
207         }
208 
209         mFunctions->deleteVertexArrays(1, &vao);
210     }
211 }
212 
deleteTexture(GLuint texture)213 void StateManagerGL::deleteTexture(GLuint texture)
214 {
215     if (texture != 0)
216     {
217         for (gl::TextureType type : angle::AllEnums<gl::TextureType>())
218         {
219             const auto &textureVector = mTextures[type];
220             for (size_t textureUnitIndex = 0; textureUnitIndex < textureVector.size();
221                  textureUnitIndex++)
222             {
223                 if (textureVector[textureUnitIndex] == texture)
224                 {
225                     activeTexture(textureUnitIndex);
226                     bindTexture(type, 0);
227                 }
228             }
229         }
230 
231         for (size_t imageUnitIndex = 0; imageUnitIndex < mImages.size(); imageUnitIndex++)
232         {
233             if (mImages[imageUnitIndex].texture == texture)
234             {
235                 bindImageTexture(imageUnitIndex, 0, 0, false, 0, GL_READ_ONLY, GL_R32UI);
236             }
237         }
238 
239         mFunctions->deleteTextures(1, &texture);
240     }
241 }
242 
deleteSampler(GLuint sampler)243 void StateManagerGL::deleteSampler(GLuint sampler)
244 {
245     if (sampler != 0)
246     {
247         for (size_t unit = 0; unit < mSamplers.size(); unit++)
248         {
249             if (mSamplers[unit] == sampler)
250             {
251                 bindSampler(unit, 0);
252             }
253         }
254 
255         mFunctions->deleteSamplers(1, &sampler);
256     }
257 }
258 
deleteBuffer(GLuint buffer)259 void StateManagerGL::deleteBuffer(GLuint buffer)
260 {
261     if (buffer == 0)
262     {
263         return;
264     }
265 
266     for (auto target : angle::AllEnums<gl::BufferBinding>())
267     {
268         if (mBuffers[target] == buffer)
269         {
270             bindBuffer(target, 0);
271         }
272 
273         auto &indexedTarget = mIndexedBuffers[target];
274         for (size_t bindIndex = 0; bindIndex < indexedTarget.size(); ++bindIndex)
275         {
276             if (indexedTarget[bindIndex].buffer == buffer)
277             {
278                 bindBufferBase(target, bindIndex, 0);
279             }
280         }
281     }
282 
283     mFunctions->deleteBuffers(1, &buffer);
284 }
285 
deleteFramebuffer(GLuint fbo)286 void StateManagerGL::deleteFramebuffer(GLuint fbo)
287 {
288     if (fbo != 0)
289     {
290         for (size_t binding = 0; binding < mFramebuffers.size(); ++binding)
291         {
292             if (mFramebuffers[binding] == fbo)
293             {
294                 GLenum enumValue = angle::FramebufferBindingToEnum(
295                     static_cast<angle::FramebufferBinding>(binding));
296                 bindFramebuffer(enumValue, 0);
297             }
298         }
299         mFunctions->deleteFramebuffers(1, &fbo);
300     }
301 }
302 
deleteRenderbuffer(GLuint rbo)303 void StateManagerGL::deleteRenderbuffer(GLuint rbo)
304 {
305     if (rbo != 0)
306     {
307         if (mRenderbuffer == rbo)
308         {
309             bindRenderbuffer(GL_RENDERBUFFER, 0);
310         }
311 
312         mFunctions->deleteRenderbuffers(1, &rbo);
313     }
314 }
315 
deleteTransformFeedback(GLuint transformFeedback)316 void StateManagerGL::deleteTransformFeedback(GLuint transformFeedback)
317 {
318     if (transformFeedback != 0)
319     {
320         if (mTransformFeedback == transformFeedback)
321         {
322             bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
323         }
324 
325         if (mCurrentTransformFeedback != nullptr &&
326             mCurrentTransformFeedback->getTransformFeedbackID() == transformFeedback)
327         {
328             mCurrentTransformFeedback = nullptr;
329         }
330 
331         mFunctions->deleteTransformFeedbacks(1, &transformFeedback);
332     }
333 }
334 
useProgram(GLuint program)335 void StateManagerGL::useProgram(GLuint program)
336 {
337     if (mProgram != program)
338     {
339         forceUseProgram(program);
340     }
341 }
342 
forceUseProgram(GLuint program)343 void StateManagerGL::forceUseProgram(GLuint program)
344 {
345     mProgram = program;
346     mFunctions->useProgram(mProgram);
347     mLocalDirtyBits.set(gl::State::DIRTY_BIT_PROGRAM_BINDING);
348 }
349 
bindVertexArray(GLuint vao,GLuint elementArrayBuffer)350 void StateManagerGL::bindVertexArray(GLuint vao, GLuint elementArrayBuffer)
351 {
352     if (mVAO != vao)
353     {
354         mVAO                                      = vao;
355         mBuffers[gl::BufferBinding::ElementArray] = elementArrayBuffer;
356         mFunctions->bindVertexArray(vao);
357 
358         mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
359     }
360 }
361 
bindBuffer(gl::BufferBinding target,GLuint buffer)362 void StateManagerGL::bindBuffer(gl::BufferBinding target, GLuint buffer)
363 {
364     // GL drivers differ in whether the transform feedback bind point is modified when
365     // glBindTransformFeedback is called. To avoid these behavior differences we shouldn't try to
366     // use it.
367     ASSERT(target != gl::BufferBinding::TransformFeedback);
368     if (mBuffers[target] != buffer)
369     {
370         mBuffers[target] = buffer;
371         mFunctions->bindBuffer(gl::ToGLenum(target), buffer);
372     }
373 }
374 
bindBufferBase(gl::BufferBinding target,size_t index,GLuint buffer)375 void StateManagerGL::bindBufferBase(gl::BufferBinding target, size_t index, GLuint buffer)
376 {
377     // Transform feedback buffer bindings are tracked in TransformFeedbackGL
378     ASSERT(target != gl::BufferBinding::TransformFeedback);
379 
380     ASSERT(index < mIndexedBuffers[target].size());
381     auto &binding = mIndexedBuffers[target][index];
382     if (binding.buffer != buffer || binding.offset != static_cast<size_t>(-1) ||
383         binding.size != static_cast<size_t>(-1))
384     {
385         binding.buffer   = buffer;
386         binding.offset   = static_cast<size_t>(-1);
387         binding.size     = static_cast<size_t>(-1);
388         mBuffers[target] = buffer;
389         mFunctions->bindBufferBase(gl::ToGLenum(target), static_cast<GLuint>(index), buffer);
390     }
391 }
392 
bindBufferRange(gl::BufferBinding target,size_t index,GLuint buffer,size_t offset,size_t size)393 void StateManagerGL::bindBufferRange(gl::BufferBinding target,
394                                      size_t index,
395                                      GLuint buffer,
396                                      size_t offset,
397                                      size_t size)
398 {
399     // Transform feedback buffer bindings are tracked in TransformFeedbackGL
400     ASSERT(target != gl::BufferBinding::TransformFeedback);
401 
402     auto &binding = mIndexedBuffers[target][index];
403     if (binding.buffer != buffer || binding.offset != offset || binding.size != size)
404     {
405         binding.buffer   = buffer;
406         binding.offset   = offset;
407         binding.size     = size;
408         mBuffers[target] = buffer;
409         mFunctions->bindBufferRange(gl::ToGLenum(target), static_cast<GLuint>(index), buffer,
410                                     offset, size);
411     }
412 }
413 
activeTexture(size_t unit)414 void StateManagerGL::activeTexture(size_t unit)
415 {
416     if (mTextureUnitIndex != unit)
417     {
418         mTextureUnitIndex = unit;
419         mFunctions->activeTexture(GL_TEXTURE0 + static_cast<GLenum>(mTextureUnitIndex));
420     }
421 }
422 
bindTexture(gl::TextureType type,GLuint texture)423 void StateManagerGL::bindTexture(gl::TextureType type, GLuint texture)
424 {
425     gl::TextureType nativeType = nativegl::GetNativeTextureType(type);
426     if (mTextures[nativeType][mTextureUnitIndex] != texture)
427     {
428         mTextures[nativeType][mTextureUnitIndex] = texture;
429         mFunctions->bindTexture(nativegl::GetTextureBindingTarget(type), texture);
430         mLocalDirtyBits.set(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
431     }
432 }
433 
invalidateTexture(gl::TextureType type)434 void StateManagerGL::invalidateTexture(gl::TextureType type)
435 {
436     // Assume the tracked texture binding is incorrect, query the real bound texture from GL.
437     GLint boundTexture = 0;
438     mFunctions->getIntegerv(nativegl::GetTextureBindingQuery(type), &boundTexture);
439     mTextures[type][mTextureUnitIndex] = static_cast<GLuint>(boundTexture);
440     mLocalDirtyBits.set(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
441 }
442 
bindSampler(size_t unit,GLuint sampler)443 void StateManagerGL::bindSampler(size_t unit, GLuint sampler)
444 {
445     if (mSamplers[unit] != sampler)
446     {
447         mSamplers[unit] = sampler;
448         mFunctions->bindSampler(static_cast<GLuint>(unit), sampler);
449         mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLER_BINDINGS);
450     }
451 }
452 
bindImageTexture(size_t unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)453 void StateManagerGL::bindImageTexture(size_t unit,
454                                       GLuint texture,
455                                       GLint level,
456                                       GLboolean layered,
457                                       GLint layer,
458                                       GLenum access,
459                                       GLenum format)
460 {
461     auto &binding = mImages[unit];
462     if (binding.texture != texture || binding.level != level || binding.layered != layered ||
463         binding.layer != layer || binding.access != access || binding.format != format)
464     {
465         binding.texture = texture;
466         binding.level   = level;
467         binding.layered = layered;
468         binding.layer   = layer;
469         binding.access  = access;
470         binding.format  = format;
471         mFunctions->bindImageTexture(angle::base::checked_cast<GLuint>(unit), texture, level,
472                                      layered, layer, access, format);
473     }
474 }
475 
setPixelUnpackState(const gl::PixelUnpackState & unpack)476 void StateManagerGL::setPixelUnpackState(const gl::PixelUnpackState &unpack)
477 {
478     if (mUnpackAlignment != unpack.alignment)
479     {
480         mUnpackAlignment = unpack.alignment;
481         mFunctions->pixelStorei(GL_UNPACK_ALIGNMENT, mUnpackAlignment);
482 
483         mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
484     }
485 
486     if (mUnpackRowLength != unpack.rowLength)
487     {
488         mUnpackRowLength = unpack.rowLength;
489         mFunctions->pixelStorei(GL_UNPACK_ROW_LENGTH, mUnpackRowLength);
490 
491         mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
492     }
493 
494     if (mUnpackSkipRows != unpack.skipRows)
495     {
496         mUnpackSkipRows = unpack.skipRows;
497         mFunctions->pixelStorei(GL_UNPACK_SKIP_ROWS, mUnpackSkipRows);
498 
499         mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
500     }
501 
502     if (mUnpackSkipPixels != unpack.skipPixels)
503     {
504         mUnpackSkipPixels = unpack.skipPixels;
505         mFunctions->pixelStorei(GL_UNPACK_SKIP_PIXELS, mUnpackSkipPixels);
506 
507         mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
508     }
509 
510     if (mUnpackImageHeight != unpack.imageHeight)
511     {
512         mUnpackImageHeight = unpack.imageHeight;
513         mFunctions->pixelStorei(GL_UNPACK_IMAGE_HEIGHT, mUnpackImageHeight);
514 
515         mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
516     }
517 
518     if (mUnpackSkipImages != unpack.skipImages)
519     {
520         mUnpackSkipImages = unpack.skipImages;
521         mFunctions->pixelStorei(GL_UNPACK_SKIP_IMAGES, mUnpackSkipImages);
522 
523         mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
524     }
525 }
526 
setPixelUnpackBuffer(const gl::Buffer * pixelBuffer)527 void StateManagerGL::setPixelUnpackBuffer(const gl::Buffer *pixelBuffer)
528 {
529     GLuint bufferID = 0;
530     if (pixelBuffer != nullptr)
531     {
532         bufferID = GetImplAs<BufferGL>(pixelBuffer)->getBufferID();
533     }
534     bindBuffer(gl::BufferBinding::PixelUnpack, bufferID);
535 }
536 
setPixelPackState(const gl::PixelPackState & pack)537 void StateManagerGL::setPixelPackState(const gl::PixelPackState &pack)
538 {
539     if (mPackAlignment != pack.alignment)
540     {
541         mPackAlignment = pack.alignment;
542         mFunctions->pixelStorei(GL_PACK_ALIGNMENT, mPackAlignment);
543 
544         mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
545     }
546 
547     if (mPackRowLength != pack.rowLength)
548     {
549         mPackRowLength = pack.rowLength;
550         mFunctions->pixelStorei(GL_PACK_ROW_LENGTH, mPackRowLength);
551 
552         mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
553     }
554 
555     if (mPackSkipRows != pack.skipRows)
556     {
557         mPackSkipRows = pack.skipRows;
558         mFunctions->pixelStorei(GL_PACK_SKIP_ROWS, mPackSkipRows);
559 
560         mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
561     }
562 
563     if (mPackSkipPixels != pack.skipPixels)
564     {
565         mPackSkipPixels = pack.skipPixels;
566         mFunctions->pixelStorei(GL_PACK_SKIP_PIXELS, mPackSkipPixels);
567 
568         mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
569     }
570 }
571 
setPixelPackBuffer(const gl::Buffer * pixelBuffer)572 void StateManagerGL::setPixelPackBuffer(const gl::Buffer *pixelBuffer)
573 {
574     GLuint bufferID = 0;
575     if (pixelBuffer != nullptr)
576     {
577         bufferID = GetImplAs<BufferGL>(pixelBuffer)->getBufferID();
578     }
579     bindBuffer(gl::BufferBinding::PixelPack, bufferID);
580 }
581 
bindFramebuffer(GLenum type,GLuint framebuffer)582 void StateManagerGL::bindFramebuffer(GLenum type, GLuint framebuffer)
583 {
584     switch (type)
585     {
586         case GL_FRAMEBUFFER:
587             if (mFramebuffers[angle::FramebufferBindingRead] != framebuffer ||
588                 mFramebuffers[angle::FramebufferBindingDraw] != framebuffer)
589             {
590                 mFramebuffers[angle::FramebufferBindingRead] = framebuffer;
591                 mFramebuffers[angle::FramebufferBindingDraw] = framebuffer;
592                 mFunctions->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
593 
594                 mLocalDirtyBits.set(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
595                 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
596             }
597             break;
598 
599         case GL_READ_FRAMEBUFFER:
600             if (mFramebuffers[angle::FramebufferBindingRead] != framebuffer)
601             {
602                 mFramebuffers[angle::FramebufferBindingRead] = framebuffer;
603                 mFunctions->bindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
604 
605                 mLocalDirtyBits.set(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
606             }
607             break;
608 
609         case GL_DRAW_FRAMEBUFFER:
610             if (mFramebuffers[angle::FramebufferBindingDraw] != framebuffer)
611             {
612                 mFramebuffers[angle::FramebufferBindingDraw] = framebuffer;
613                 mFunctions->bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
614 
615                 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
616             }
617             break;
618 
619         default:
620             UNREACHABLE();
621             break;
622     }
623 }
624 
bindRenderbuffer(GLenum type,GLuint renderbuffer)625 void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer)
626 {
627     ASSERT(type == GL_RENDERBUFFER);
628     if (mRenderbuffer != renderbuffer)
629     {
630         mRenderbuffer = renderbuffer;
631         mFunctions->bindRenderbuffer(type, mRenderbuffer);
632     }
633 }
634 
bindTransformFeedback(GLenum type,GLuint transformFeedback)635 void StateManagerGL::bindTransformFeedback(GLenum type, GLuint transformFeedback)
636 {
637     ASSERT(type == GL_TRANSFORM_FEEDBACK);
638     if (mTransformFeedback != transformFeedback)
639     {
640         // Pause the current transform feedback if one is active.
641         // To handle virtualized contexts, StateManagerGL needs to be able to bind a new transform
642         // feedback at any time, even if there is one active.
643         if (mCurrentTransformFeedback != nullptr &&
644             mCurrentTransformFeedback->getTransformFeedbackID() != transformFeedback)
645         {
646             mCurrentTransformFeedback->syncPausedState(true);
647             mCurrentTransformFeedback = nullptr;
648         }
649 
650         mTransformFeedback = transformFeedback;
651         mFunctions->bindTransformFeedback(type, mTransformFeedback);
652         onTransformFeedbackStateChange();
653     }
654 }
655 
onTransformFeedbackStateChange()656 void StateManagerGL::onTransformFeedbackStateChange()
657 {
658     mLocalDirtyBits.set(gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING);
659 }
660 
beginQuery(gl::QueryType type,QueryGL * queryObject,GLuint queryId)661 void StateManagerGL::beginQuery(gl::QueryType type, QueryGL *queryObject, GLuint queryId)
662 {
663     // Make sure this is a valid query type and there is no current active query of this type
664     ASSERT(mQueries[type] == nullptr);
665     ASSERT(queryId != 0);
666 
667     mQueries[type] = queryObject;
668     mFunctions->beginQuery(ToGLenum(type), queryId);
669 }
670 
endQuery(gl::QueryType type,QueryGL * queryObject,GLuint queryId)671 void StateManagerGL::endQuery(gl::QueryType type, QueryGL *queryObject, GLuint queryId)
672 {
673     ASSERT(queryObject != nullptr);
674     ASSERT(mQueries[type] == queryObject);
675     mQueries[type] = nullptr;
676     mFunctions->endQuery(ToGLenum(type));
677 }
678 
updateDrawIndirectBufferBinding(const gl::Context * context)679 void StateManagerGL::updateDrawIndirectBufferBinding(const gl::Context *context)
680 {
681     gl::Buffer *drawIndirectBuffer =
682         context->getState().getTargetBuffer(gl::BufferBinding::DrawIndirect);
683     if (drawIndirectBuffer != nullptr)
684     {
685         const BufferGL *bufferGL = GetImplAs<BufferGL>(drawIndirectBuffer);
686         bindBuffer(gl::BufferBinding::DrawIndirect, bufferGL->getBufferID());
687     }
688 }
689 
updateDispatchIndirectBufferBinding(const gl::Context * context)690 void StateManagerGL::updateDispatchIndirectBufferBinding(const gl::Context *context)
691 {
692     gl::Buffer *dispatchIndirectBuffer =
693         context->getState().getTargetBuffer(gl::BufferBinding::DispatchIndirect);
694     if (dispatchIndirectBuffer != nullptr)
695     {
696         const BufferGL *bufferGL = GetImplAs<BufferGL>(dispatchIndirectBuffer);
697         bindBuffer(gl::BufferBinding::DispatchIndirect, bufferGL->getBufferID());
698     }
699 }
700 
pauseTransformFeedback()701 void StateManagerGL::pauseTransformFeedback()
702 {
703     if (mCurrentTransformFeedback != nullptr)
704     {
705         mCurrentTransformFeedback->syncPausedState(true);
706         onTransformFeedbackStateChange();
707     }
708 }
709 
pauseAllQueries(const gl::Context * context)710 angle::Result StateManagerGL::pauseAllQueries(const gl::Context *context)
711 {
712     for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
713     {
714         QueryGL *previousQuery = mQueries[type];
715 
716         if (previousQuery != nullptr)
717         {
718             ANGLE_TRY(previousQuery->pause(context));
719             mTemporaryPausedQueries[type] = previousQuery;
720             mQueries[type]                = nullptr;
721         }
722     }
723 
724     return angle::Result::Continue;
725 }
726 
pauseQuery(const gl::Context * context,gl::QueryType type)727 angle::Result StateManagerGL::pauseQuery(const gl::Context *context, gl::QueryType type)
728 {
729     QueryGL *previousQuery = mQueries[type];
730 
731     if (previousQuery)
732     {
733         ANGLE_TRY(previousQuery->pause(context));
734         mTemporaryPausedQueries[type] = previousQuery;
735         mQueries[type]                = nullptr;
736     }
737 
738     return angle::Result::Continue;
739 }
740 
resumeAllQueries(const gl::Context * context)741 angle::Result StateManagerGL::resumeAllQueries(const gl::Context *context)
742 {
743     for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
744     {
745         QueryGL *pausedQuery = mTemporaryPausedQueries[type];
746 
747         if (pausedQuery != nullptr)
748         {
749             ASSERT(mQueries[type] == nullptr);
750             ANGLE_TRY(pausedQuery->resume(context));
751             mTemporaryPausedQueries[type] = nullptr;
752         }
753     }
754 
755     return angle::Result::Continue;
756 }
757 
resumeQuery(const gl::Context * context,gl::QueryType type)758 angle::Result StateManagerGL::resumeQuery(const gl::Context *context, gl::QueryType type)
759 {
760     QueryGL *pausedQuery = mTemporaryPausedQueries[type];
761 
762     if (pausedQuery != nullptr)
763     {
764         ANGLE_TRY(pausedQuery->resume(context));
765         mTemporaryPausedQueries[type] = nullptr;
766     }
767 
768     return angle::Result::Continue;
769 }
770 
onMakeCurrent(const gl::Context * context)771 angle::Result StateManagerGL::onMakeCurrent(const gl::Context *context)
772 {
773     const gl::State &glState = context->getState();
774 
775 #if defined(ANGLE_ENABLE_ASSERTS)
776     // Temporarily pausing queries during context switch is not supported
777     for (QueryGL *pausedQuery : mTemporaryPausedQueries)
778     {
779         ASSERT(pausedQuery == nullptr);
780     }
781 #endif
782 
783     // If the context has changed, pause the previous context's queries
784     auto contextID = context->getState().getContextID();
785     if (contextID != mPrevDrawContext)
786     {
787         for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
788         {
789             QueryGL *currentQuery = mQueries[type];
790             // Pause any old query object
791             if (currentQuery != nullptr)
792             {
793                 ANGLE_TRY(currentQuery->pause(context));
794                 mQueries[type] = nullptr;
795             }
796 
797             // Check if this new context needs to resume a query
798             gl::Query *newQuery = glState.getActiveQuery(type);
799             if (newQuery != nullptr)
800             {
801                 QueryGL *queryGL = GetImplAs<QueryGL>(newQuery);
802                 ANGLE_TRY(queryGL->resume(context));
803             }
804         }
805     }
806     onTransformFeedbackStateChange();
807     mPrevDrawContext = contextID;
808 
809     // Seamless cubemaps are required for ES3 and higher contexts. It should be the cheapest to set
810     // this state here since MakeCurrent is expected to be called less frequently than draw calls.
811     setTextureCubemapSeamlessEnabled(context->getClientMajorVersion() >= 3);
812 
813     return angle::Result::Continue;
814 }
815 
updateProgramTextureBindings(const gl::Context * context)816 void StateManagerGL::updateProgramTextureBindings(const gl::Context *context)
817 {
818     const gl::State &glState                = context->getState();
819     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
820 
821     // It is possible there is no active program during a path operation.
822     if (!executable)
823         return;
824 
825     const gl::ActiveTexturesCache &textures        = glState.getActiveTexturesCache();
826     const gl::ActiveTextureMask &activeTextures    = executable->getActiveSamplersMask();
827     const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
828 
829     for (size_t textureUnitIndex : activeTextures)
830     {
831         gl::TextureType textureType = textureTypes[textureUnitIndex];
832         gl::Texture *texture        = textures[textureUnitIndex];
833 
834         // A nullptr texture indicates incomplete.
835         if (texture != nullptr)
836         {
837             const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
838             ASSERT(!texture->hasAnyDirtyBit());
839             ASSERT(!textureGL->hasAnyDirtyBit());
840 
841             activeTexture(textureUnitIndex);
842             bindTexture(textureType, textureGL->getTextureID());
843         }
844         else
845         {
846             activeTexture(textureUnitIndex);
847             bindTexture(textureType, 0);
848         }
849     }
850 }
851 
updateProgramStorageBufferBindings(const gl::Context * context)852 void StateManagerGL::updateProgramStorageBufferBindings(const gl::Context *context)
853 {
854     const gl::State &glState   = context->getState();
855     const gl::Program *program = glState.getProgram();
856 
857     for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
858          blockIndex++)
859     {
860         GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
861         const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
862 
863         if (shaderStorageBuffer.get() != nullptr)
864         {
865             BufferGL *bufferGL = GetImplAs<BufferGL>(shaderStorageBuffer.get());
866 
867             if (shaderStorageBuffer.getSize() == 0)
868             {
869                 bindBufferBase(gl::BufferBinding::ShaderStorage, binding, bufferGL->getBufferID());
870             }
871             else
872             {
873                 bindBufferRange(gl::BufferBinding::ShaderStorage, binding, bufferGL->getBufferID(),
874                                 shaderStorageBuffer.getOffset(), shaderStorageBuffer.getSize());
875             }
876         }
877     }
878 }
879 
updateProgramUniformBufferBindings(const gl::Context * context)880 void StateManagerGL::updateProgramUniformBufferBindings(const gl::Context *context)
881 {
882     // Sync the current program state
883     const gl::State &glState   = context->getState();
884     const gl::Program *program = glState.getProgram();
885 
886     for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
887          uniformBlockIndex++)
888     {
889         GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
890         const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding);
891 
892         if (uniformBuffer.get() != nullptr)
893         {
894             BufferGL *bufferGL = GetImplAs<BufferGL>(uniformBuffer.get());
895 
896             if (uniformBuffer.getSize() == 0)
897             {
898                 bindBufferBase(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID());
899             }
900             else
901             {
902                 bindBufferRange(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID(),
903                                 uniformBuffer.getOffset(), uniformBuffer.getSize());
904             }
905         }
906     }
907 }
908 
updateProgramAtomicCounterBufferBindings(const gl::Context * context)909 void StateManagerGL::updateProgramAtomicCounterBufferBindings(const gl::Context *context)
910 {
911     const gl::State &glState   = context->getState();
912     const gl::Program *program = glState.getProgram();
913 
914     for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
915     {
916         GLuint binding     = atomicCounterBuffer.binding;
917         const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
918 
919         if (buffer.get() != nullptr)
920         {
921             BufferGL *bufferGL = GetImplAs<BufferGL>(buffer.get());
922 
923             if (buffer.getSize() == 0)
924             {
925                 bindBufferBase(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID());
926             }
927             else
928             {
929                 bindBufferRange(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID(),
930                                 buffer.getOffset(), buffer.getSize());
931             }
932         }
933     }
934 }
935 
updateProgramImageBindings(const gl::Context * context)936 void StateManagerGL::updateProgramImageBindings(const gl::Context *context)
937 {
938     const gl::State &glState                = context->getState();
939     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
940     const gl::Program *program              = glState.getProgram();
941 
942     // It is possible there is no active program during a path operation.
943     if (!executable || !program)
944         return;
945 
946     ASSERT(context->getClientVersion() >= gl::ES_3_1 || program->getImageBindings().empty());
947     for (size_t imageUnitIndex : executable->getActiveImagesMask())
948     {
949         const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
950         const TextureGL *textureGL     = SafeGetImplAs<TextureGL>(imageUnit.texture.get());
951         if (textureGL)
952         {
953             bindImageTexture(imageUnitIndex, textureGL->getTextureID(), imageUnit.level,
954                              imageUnit.layered, imageUnit.layer, imageUnit.access,
955                              imageUnit.format);
956         }
957         else
958         {
959             bindImageTexture(imageUnitIndex, 0, imageUnit.level, imageUnit.layered, imageUnit.layer,
960                              imageUnit.access, imageUnit.format);
961         }
962     }
963 }
964 
setAttributeCurrentData(size_t index,const gl::VertexAttribCurrentValueData & data)965 void StateManagerGL::setAttributeCurrentData(size_t index,
966                                              const gl::VertexAttribCurrentValueData &data)
967 {
968     if (mVertexAttribCurrentValues[index] != data)
969     {
970         mVertexAttribCurrentValues[index] = data;
971         switch (mVertexAttribCurrentValues[index].Type)
972         {
973             case gl::VertexAttribType::Float:
974                 mFunctions->vertexAttrib4fv(static_cast<GLuint>(index),
975                                             mVertexAttribCurrentValues[index].Values.FloatValues);
976                 break;
977             case gl::VertexAttribType::Int:
978                 mFunctions->vertexAttribI4iv(static_cast<GLuint>(index),
979                                              mVertexAttribCurrentValues[index].Values.IntValues);
980                 break;
981             case gl::VertexAttribType::UnsignedInt:
982                 mFunctions->vertexAttribI4uiv(
983                     static_cast<GLuint>(index),
984                     mVertexAttribCurrentValues[index].Values.UnsignedIntValues);
985                 break;
986             default:
987                 UNREACHABLE();
988         }
989 
990         mLocalDirtyBits.set(gl::State::DIRTY_BIT_CURRENT_VALUES);
991         mLocalDirtyCurrentValues.set(index);
992     }
993 }
994 
setScissorTestEnabled(bool enabled)995 void StateManagerGL::setScissorTestEnabled(bool enabled)
996 {
997     if (mScissorTestEnabled != enabled)
998     {
999         mScissorTestEnabled = enabled;
1000         if (mScissorTestEnabled)
1001         {
1002             mFunctions->enable(GL_SCISSOR_TEST);
1003         }
1004         else
1005         {
1006             mFunctions->disable(GL_SCISSOR_TEST);
1007         }
1008 
1009         mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
1010     }
1011 }
1012 
setScissor(const gl::Rectangle & scissor)1013 void StateManagerGL::setScissor(const gl::Rectangle &scissor)
1014 {
1015     if (scissor != mScissor)
1016     {
1017         mScissor = scissor;
1018         mFunctions->scissor(mScissor.x, mScissor.y, mScissor.width, mScissor.height);
1019 
1020         mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR);
1021     }
1022 }
1023 
setViewport(const gl::Rectangle & viewport)1024 void StateManagerGL::setViewport(const gl::Rectangle &viewport)
1025 {
1026     if (viewport != mViewport)
1027     {
1028         mViewport = viewport;
1029         mFunctions->viewport(mViewport.x, mViewport.y, mViewport.width, mViewport.height);
1030 
1031         mLocalDirtyBits.set(gl::State::DIRTY_BIT_VIEWPORT);
1032     }
1033 }
1034 
setDepthRange(float near,float far)1035 void StateManagerGL::setDepthRange(float near, float far)
1036 {
1037     mNear = near;
1038     mFar  = far;
1039 
1040     // The glDepthRangef function isn't available until OpenGL 4.1.  Prefer it when it is
1041     // available because OpenGL ES only works in floats.
1042     if (mFunctions->depthRangef)
1043     {
1044         mFunctions->depthRangef(mNear, mFar);
1045     }
1046     else
1047     {
1048         ASSERT(mFunctions->depthRange);
1049         mFunctions->depthRange(mNear, mFar);
1050     }
1051 
1052     mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_RANGE);
1053 }
1054 
setBlendEnabled(bool enabled)1055 void StateManagerGL::setBlendEnabled(bool enabled)
1056 {
1057     const gl::DrawBufferMask mask =
1058         enabled ? mBlendStateExt.mMaxEnabledMask : gl::DrawBufferMask::Zero();
1059     if (mBlendStateExt.mEnabledMask == mask)
1060     {
1061         return;
1062     }
1063 
1064     if (enabled)
1065     {
1066         mFunctions->enable(GL_BLEND);
1067     }
1068     else
1069     {
1070         mFunctions->disable(GL_BLEND);
1071     }
1072 
1073     mBlendStateExt.setEnabled(enabled);
1074     mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
1075 }
1076 
setBlendEnabledIndexed(const gl::DrawBufferMask enabledMask)1077 void StateManagerGL::setBlendEnabledIndexed(const gl::DrawBufferMask enabledMask)
1078 {
1079     if (mBlendStateExt.mEnabledMask == enabledMask)
1080     {
1081         return;
1082     }
1083 
1084     // Get DrawBufferMask of buffers with different blend enable state
1085     gl::DrawBufferMask diffMask = mBlendStateExt.mEnabledMask ^ enabledMask;
1086     const size_t diffCount      = diffMask.count();
1087 
1088     // Check if enabling or disabling blending for all buffers reduces the number of subsequent
1089     // indexed commands. Implicitly handles the case when the new blend enable state is the same for
1090     // all buffers.
1091     if (diffCount > 1)
1092     {
1093         // The number of indexed blend enable commands in case a mass disable is used.
1094         const size_t enabledCount = enabledMask.count();
1095 
1096         // The mask and the number of indexed blend disable commands in case a mass enable is used.
1097         const gl::DrawBufferMask disabledMask = enabledMask ^ mBlendStateExt.mMaxEnabledMask;
1098         const size_t disabledCount            = disabledMask.count();
1099 
1100         if (enabledCount < diffCount && enabledCount <= disabledCount)
1101         {
1102             diffMask = enabledMask;
1103             mFunctions->disable(GL_BLEND);
1104         }
1105         else if (disabledCount < diffCount && disabledCount <= enabledCount)
1106         {
1107             diffMask = disabledMask;
1108             mFunctions->enable(GL_BLEND);
1109         }
1110     }
1111 
1112     for (size_t drawBufferIndex : diffMask)
1113     {
1114         if (enabledMask.test(drawBufferIndex))
1115         {
1116             mFunctions->enablei(GL_BLEND, static_cast<GLuint>(drawBufferIndex));
1117         }
1118         else
1119         {
1120             mFunctions->disablei(GL_BLEND, static_cast<GLuint>(drawBufferIndex));
1121         }
1122     }
1123 
1124     mBlendStateExt.mEnabledMask = enabledMask;
1125     mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
1126 }
1127 
setBlendColor(const gl::ColorF & blendColor)1128 void StateManagerGL::setBlendColor(const gl::ColorF &blendColor)
1129 {
1130     if (mBlendColor != blendColor)
1131     {
1132         mBlendColor = blendColor;
1133         mFunctions->blendColor(mBlendColor.red, mBlendColor.green, mBlendColor.blue,
1134                                mBlendColor.alpha);
1135 
1136         mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_COLOR);
1137     }
1138 }
1139 
setBlendFuncs(const gl::BlendStateExt & blendStateExt)1140 void StateManagerGL::setBlendFuncs(const gl::BlendStateExt &blendStateExt)
1141 {
1142     if (mBlendStateExt.mSrcColor == blendStateExt.mSrcColor &&
1143         mBlendStateExt.mDstColor == blendStateExt.mDstColor &&
1144         mBlendStateExt.mSrcAlpha == blendStateExt.mSrcAlpha &&
1145         mBlendStateExt.mDstAlpha == blendStateExt.mDstAlpha)
1146     {
1147         return;
1148     }
1149 
1150     if (!mIndependentBlendStates)
1151     {
1152         mFunctions->blendFuncSeparate(
1153             blendStateExt.getSrcColorIndexed(0), blendStateExt.getDstColorIndexed(0),
1154             blendStateExt.getSrcAlphaIndexed(0), blendStateExt.getDstAlphaIndexed(0));
1155     }
1156     else
1157     {
1158         // Get DrawBufferMask of buffers with different blend factors
1159         gl::DrawBufferMask diffMask =
1160             mBlendStateExt.compareFactors(blendStateExt.mSrcColor, blendStateExt.mDstColor,
1161                                           blendStateExt.mSrcAlpha, blendStateExt.mDstAlpha);
1162         size_t diffCount = diffMask.count();
1163 
1164         // Check if setting all buffers to the same value reduces the number of subsequent indexed
1165         // commands. Implicitly handles the case when the new blend function state is the same for
1166         // all buffers.
1167         if (diffCount > 1)
1168         {
1169             bool found                                            = false;
1170             gl::BlendStateExt::FactorStorage::Type commonSrcColor = 0;
1171             gl::BlendStateExt::FactorStorage::Type commonDstColor = 0;
1172             gl::BlendStateExt::FactorStorage::Type commonSrcAlpha = 0;
1173             gl::BlendStateExt::FactorStorage::Type commonDstAlpha = 0;
1174             for (size_t i = 0; i < mBlendStateExt.mMaxDrawBuffers - 1; i++)
1175             {
1176                 const gl::BlendStateExt::FactorStorage::Type tempCommonSrcColor =
1177                     blendStateExt.expandSrcColorIndexed(i);
1178                 const gl::BlendStateExt::FactorStorage::Type tempCommonDstColor =
1179                     blendStateExt.expandDstColorIndexed(i);
1180                 const gl::BlendStateExt::FactorStorage::Type tempCommonSrcAlpha =
1181                     blendStateExt.expandSrcAlphaIndexed(i);
1182                 const gl::BlendStateExt::FactorStorage::Type tempCommonDstAlpha =
1183                     blendStateExt.expandDstAlphaIndexed(i);
1184 
1185                 const gl::DrawBufferMask tempDiffMask = blendStateExt.compareFactors(
1186                     tempCommonSrcColor, tempCommonDstColor, tempCommonSrcAlpha, tempCommonDstAlpha);
1187 
1188                 const size_t tempDiffCount = tempDiffMask.count();
1189                 if (tempDiffCount < diffCount)
1190                 {
1191                     found          = true;
1192                     diffMask       = tempDiffMask;
1193                     diffCount      = tempDiffCount;
1194                     commonSrcColor = tempCommonSrcColor;
1195                     commonDstColor = tempCommonDstColor;
1196                     commonSrcAlpha = tempCommonSrcAlpha;
1197                     commonDstAlpha = tempCommonDstAlpha;
1198                     if (tempDiffCount == 0)
1199                     {
1200                         break;  // the blend factors are the same for all buffers
1201                     }
1202                 }
1203             }
1204             if (found)
1205             {
1206                 mFunctions->blendFuncSeparate(
1207                     ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonSrcColor)),
1208                     ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonDstColor)),
1209                     ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonSrcAlpha)),
1210                     ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonDstAlpha)));
1211             }
1212         }
1213 
1214         for (size_t drawBufferIndex : diffMask)
1215         {
1216             mFunctions->blendFuncSeparatei(static_cast<GLuint>(drawBufferIndex),
1217                                            blendStateExt.getSrcColorIndexed(drawBufferIndex),
1218                                            blendStateExt.getDstColorIndexed(drawBufferIndex),
1219                                            blendStateExt.getSrcAlphaIndexed(drawBufferIndex),
1220                                            blendStateExt.getDstAlphaIndexed(drawBufferIndex));
1221         }
1222     }
1223     mBlendStateExt.mSrcColor = blendStateExt.mSrcColor;
1224     mBlendStateExt.mDstColor = blendStateExt.mDstColor;
1225     mBlendStateExt.mSrcAlpha = blendStateExt.mSrcAlpha;
1226     mBlendStateExt.mDstAlpha = blendStateExt.mDstAlpha;
1227     mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);
1228 }
1229 
setBlendEquations(const gl::BlendStateExt & blendStateExt)1230 void StateManagerGL::setBlendEquations(const gl::BlendStateExt &blendStateExt)
1231 {
1232     if (mBlendStateExt.mEquationColor == blendStateExt.mEquationColor &&
1233         mBlendStateExt.mEquationAlpha == blendStateExt.mEquationAlpha)
1234     {
1235         return;
1236     }
1237 
1238     if (!mIndependentBlendStates)
1239     {
1240         mFunctions->blendEquationSeparate(blendStateExt.getEquationColorIndexed(0),
1241                                           blendStateExt.getEquationAlphaIndexed(0));
1242     }
1243     else
1244     {
1245         // Get DrawBufferMask of buffers with different blend equations
1246         gl::DrawBufferMask diffMask = mBlendStateExt.compareEquations(blendStateExt.mEquationColor,
1247                                                                       blendStateExt.mEquationAlpha);
1248         size_t diffCount            = diffMask.count();
1249 
1250         // Check if setting all buffers to the same value reduces the number of subsequent indexed
1251         // commands. Implicitly handles the case when the new blend equation state is the same for
1252         // all buffers.
1253         if (diffCount > 1)
1254         {
1255             bool found                                                   = false;
1256             gl::BlendStateExt::EquationStorage::Type commonEquationColor = 0;
1257             gl::BlendStateExt::EquationStorage::Type commonEquationAlpha = 0;
1258             for (size_t i = 0; i < mBlendStateExt.mMaxDrawBuffers - 1; i++)
1259             {
1260                 const gl::BlendStateExt::EquationStorage::Type tempCommonEquationColor =
1261                     blendStateExt.expandEquationColorIndexed(i);
1262                 const gl::BlendStateExt::EquationStorage::Type tempCommonEquationAlpha =
1263                     blendStateExt.expandEquationAlphaIndexed(i);
1264 
1265                 const gl::DrawBufferMask tempDiffMask = blendStateExt.compareEquations(
1266                     tempCommonEquationColor, tempCommonEquationAlpha);
1267 
1268                 const size_t tempDiffCount = tempDiffMask.count();
1269                 if (tempDiffCount < diffCount)
1270                 {
1271                     found               = true;
1272                     diffMask            = tempDiffMask;
1273                     diffCount           = tempDiffCount;
1274                     commonEquationColor = tempCommonEquationColor;
1275                     commonEquationAlpha = tempCommonEquationAlpha;
1276                     if (tempDiffCount == 0)
1277                     {
1278                         break;  // the new blend equations are the same for all buffers
1279                     }
1280                 }
1281             }
1282             if (found)
1283             {
1284                 mFunctions->blendEquationSeparate(
1285                     ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
1286                         0, commonEquationColor)),
1287                     ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
1288                         0, commonEquationAlpha)));
1289             }
1290         }
1291 
1292         for (size_t drawBufferIndex : diffMask)
1293         {
1294             mFunctions->blendEquationSeparatei(
1295                 static_cast<GLuint>(drawBufferIndex),
1296                 blendStateExt.getEquationColorIndexed(drawBufferIndex),
1297                 blendStateExt.getEquationAlphaIndexed(drawBufferIndex));
1298         }
1299     }
1300     mBlendStateExt.mEquationColor = blendStateExt.mEquationColor;
1301     mBlendStateExt.mEquationAlpha = blendStateExt.mEquationAlpha;
1302     mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
1303 }
1304 
setColorMask(bool red,bool green,bool blue,bool alpha)1305 void StateManagerGL::setColorMask(bool red, bool green, bool blue, bool alpha)
1306 {
1307     const gl::BlendStateExt::ColorMaskStorage::Type mask =
1308         mBlendStateExt.expandColorMaskValue(red, green, blue, alpha);
1309     if (mBlendStateExt.mColorMask != mask)
1310     {
1311         mFunctions->colorMask(red, green, blue, alpha);
1312         mBlendStateExt.mColorMask = mask;
1313         mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
1314     }
1315 }
1316 
setSampleAlphaToCoverageEnabled(bool enabled)1317 void StateManagerGL::setSampleAlphaToCoverageEnabled(bool enabled)
1318 {
1319     if (mSampleAlphaToCoverageEnabled != enabled)
1320     {
1321         mSampleAlphaToCoverageEnabled = enabled;
1322         if (mSampleAlphaToCoverageEnabled)
1323         {
1324             mFunctions->enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
1325         }
1326         else
1327         {
1328             mFunctions->disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
1329         }
1330 
1331         mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
1332     }
1333 }
1334 
setSampleCoverageEnabled(bool enabled)1335 void StateManagerGL::setSampleCoverageEnabled(bool enabled)
1336 {
1337     if (mSampleCoverageEnabled != enabled)
1338     {
1339         mSampleCoverageEnabled = enabled;
1340         if (mSampleCoverageEnabled)
1341         {
1342             mFunctions->enable(GL_SAMPLE_COVERAGE);
1343         }
1344         else
1345         {
1346             mFunctions->disable(GL_SAMPLE_COVERAGE);
1347         }
1348 
1349         mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
1350     }
1351 }
1352 
setSampleCoverage(float value,bool invert)1353 void StateManagerGL::setSampleCoverage(float value, bool invert)
1354 {
1355     if (mSampleCoverageValue != value || mSampleCoverageInvert != invert)
1356     {
1357         mSampleCoverageValue  = value;
1358         mSampleCoverageInvert = invert;
1359         mFunctions->sampleCoverage(mSampleCoverageValue, mSampleCoverageInvert);
1360 
1361         mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE);
1362     }
1363 }
1364 
setSampleMaskEnabled(bool enabled)1365 void StateManagerGL::setSampleMaskEnabled(bool enabled)
1366 {
1367     if (mSampleMaskEnabled != enabled)
1368     {
1369         mSampleMaskEnabled = enabled;
1370         if (mSampleMaskEnabled)
1371         {
1372             mFunctions->enable(GL_SAMPLE_MASK);
1373         }
1374         else
1375         {
1376             mFunctions->disable(GL_SAMPLE_MASK);
1377         }
1378 
1379         mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_MASK_ENABLED);
1380     }
1381 }
1382 
setSampleMaski(GLuint maskNumber,GLbitfield mask)1383 void StateManagerGL::setSampleMaski(GLuint maskNumber, GLbitfield mask)
1384 {
1385     ASSERT(maskNumber < mSampleMaskValues.size());
1386     if (mSampleMaskValues[maskNumber] != mask)
1387     {
1388         mSampleMaskValues[maskNumber] = mask;
1389         mFunctions->sampleMaski(maskNumber, mask);
1390 
1391         mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_MASK);
1392     }
1393 }
1394 
1395 // Depth and stencil redundant state changes are guarded in the
1396 // frontend so for related cases here just set the dirty bit
1397 // and update backend states.
setDepthTestEnabled(bool enabled)1398 void StateManagerGL::setDepthTestEnabled(bool enabled)
1399 {
1400     mDepthTestEnabled = enabled;
1401     if (mDepthTestEnabled)
1402     {
1403         mFunctions->enable(GL_DEPTH_TEST);
1404     }
1405     else
1406     {
1407         mFunctions->disable(GL_DEPTH_TEST);
1408     }
1409 
1410     mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED);
1411 }
1412 
setDepthFunc(GLenum depthFunc)1413 void StateManagerGL::setDepthFunc(GLenum depthFunc)
1414 {
1415     mDepthFunc = depthFunc;
1416     mFunctions->depthFunc(mDepthFunc);
1417 
1418     mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_FUNC);
1419 }
1420 
setDepthMask(bool mask)1421 void StateManagerGL::setDepthMask(bool mask)
1422 {
1423     mDepthMask = mask;
1424     mFunctions->depthMask(mDepthMask);
1425 
1426     mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_MASK);
1427 }
1428 
setStencilTestEnabled(bool enabled)1429 void StateManagerGL::setStencilTestEnabled(bool enabled)
1430 {
1431     mStencilTestEnabled = enabled;
1432     if (mStencilTestEnabled)
1433     {
1434         mFunctions->enable(GL_STENCIL_TEST);
1435     }
1436     else
1437     {
1438         mFunctions->disable(GL_STENCIL_TEST);
1439     }
1440 
1441     mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED);
1442 }
1443 
setStencilFrontWritemask(GLuint mask)1444 void StateManagerGL::setStencilFrontWritemask(GLuint mask)
1445 {
1446     mStencilFrontWritemask = mask;
1447     mFunctions->stencilMaskSeparate(GL_FRONT, mStencilFrontWritemask);
1448 
1449     mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
1450 }
1451 
setStencilBackWritemask(GLuint mask)1452 void StateManagerGL::setStencilBackWritemask(GLuint mask)
1453 {
1454     mStencilBackWritemask = mask;
1455     mFunctions->stencilMaskSeparate(GL_BACK, mStencilBackWritemask);
1456 
1457     mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
1458 }
1459 
setStencilFrontFuncs(GLenum func,GLint ref,GLuint mask)1460 void StateManagerGL::setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask)
1461 {
1462     mStencilFrontFunc      = func;
1463     mStencilFrontRef       = ref;
1464     mStencilFrontValueMask = mask;
1465     mFunctions->stencilFuncSeparate(GL_FRONT, mStencilFrontFunc, mStencilFrontRef,
1466                                     mStencilFrontValueMask);
1467 
1468     mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT);
1469 }
1470 
setStencilBackFuncs(GLenum func,GLint ref,GLuint mask)1471 void StateManagerGL::setStencilBackFuncs(GLenum func, GLint ref, GLuint mask)
1472 {
1473     mStencilBackFunc      = func;
1474     mStencilBackRef       = ref;
1475     mStencilBackValueMask = mask;
1476     mFunctions->stencilFuncSeparate(GL_BACK, mStencilBackFunc, mStencilBackRef,
1477                                     mStencilBackValueMask);
1478 
1479     mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK);
1480 }
1481 
setStencilFrontOps(GLenum sfail,GLenum dpfail,GLenum dppass)1482 void StateManagerGL::setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass)
1483 {
1484     mStencilFrontStencilFailOp          = sfail;
1485     mStencilFrontStencilPassDepthFailOp = dpfail;
1486     mStencilFrontStencilPassDepthPassOp = dppass;
1487     mFunctions->stencilOpSeparate(GL_FRONT, mStencilFrontStencilFailOp,
1488                                   mStencilFrontStencilPassDepthFailOp,
1489                                   mStencilFrontStencilPassDepthPassOp);
1490 
1491     mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_FRONT);
1492 }
1493 
setStencilBackOps(GLenum sfail,GLenum dpfail,GLenum dppass)1494 void StateManagerGL::setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass)
1495 {
1496     mStencilBackStencilFailOp          = sfail;
1497     mStencilBackStencilPassDepthFailOp = dpfail;
1498     mStencilBackStencilPassDepthPassOp = dppass;
1499     mFunctions->stencilOpSeparate(GL_BACK, mStencilBackStencilFailOp,
1500                                   mStencilBackStencilPassDepthFailOp,
1501                                   mStencilBackStencilPassDepthPassOp);
1502 
1503     mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_BACK);
1504 }
1505 
setCullFaceEnabled(bool enabled)1506 void StateManagerGL::setCullFaceEnabled(bool enabled)
1507 {
1508     if (mCullFaceEnabled != enabled)
1509     {
1510         mCullFaceEnabled = enabled;
1511         if (mCullFaceEnabled)
1512         {
1513             mFunctions->enable(GL_CULL_FACE);
1514         }
1515         else
1516         {
1517             mFunctions->disable(GL_CULL_FACE);
1518         }
1519 
1520         mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE_ENABLED);
1521     }
1522 }
1523 
setCullFace(gl::CullFaceMode cullFace)1524 void StateManagerGL::setCullFace(gl::CullFaceMode cullFace)
1525 {
1526     if (mCullFace != cullFace)
1527     {
1528         mCullFace = cullFace;
1529         mFunctions->cullFace(ToGLenum(mCullFace));
1530 
1531         mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE);
1532     }
1533 }
1534 
setFrontFace(GLenum frontFace)1535 void StateManagerGL::setFrontFace(GLenum frontFace)
1536 {
1537     if (mFrontFace != frontFace)
1538     {
1539         mFrontFace = frontFace;
1540         mFunctions->frontFace(mFrontFace);
1541 
1542         mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRONT_FACE);
1543     }
1544 }
1545 
setPolygonOffsetFillEnabled(bool enabled)1546 void StateManagerGL::setPolygonOffsetFillEnabled(bool enabled)
1547 {
1548     if (mPolygonOffsetFillEnabled != enabled)
1549     {
1550         mPolygonOffsetFillEnabled = enabled;
1551         if (mPolygonOffsetFillEnabled)
1552         {
1553             mFunctions->enable(GL_POLYGON_OFFSET_FILL);
1554         }
1555         else
1556         {
1557             mFunctions->disable(GL_POLYGON_OFFSET_FILL);
1558         }
1559 
1560         mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
1561     }
1562 }
1563 
setPolygonOffset(float factor,float units)1564 void StateManagerGL::setPolygonOffset(float factor, float units)
1565 {
1566     if (mPolygonOffsetFactor != factor || mPolygonOffsetUnits != units)
1567     {
1568         mPolygonOffsetFactor = factor;
1569         mPolygonOffsetUnits  = units;
1570         mFunctions->polygonOffset(mPolygonOffsetFactor, mPolygonOffsetUnits);
1571 
1572         mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET);
1573     }
1574 }
1575 
setRasterizerDiscardEnabled(bool enabled)1576 void StateManagerGL::setRasterizerDiscardEnabled(bool enabled)
1577 {
1578     if (mRasterizerDiscardEnabled != enabled)
1579     {
1580         mRasterizerDiscardEnabled = enabled;
1581         if (mRasterizerDiscardEnabled)
1582         {
1583             mFunctions->enable(GL_RASTERIZER_DISCARD);
1584         }
1585         else
1586         {
1587             mFunctions->disable(GL_RASTERIZER_DISCARD);
1588         }
1589 
1590         mLocalDirtyBits.set(gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
1591     }
1592 }
1593 
setLineWidth(float width)1594 void StateManagerGL::setLineWidth(float width)
1595 {
1596     if (mLineWidth != width)
1597     {
1598         mLineWidth = width;
1599         mFunctions->lineWidth(mLineWidth);
1600 
1601         mLocalDirtyBits.set(gl::State::DIRTY_BIT_LINE_WIDTH);
1602     }
1603 }
1604 
setPrimitiveRestartEnabled(const gl::Context * context,bool enabled)1605 angle::Result StateManagerGL::setPrimitiveRestartEnabled(const gl::Context *context, bool enabled)
1606 {
1607     if (mPrimitiveRestartEnabled != enabled)
1608     {
1609         GLenum cap = mFeatures.emulatePrimitiveRestartFixedIndex.enabled
1610                          ? GL_PRIMITIVE_RESTART
1611                          : GL_PRIMITIVE_RESTART_FIXED_INDEX;
1612 
1613         if (enabled)
1614         {
1615             ANGLE_GL_TRY(context, mFunctions->enable(cap));
1616         }
1617         else
1618         {
1619             ANGLE_GL_TRY(context, mFunctions->disable(cap));
1620         }
1621         mPrimitiveRestartEnabled = enabled;
1622 
1623         mLocalDirtyBits.set(gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
1624     }
1625 
1626     return angle::Result::Continue;
1627 }
1628 
setPrimitiveRestartIndex(const gl::Context * context,GLuint index)1629 angle::Result StateManagerGL::setPrimitiveRestartIndex(const gl::Context *context, GLuint index)
1630 {
1631     if (mPrimitiveRestartIndex != index)
1632     {
1633         ANGLE_GL_TRY(context, mFunctions->primitiveRestartIndex(index));
1634         mPrimitiveRestartIndex = index;
1635 
1636         // No dirty bit for this state, it is not exposed to the frontend.
1637     }
1638 
1639     return angle::Result::Continue;
1640 }
1641 
setClearDepth(float clearDepth)1642 void StateManagerGL::setClearDepth(float clearDepth)
1643 {
1644     if (mClearDepth != clearDepth)
1645     {
1646         mClearDepth = clearDepth;
1647 
1648         // The glClearDepthf function isn't available until OpenGL 4.1.  Prefer it when it is
1649         // available because OpenGL ES only works in floats.
1650         if (mFunctions->clearDepthf)
1651         {
1652             mFunctions->clearDepthf(mClearDepth);
1653         }
1654         else
1655         {
1656             ASSERT(mFunctions->clearDepth);
1657             mFunctions->clearDepth(mClearDepth);
1658         }
1659 
1660         mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_DEPTH);
1661     }
1662 }
1663 
setClearColor(const gl::ColorF & clearColor)1664 void StateManagerGL::setClearColor(const gl::ColorF &clearColor)
1665 {
1666     gl::ColorF modifiedClearColor = clearColor;
1667     if (mFeatures.clearToZeroOrOneBroken.enabled &&
1668         (clearColor.red == 1.0f || clearColor.red == 0.0f) &&
1669         (clearColor.green == 1.0f || clearColor.green == 0.0f) &&
1670         (clearColor.blue == 1.0f || clearColor.blue == 0.0f) &&
1671         (clearColor.alpha == 1.0f || clearColor.alpha == 0.0f))
1672     {
1673         if (clearColor.alpha == 1.0f)
1674         {
1675             modifiedClearColor.alpha = 2.0f;
1676         }
1677         else
1678         {
1679             modifiedClearColor.alpha = -1.0f;
1680         }
1681     }
1682 
1683     if (mClearColor != modifiedClearColor)
1684     {
1685         mClearColor = modifiedClearColor;
1686         mFunctions->clearColor(mClearColor.red, mClearColor.green, mClearColor.blue,
1687                                mClearColor.alpha);
1688 
1689         mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_COLOR);
1690     }
1691 }
1692 
setClearStencil(GLint clearStencil)1693 void StateManagerGL::setClearStencil(GLint clearStencil)
1694 {
1695     if (mClearStencil != clearStencil)
1696     {
1697         mClearStencil = clearStencil;
1698         mFunctions->clearStencil(mClearStencil);
1699 
1700         mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_STENCIL);
1701     }
1702 }
1703 
syncState(const gl::Context * context,const gl::State::DirtyBits & glDirtyBits,const gl::State::DirtyBits & bitMask)1704 angle::Result StateManagerGL::syncState(const gl::Context *context,
1705                                         const gl::State::DirtyBits &glDirtyBits,
1706                                         const gl::State::DirtyBits &bitMask)
1707 {
1708     const gl::State &state = context->getState();
1709 
1710     const gl::State::DirtyBits glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits) & bitMask;
1711     if (!glAndLocalDirtyBits.any())
1712     {
1713         return angle::Result::Continue;
1714     }
1715 
1716     // TODO(jmadill): Investigate only syncing vertex state for active attributes
1717     for (auto iter = glAndLocalDirtyBits.begin(), endIter = glAndLocalDirtyBits.end();
1718          iter != endIter; ++iter)
1719     {
1720         switch (*iter)
1721         {
1722             case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
1723                 setScissorTestEnabled(state.isScissorTestEnabled());
1724                 break;
1725             case gl::State::DIRTY_BIT_SCISSOR:
1726             {
1727                 const gl::Rectangle &scissor = state.getScissor();
1728                 setScissor(scissor);
1729             }
1730             break;
1731             case gl::State::DIRTY_BIT_VIEWPORT:
1732             {
1733                 const gl::Rectangle &viewport = state.getViewport();
1734                 setViewport(viewport);
1735             }
1736             break;
1737             case gl::State::DIRTY_BIT_DEPTH_RANGE:
1738                 setDepthRange(state.getNearPlane(), state.getFarPlane());
1739                 break;
1740             case gl::State::DIRTY_BIT_BLEND_ENABLED:
1741                 if (mIndependentBlendStates)
1742                 {
1743                     setBlendEnabledIndexed(state.getBlendEnabledDrawBufferMask());
1744                 }
1745                 else
1746                 {
1747                     setBlendEnabled(state.isBlendEnabled());
1748                 }
1749                 break;
1750             case gl::State::DIRTY_BIT_BLEND_COLOR:
1751                 setBlendColor(state.getBlendColor());
1752                 break;
1753             case gl::State::DIRTY_BIT_BLEND_FUNCS:
1754             {
1755                 setBlendFuncs(state.getBlendStateExt());
1756                 break;
1757             }
1758             case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
1759             {
1760                 setBlendEquations(state.getBlendStateExt());
1761                 break;
1762             }
1763             case gl::State::DIRTY_BIT_COLOR_MASK:
1764             {
1765                 const gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
1766                 const FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
1767                 const bool disableAlphaWrite =
1768                     framebufferGL->hasEmulatedAlphaChannelTextureAttachment();
1769 
1770                 setColorMaskForFramebuffer(state.getBlendStateExt(), disableAlphaWrite);
1771                 break;
1772             }
1773             case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
1774                 setSampleAlphaToCoverageEnabled(state.isSampleAlphaToCoverageEnabled());
1775                 break;
1776             case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
1777                 setSampleCoverageEnabled(state.isSampleCoverageEnabled());
1778                 break;
1779             case gl::State::DIRTY_BIT_SAMPLE_COVERAGE:
1780                 setSampleCoverage(state.getSampleCoverageValue(), state.getSampleCoverageInvert());
1781                 break;
1782             case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
1783                 setDepthTestEnabled(state.isDepthTestEnabled());
1784                 break;
1785             case gl::State::DIRTY_BIT_DEPTH_FUNC:
1786                 setDepthFunc(state.getDepthStencilState().depthFunc);
1787                 break;
1788             case gl::State::DIRTY_BIT_DEPTH_MASK:
1789                 setDepthMask(state.getDepthStencilState().depthMask);
1790                 break;
1791             case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
1792                 setStencilTestEnabled(state.isStencilTestEnabled());
1793                 break;
1794             case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
1795             {
1796                 const auto &depthStencilState = state.getDepthStencilState();
1797                 setStencilFrontFuncs(depthStencilState.stencilFunc, state.getStencilRef(),
1798                                      depthStencilState.stencilMask);
1799                 break;
1800             }
1801             case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
1802             {
1803                 const auto &depthStencilState = state.getDepthStencilState();
1804                 setStencilBackFuncs(depthStencilState.stencilBackFunc, state.getStencilBackRef(),
1805                                     depthStencilState.stencilBackMask);
1806                 break;
1807             }
1808             case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
1809             {
1810                 const auto &depthStencilState = state.getDepthStencilState();
1811                 setStencilFrontOps(depthStencilState.stencilFail,
1812                                    depthStencilState.stencilPassDepthFail,
1813                                    depthStencilState.stencilPassDepthPass);
1814                 break;
1815             }
1816             case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
1817             {
1818                 const auto &depthStencilState = state.getDepthStencilState();
1819                 setStencilBackOps(depthStencilState.stencilBackFail,
1820                                   depthStencilState.stencilBackPassDepthFail,
1821                                   depthStencilState.stencilBackPassDepthPass);
1822                 break;
1823             }
1824             case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
1825                 setStencilFrontWritemask(state.getDepthStencilState().stencilWritemask);
1826                 break;
1827             case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
1828                 setStencilBackWritemask(state.getDepthStencilState().stencilBackWritemask);
1829                 break;
1830             case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
1831                 setCullFaceEnabled(state.isCullFaceEnabled());
1832                 break;
1833             case gl::State::DIRTY_BIT_CULL_FACE:
1834                 setCullFace(state.getRasterizerState().cullMode);
1835                 break;
1836             case gl::State::DIRTY_BIT_FRONT_FACE:
1837                 setFrontFace(state.getRasterizerState().frontFace);
1838                 break;
1839             case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
1840                 setPolygonOffsetFillEnabled(state.isPolygonOffsetFillEnabled());
1841                 break;
1842             case gl::State::DIRTY_BIT_POLYGON_OFFSET:
1843             {
1844                 const auto &rasterizerState = state.getRasterizerState();
1845                 setPolygonOffset(rasterizerState.polygonOffsetFactor,
1846                                  rasterizerState.polygonOffsetUnits);
1847                 break;
1848             }
1849             case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
1850                 setRasterizerDiscardEnabled(state.isRasterizerDiscardEnabled());
1851                 break;
1852             case gl::State::DIRTY_BIT_LINE_WIDTH:
1853                 setLineWidth(state.getLineWidth());
1854                 break;
1855             case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
1856                 ANGLE_TRY(setPrimitiveRestartEnabled(context, state.isPrimitiveRestartEnabled()));
1857                 break;
1858             case gl::State::DIRTY_BIT_CLEAR_COLOR:
1859                 setClearColor(state.getColorClearValue());
1860                 break;
1861             case gl::State::DIRTY_BIT_CLEAR_DEPTH:
1862                 setClearDepth(state.getDepthClearValue());
1863                 break;
1864             case gl::State::DIRTY_BIT_CLEAR_STENCIL:
1865                 setClearStencil(state.getStencilClearValue());
1866                 break;
1867             case gl::State::DIRTY_BIT_UNPACK_STATE:
1868                 setPixelUnpackState(state.getUnpackState());
1869                 break;
1870             case gl::State::DIRTY_BIT_UNPACK_BUFFER_BINDING:
1871                 setPixelUnpackBuffer(state.getTargetBuffer(gl::BufferBinding::PixelUnpack));
1872                 break;
1873             case gl::State::DIRTY_BIT_PACK_STATE:
1874                 setPixelPackState(state.getPackState());
1875                 break;
1876             case gl::State::DIRTY_BIT_PACK_BUFFER_BINDING:
1877                 setPixelPackBuffer(state.getTargetBuffer(gl::BufferBinding::PixelPack));
1878                 break;
1879             case gl::State::DIRTY_BIT_DITHER_ENABLED:
1880                 setDitherEnabled(state.isDitherEnabled());
1881                 break;
1882             case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
1883             {
1884                 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
1885 
1886                 // Necessary for an Intel TexImage workaround.
1887                 if (!framebuffer)
1888                     continue;
1889 
1890                 FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
1891                 bindFramebuffer(GL_READ_FRAMEBUFFER, framebufferGL->getFramebufferID());
1892                 break;
1893             }
1894             case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
1895             {
1896                 gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
1897 
1898                 // Necessary for an Intel TexImage workaround.
1899                 if (!framebuffer)
1900                     continue;
1901 
1902                 FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
1903                 bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferGL->getFramebufferID());
1904 
1905                 const gl::Program *program = state.getProgram();
1906                 if (program)
1907                 {
1908                     updateMultiviewBaseViewLayerIndexUniform(program, framebufferGL->getState());
1909                 }
1910 
1911                 // Changing the draw framebuffer binding sometimes requires resetting srgb blending.
1912                 if (mFunctions->standard == STANDARD_GL_DESKTOP)
1913                 {
1914                     iter.setLaterBit(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
1915                 }
1916 
1917                 // If the framebuffer is emulating RGB on top of RGBA, the color mask has to be
1918                 // updated
1919                 iter.setLaterBit(gl::State::DIRTY_BIT_COLOR_MASK);
1920                 break;
1921             }
1922             case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
1923                 // TODO(jmadill): implement this
1924                 break;
1925             case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
1926             {
1927                 const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(state.getVertexArray());
1928                 bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
1929 
1930                 propagateProgramToVAO(state.getProgram(),
1931                                       GetImplAs<VertexArrayGL>(state.getVertexArray()));
1932                 break;
1933             }
1934             case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
1935                 updateDrawIndirectBufferBinding(context);
1936                 break;
1937             case gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
1938                 updateDispatchIndirectBufferBinding(context);
1939                 break;
1940             case gl::State::DIRTY_BIT_PROGRAM_BINDING:
1941             {
1942                 gl::Program *program = state.getProgram();
1943                 if (program != nullptr)
1944                 {
1945                     useProgram(GetImplAs<ProgramGL>(program)->getProgramID());
1946                 }
1947                 break;
1948             }
1949             case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
1950             {
1951                 const gl::Program *program              = state.getProgram();
1952                 const gl::ProgramExecutable *executable = state.getProgramExecutable();
1953 
1954                 if (program && executable)
1955                 {
1956                     iter.setLaterBit(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
1957 
1958                     if (executable->getActiveImagesMask().any())
1959                     {
1960                         iter.setLaterBit(gl::State::DIRTY_BIT_IMAGE_BINDINGS);
1961                     }
1962 
1963                     if (program->getActiveShaderStorageBlockCount() > 0)
1964                     {
1965                         iter.setLaterBit(gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
1966                     }
1967 
1968                     if (program->getActiveUniformBlockCount() > 0)
1969                     {
1970                         iter.setLaterBit(gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
1971                     }
1972 
1973                     if (program->getActiveAtomicCounterBufferCount() > 0)
1974                     {
1975                         iter.setLaterBit(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
1976                     }
1977 
1978                     if (mIsMultiviewEnabled && program->usesMultiview())
1979                     {
1980                         updateMultiviewBaseViewLayerIndexUniform(
1981                             program, state.getDrawFramebuffer()->getImplementation()->getState());
1982                     }
1983                 }
1984 
1985                 if (!program ||
1986                     !program->getExecutable().hasLinkedShaderStage(gl::ShaderType::Compute))
1987                 {
1988                     propagateProgramToVAO(program,
1989                                           GetImplAs<VertexArrayGL>(state.getVertexArray()));
1990                 }
1991                 break;
1992             }
1993             case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
1994                 updateProgramTextureBindings(context);
1995                 break;
1996             case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
1997                 syncSamplersState(context);
1998                 break;
1999             case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
2000                 updateProgramImageBindings(context);
2001                 break;
2002             case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
2003                 syncTransformFeedbackState(context);
2004                 break;
2005             case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
2006                 updateProgramStorageBufferBindings(context);
2007                 break;
2008             case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
2009                 updateProgramUniformBufferBindings(context);
2010                 break;
2011             case gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
2012                 updateProgramAtomicCounterBufferBindings(context);
2013                 break;
2014             case gl::State::DIRTY_BIT_MULTISAMPLING:
2015                 setMultisamplingStateEnabled(state.isMultisamplingEnabled());
2016                 break;
2017             case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
2018                 setSampleAlphaToOneStateEnabled(state.isSampleAlphaToOneEnabled());
2019                 break;
2020             case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
2021                 setCoverageModulation(state.getCoverageModulation());
2022                 break;
2023             case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB:
2024                 setFramebufferSRGBEnabledForFramebuffer(
2025                     context, state.getFramebufferSRGB(),
2026                     GetImplAs<FramebufferGL>(state.getDrawFramebuffer()));
2027                 break;
2028             case gl::State::DIRTY_BIT_SAMPLE_MASK_ENABLED:
2029                 setSampleMaskEnabled(state.isSampleMaskEnabled());
2030                 break;
2031             case gl::State::DIRTY_BIT_SAMPLE_MASK:
2032             {
2033                 for (GLuint maskNumber = 0; maskNumber < state.getMaxSampleMaskWords();
2034                      ++maskNumber)
2035                 {
2036                     setSampleMaski(maskNumber, state.getSampleMaskWord(maskNumber));
2037                 }
2038                 break;
2039             }
2040             case gl::State::DIRTY_BIT_CURRENT_VALUES:
2041             {
2042                 gl::AttributesMask combinedMask =
2043                     (state.getAndResetDirtyCurrentValues() | mLocalDirtyCurrentValues);
2044                 mLocalDirtyCurrentValues.reset();
2045 
2046                 for (auto attribIndex : combinedMask)
2047                 {
2048                     setAttributeCurrentData(attribIndex,
2049                                             state.getVertexAttribCurrentValue(attribIndex));
2050                 }
2051                 break;
2052             }
2053             case gl::State::DIRTY_BIT_PROVOKING_VERTEX:
2054                 setProvokingVertex(ToGLenum(state.getProvokingVertex()));
2055                 break;
2056             case gl::State::DIRTY_BIT_EXTENDED:
2057                 // Handling clip distance enabled flags:
2058                 setClipDistancesEnable(state.getEnabledClipDistances());
2059                 // TODO(jmadill): handle mipmap generation hint
2060                 // TODO(jmadill): handle shader derivative hint
2061                 break;
2062             default:
2063                 UNREACHABLE();
2064                 break;
2065         }
2066     }
2067 
2068     mLocalDirtyBits &= ~(bitMask);
2069 
2070     return angle::Result::Continue;
2071 }
2072 
setFramebufferSRGBEnabled(const gl::Context * context,bool enabled)2073 void StateManagerGL::setFramebufferSRGBEnabled(const gl::Context *context, bool enabled)
2074 {
2075     if (!mFramebufferSRGBAvailable)
2076     {
2077         return;
2078     }
2079 
2080     if (mFramebufferSRGBEnabled != enabled)
2081     {
2082         mFramebufferSRGBEnabled = enabled;
2083         if (mFramebufferSRGBEnabled)
2084         {
2085             mFunctions->enable(GL_FRAMEBUFFER_SRGB);
2086         }
2087         else
2088         {
2089             mFunctions->disable(GL_FRAMEBUFFER_SRGB);
2090         }
2091         mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
2092     }
2093 }
2094 
setFramebufferSRGBEnabledForFramebuffer(const gl::Context * context,bool enabled,const FramebufferGL * framebuffer)2095 void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context,
2096                                                              bool enabled,
2097                                                              const FramebufferGL *framebuffer)
2098 {
2099     if (mFunctions->standard == STANDARD_GL_DESKTOP && framebuffer->isDefault())
2100     {
2101         // Obey the framebuffer sRGB state for blending on all framebuffers except the default
2102         // framebuffer on Desktop OpenGL.
2103         // When SRGB blending is enabled, only SRGB capable formats will use it but the default
2104         // framebuffer will always use it if it is enabled.
2105         // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
2106         setFramebufferSRGBEnabled(context, false);
2107     }
2108     else
2109     {
2110         setFramebufferSRGBEnabled(context, enabled);
2111     }
2112 }
2113 
setColorMaskForFramebuffer(const gl::BlendStateExt & blendStateExt,const bool disableAlpha)2114 void StateManagerGL::setColorMaskForFramebuffer(const gl::BlendStateExt &blendStateExt,
2115                                                 const bool disableAlpha)
2116 {
2117     bool r, g, b, a;
2118 
2119     // Given that disableAlpha can be true only on macOS backbuffers and color mask is re-synced on
2120     // bound draw framebuffer change, switch all draw buffers color masks to avoid special case
2121     // later.
2122     if (!mIndependentBlendStates || disableAlpha)
2123     {
2124         blendStateExt.getColorMaskIndexed(0, &r, &g, &b, &a);
2125         setColorMask(r, g, b, disableAlpha ? false : a);
2126         return;
2127     }
2128 
2129     // Check if the current mask already matches the new state
2130     if (mBlendStateExt.mColorMask == blendStateExt.mColorMask)
2131     {
2132         return;
2133     }
2134 
2135     // Get DrawBufferMask of buffers with different color masks
2136     gl::DrawBufferMask diffMask = mBlendStateExt.compareColorMask(blendStateExt.mColorMask);
2137     size_t diffCount            = diffMask.count();
2138 
2139     // Check if setting all buffers to the same value reduces the number of subsequent indexed
2140     // commands. Implicitly handles the case when the new mask is the same for all buffers.
2141     // For instance, let's say that previously synced mask is ccccff00 and the new state is
2142     // ffeeeeee. Instead of calling colorMaski 8 times, ANGLE can set all buffers to `e` and then
2143     // use colorMaski only twice. On the other hand, if the new state is cceeee00, a non-indexed
2144     // call will increase the total number of GL commands.
2145     if (diffCount > 1)
2146     {
2147         bool found                                                = false;
2148         gl::BlendStateExt::ColorMaskStorage::Type commonColorMask = 0;
2149         for (size_t i = 0; i < mBlendStateExt.mMaxDrawBuffers - 1; i++)
2150         {
2151             const gl::BlendStateExt::ColorMaskStorage::Type tempCommonColorMask =
2152                 blendStateExt.expandColorMaskIndexed(i);
2153             const gl::DrawBufferMask tempDiffMask =
2154                 blendStateExt.compareColorMask(tempCommonColorMask);
2155             const size_t tempDiffCount = tempDiffMask.count();
2156             if (tempDiffCount < diffCount)
2157             {
2158                 found           = true;
2159                 diffMask        = tempDiffMask;
2160                 diffCount       = tempDiffCount;
2161                 commonColorMask = tempCommonColorMask;
2162                 if (tempDiffCount == 0)
2163                 {
2164                     break;  // the new mask is the same for all buffers
2165                 }
2166             }
2167         }
2168         if (found)
2169         {
2170             gl::BlendStateExt::UnpackColorMask(commonColorMask, &r, &g, &b, &a);
2171             mFunctions->colorMask(r, g, b, a);
2172         }
2173     }
2174 
2175     for (size_t drawBufferIndex : diffMask)
2176     {
2177         blendStateExt.getColorMaskIndexed(drawBufferIndex, &r, &g, &b, &a);
2178         mFunctions->colorMaski(static_cast<GLuint>(drawBufferIndex), r, g, b, a);
2179     }
2180 
2181     mBlendStateExt.mColorMask = blendStateExt.mColorMask;
2182     mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
2183 }
2184 
setDitherEnabled(bool enabled)2185 void StateManagerGL::setDitherEnabled(bool enabled)
2186 {
2187     if (mDitherEnabled != enabled)
2188     {
2189         mDitherEnabled = enabled;
2190         if (mDitherEnabled)
2191         {
2192             mFunctions->enable(GL_DITHER);
2193         }
2194         else
2195         {
2196             mFunctions->disable(GL_DITHER);
2197         }
2198     }
2199 }
2200 
setMultisamplingStateEnabled(bool enabled)2201 void StateManagerGL::setMultisamplingStateEnabled(bool enabled)
2202 {
2203     if (mMultisamplingEnabled != enabled)
2204     {
2205         mMultisamplingEnabled = enabled;
2206         if (mMultisamplingEnabled)
2207         {
2208             mFunctions->enable(GL_MULTISAMPLE_EXT);
2209         }
2210         else
2211         {
2212             mFunctions->disable(GL_MULTISAMPLE_EXT);
2213         }
2214         mLocalDirtyBits.set(gl::State::DIRTY_BIT_MULTISAMPLING);
2215     }
2216 }
2217 
setSampleAlphaToOneStateEnabled(bool enabled)2218 void StateManagerGL::setSampleAlphaToOneStateEnabled(bool enabled)
2219 {
2220     if (mSampleAlphaToOneEnabled != enabled)
2221     {
2222         mSampleAlphaToOneEnabled = enabled;
2223         if (mSampleAlphaToOneEnabled)
2224         {
2225             mFunctions->enable(GL_SAMPLE_ALPHA_TO_ONE);
2226         }
2227         else
2228         {
2229             mFunctions->disable(GL_SAMPLE_ALPHA_TO_ONE);
2230         }
2231         mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
2232     }
2233 }
2234 
setCoverageModulation(GLenum components)2235 void StateManagerGL::setCoverageModulation(GLenum components)
2236 {
2237     if (mCoverageModulation != components)
2238     {
2239         mCoverageModulation = components;
2240         mFunctions->coverageModulationNV(components);
2241 
2242         mLocalDirtyBits.set(gl::State::DIRTY_BIT_COVERAGE_MODULATION);
2243     }
2244 }
2245 
setProvokingVertex(GLenum mode)2246 void StateManagerGL::setProvokingVertex(GLenum mode)
2247 {
2248     if (mode != mProvokingVertex)
2249     {
2250         mFunctions->provokingVertex(mode);
2251         mProvokingVertex = mode;
2252 
2253         mLocalDirtyBits.set(gl::State::DIRTY_BIT_PROVOKING_VERTEX);
2254     }
2255 }
2256 
setClipDistancesEnable(const gl::State::ClipDistanceEnableBits & enables)2257 void StateManagerGL::setClipDistancesEnable(const gl::State::ClipDistanceEnableBits &enables)
2258 {
2259     if (enables == mEnabledClipDistances)
2260     {
2261         return;
2262     }
2263     ASSERT(mMaxClipDistances <= gl::IMPLEMENTATION_MAX_CLIP_DISTANCES);
2264 
2265     gl::State::ClipDistanceEnableBits diff = enables ^ mEnabledClipDistances;
2266     for (size_t i : diff)
2267     {
2268         if (enables.test(i))
2269         {
2270             mFunctions->enable(GL_CLIP_DISTANCE0_EXT + static_cast<uint32_t>(i));
2271         }
2272         else
2273         {
2274             mFunctions->disable(GL_CLIP_DISTANCE0_EXT + static_cast<uint32_t>(i));
2275         }
2276     }
2277 
2278     mEnabledClipDistances = enables;
2279     mLocalDirtyBits.set(gl::State::DIRTY_BIT_EXTENDED);
2280 }
2281 
setTextureCubemapSeamlessEnabled(bool enabled)2282 void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
2283 {
2284     // TODO(jmadill): Also check for seamless extension.
2285     if (!mFunctions->isAtLeastGL(gl::Version(3, 2)))
2286     {
2287         return;
2288     }
2289 
2290     if (mTextureCubemapSeamlessEnabled != enabled)
2291     {
2292         mTextureCubemapSeamlessEnabled = enabled;
2293         if (mTextureCubemapSeamlessEnabled)
2294         {
2295             mFunctions->enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
2296         }
2297         else
2298         {
2299             mFunctions->disable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
2300         }
2301     }
2302 }
2303 
propagateProgramToVAO(const gl::Program * program,VertexArrayGL * vao)2304 void StateManagerGL::propagateProgramToVAO(const gl::Program *program, VertexArrayGL *vao)
2305 {
2306     if (vao == nullptr)
2307     {
2308         return;
2309     }
2310 
2311     // Number of views:
2312     if (mIsMultiviewEnabled)
2313     {
2314         int programNumViews = 1;
2315         if (program && program->usesMultiview())
2316         {
2317             programNumViews = program->getNumViews();
2318         }
2319         vao->applyNumViewsToDivisor(programNumViews);
2320     }
2321 
2322     // Attribute enabled mask:
2323     if (program)
2324     {
2325         vao->applyActiveAttribLocationsMask(
2326             program->getExecutable().getActiveAttribLocationsMask());
2327     }
2328 }
2329 
updateMultiviewBaseViewLayerIndexUniformImpl(const gl::Program * program,const gl::FramebufferState & drawFramebufferState) const2330 void StateManagerGL::updateMultiviewBaseViewLayerIndexUniformImpl(
2331     const gl::Program *program,
2332     const gl::FramebufferState &drawFramebufferState) const
2333 {
2334     ASSERT(mIsMultiviewEnabled && program && program->usesMultiview());
2335     const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
2336     if (drawFramebufferState.isMultiview())
2337     {
2338         programGL->enableLayeredRenderingPath(drawFramebufferState.getBaseViewIndex());
2339     }
2340 }
2341 
syncSamplersState(const gl::Context * context)2342 void StateManagerGL::syncSamplersState(const gl::Context *context)
2343 {
2344     const gl::SamplerBindingVector &samplers = context->getState().getSamplers();
2345 
2346     // This could be optimized by using a separate binding dirty bit per sampler.
2347     for (size_t samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex)
2348     {
2349         const gl::Sampler *sampler = samplers[samplerIndex].get();
2350         if (sampler != nullptr)
2351         {
2352             SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler);
2353             bindSampler(samplerIndex, samplerGL->getSamplerID());
2354         }
2355         else
2356         {
2357             bindSampler(samplerIndex, 0);
2358         }
2359     }
2360 }
2361 
syncTransformFeedbackState(const gl::Context * context)2362 void StateManagerGL::syncTransformFeedbackState(const gl::Context *context)
2363 {
2364     // Set the current transform feedback state
2365     gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
2366     if (transformFeedback)
2367     {
2368         TransformFeedbackGL *transformFeedbackGL =
2369             GetImplAs<TransformFeedbackGL>(transformFeedback);
2370         bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID());
2371         transformFeedbackGL->syncActiveState(context, transformFeedback->isActive(),
2372                                              transformFeedback->getPrimitiveMode());
2373         transformFeedbackGL->syncPausedState(transformFeedback->isPaused());
2374         mCurrentTransformFeedback = transformFeedbackGL;
2375     }
2376     else
2377     {
2378         bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
2379         mCurrentTransformFeedback = nullptr;
2380     }
2381 }
2382 
validateState() const2383 void StateManagerGL::validateState() const
2384 {
2385     // Current program
2386     ValidateStateHelper(mFunctions, mProgram, GL_CURRENT_PROGRAM, "mProgram", "GL_CURRENT_PROGRAM");
2387 
2388     // Buffers
2389     for (gl::BufferBinding bindingType : angle::AllEnums<gl::BufferBinding>())
2390     {
2391         // These binding types need compute support to be queried
2392         if (bindingType == gl::BufferBinding::AtomicCounter ||
2393             bindingType == gl::BufferBinding::DispatchIndirect ||
2394             bindingType == gl::BufferBinding::ShaderStorage)
2395         {
2396             if (!nativegl::SupportsCompute(mFunctions))
2397             {
2398                 continue;
2399             }
2400         }
2401 
2402         // Transform feedback buffer bindings are tracked in TransformFeedbackGL
2403         if (bindingType == gl::BufferBinding::TransformFeedback)
2404         {
2405             continue;
2406         }
2407 
2408         GLenum bindingTypeGL  = nativegl::GetBufferBindingQuery(bindingType);
2409         std::string localName = "mBuffers[" + ToString(bindingType) + "]";
2410         ValidateStateHelper(mFunctions, mBuffers[bindingType], bindingTypeGL, localName.c_str(),
2411                             nativegl::GetBufferBindingString(bindingType).c_str());
2412     }
2413 
2414     // Vertex array object
2415     ValidateStateHelper(mFunctions, mVAO, GL_VERTEX_ARRAY_BINDING, "mVAO",
2416                         "GL_VERTEX_ARRAY_BINDING");
2417 }
2418 
2419 }  // namespace rx
2420