• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2014 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 // State.cpp: Implements the State class, encapsulating raw GL state.
8 
9 #include "libANGLE/State.h"
10 
11 #include <string.h>
12 #include <limits>
13 
14 #include "common/bitset_utils.h"
15 #include "common/mathutil.h"
16 #include "common/matrix_utils.h"
17 #include "libANGLE/Buffer.h"
18 #include "libANGLE/Caps.h"
19 #include "libANGLE/Context.h"
20 #include "libANGLE/Debug.h"
21 #include "libANGLE/Framebuffer.h"
22 #include "libANGLE/FramebufferAttachment.h"
23 #include "libANGLE/PixelLocalStorage.h"
24 #include "libANGLE/Query.h"
25 #include "libANGLE/VertexArray.h"
26 #include "libANGLE/formatutils.h"
27 #include "libANGLE/queryconversions.h"
28 #include "libANGLE/queryutils.h"
29 #include "libANGLE/renderer/ContextImpl.h"
30 #include "libANGLE/renderer/TextureImpl.h"
31 
32 namespace gl
33 {
34 
35 namespace
36 {
GetAlternativeQueryType(QueryType type,QueryType * alternativeType)37 bool GetAlternativeQueryType(QueryType type, QueryType *alternativeType)
38 {
39     switch (type)
40     {
41         case QueryType::AnySamples:
42             *alternativeType = QueryType::AnySamplesConservative;
43             return true;
44         case QueryType::AnySamplesConservative:
45             *alternativeType = QueryType::AnySamples;
46             return true;
47         default:
48             return false;
49     }
50 }
51 
52 // Mapping from a buffer binding type to a dirty bit type.
53 constexpr angle::PackedEnumMap<BufferBinding, size_t> kBufferBindingDirtyBits = {{
54     {BufferBinding::AtomicCounter, state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING},
55     {BufferBinding::DispatchIndirect, state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING},
56     {BufferBinding::DrawIndirect, state::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING},
57     {BufferBinding::PixelPack, state::DIRTY_BIT_PACK_BUFFER_BINDING},
58     {BufferBinding::PixelUnpack, state::DIRTY_BIT_UNPACK_BUFFER_BINDING},
59     {BufferBinding::ShaderStorage, state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING},
60     {BufferBinding::Uniform, state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS},
61 }};
62 
63 // Returns a buffer binding function depending on if a dirty bit is set.
64 template <BufferBinding Target>
GetBufferBindingSetter()65 constexpr std::pair<BufferBinding, State::BufferBindingSetter> GetBufferBindingSetter()
66 {
67     return std::make_pair(Target, kBufferBindingDirtyBits[Target] != 0
68                                       ? &State::setGenericBufferBindingWithBit<Target>
69                                       : &State::setGenericBufferBinding<Target>);
70 }
71 
72 template <typename T>
73 using ContextStateMember = T *(State::*);
74 
75 template <typename T>
AllocateOrGetSharedResourceManager(const State * shareContextState,ContextStateMember<T> member,T * shareResources=nullptr)76 T *AllocateOrGetSharedResourceManager(const State *shareContextState,
77                                       ContextStateMember<T> member,
78                                       T *shareResources = nullptr)
79 {
80     if (shareContextState)
81     {
82         T *resourceManager = (*shareContextState).*member;
83         ASSERT(!resourceManager || resourceManager == shareResources || !shareResources);
84         resourceManager->addRef();
85         return resourceManager;
86     }
87     else if (shareResources)
88     {
89         shareResources->addRef();
90         return shareResources;
91     }
92     else
93     {
94         return new T();
95     }
96 }
97 
98 // TODO(https://anglebug.com/3889): Remove this helper function after blink and chromium part
99 // refactory done.
IsTextureCompatibleWithSampler(TextureType texture,TextureType sampler)100 bool IsTextureCompatibleWithSampler(TextureType texture, TextureType sampler)
101 {
102     if (sampler == texture)
103     {
104         return true;
105     }
106 
107     if (sampler == TextureType::VideoImage)
108     {
109         if (texture == TextureType::VideoImage || texture == TextureType::_2D)
110         {
111             return true;
112         }
113     }
114 
115     return false;
116 }
117 
118 uint32_t gIDCounter = 1;
119 }  // namespace
120 
121 template <typename BindingT, typename... ArgsT>
UpdateNonTFBufferBindingWebGL(const Context * context,BindingT * binding,Buffer * buffer,ArgsT...args)122 ANGLE_INLINE void UpdateNonTFBufferBindingWebGL(const Context *context,
123                                                 BindingT *binding,
124                                                 Buffer *buffer,
125                                                 ArgsT... args)
126 {
127     Buffer *oldBuffer = binding->get();
128     if (oldBuffer)
129     {
130         oldBuffer->onNonTFBindingChanged(-1);
131         oldBuffer->release(context);
132     }
133     binding->assign(buffer, args...);
134     if (buffer)
135     {
136         buffer->addRef();
137         buffer->onNonTFBindingChanged(1);
138     }
139 }
140 
141 template <typename BindingT, typename... ArgsT>
UpdateTFBufferBindingWebGL(const Context * context,BindingT * binding,bool indexed,ArgsT...args)142 void UpdateTFBufferBindingWebGL(const Context *context,
143                                 BindingT *binding,
144                                 bool indexed,
145                                 ArgsT... args)
146 {
147     if (binding->get())
148         (*binding)->onTFBindingChanged(context, false, indexed);
149     binding->set(context, args...);
150     if (binding->get())
151         (*binding)->onTFBindingChanged(context, true, indexed);
152 }
153 
UpdateBufferBinding(const Context * context,BindingPointer<Buffer> * binding,Buffer * buffer,BufferBinding target)154 void UpdateBufferBinding(const Context *context,
155                          BindingPointer<Buffer> *binding,
156                          Buffer *buffer,
157                          BufferBinding target)
158 {
159     if (context->isWebGL())
160     {
161         if (target == BufferBinding::TransformFeedback)
162         {
163             UpdateTFBufferBindingWebGL(context, binding, false, buffer);
164         }
165         else
166         {
167             UpdateNonTFBufferBindingWebGL(context, binding, buffer);
168         }
169     }
170     else
171     {
172         binding->set(context, buffer);
173     }
174 }
175 
UpdateIndexedBufferBinding(const Context * context,OffsetBindingPointer<Buffer> * binding,Buffer * buffer,BufferBinding target,GLintptr offset,GLsizeiptr size)176 void UpdateIndexedBufferBinding(const Context *context,
177                                 OffsetBindingPointer<Buffer> *binding,
178                                 Buffer *buffer,
179                                 BufferBinding target,
180                                 GLintptr offset,
181                                 GLsizeiptr size)
182 {
183     if (context->isWebGL())
184     {
185         if (target == BufferBinding::TransformFeedback)
186         {
187             UpdateTFBufferBindingWebGL(context, binding, true, buffer, offset, size);
188         }
189         else
190         {
191             UpdateNonTFBufferBindingWebGL(context, binding, buffer, offset, size);
192         }
193     }
194     else
195     {
196         binding->set(context, buffer, offset, size);
197     }
198 }
199 
200 // These template functions must be defined before they are instantiated in kBufferSetters.
201 template <BufferBinding Target>
setGenericBufferBindingWithBit(const Context * context,Buffer * buffer)202 void State::setGenericBufferBindingWithBit(const Context *context, Buffer *buffer)
203 {
204     if (context->isWebGL())
205     {
206         UpdateNonTFBufferBindingWebGL(context, &mBoundBuffers[Target], buffer);
207     }
208     else
209     {
210         mBoundBuffers[Target].set(context, buffer);
211     }
212     mDirtyBits.set(kBufferBindingDirtyBits[Target]);
213 }
214 
215 template <BufferBinding Target>
setGenericBufferBinding(const Context * context,Buffer * buffer)216 void State::setGenericBufferBinding(const Context *context, Buffer *buffer)
217 {
218     if (context->isWebGL())
219     {
220         UpdateNonTFBufferBindingWebGL(context, &mBoundBuffers[Target], buffer);
221     }
222     else
223     {
224         mBoundBuffers[Target].set(context, buffer);
225     }
226 }
227 
228 template <>
setGenericBufferBinding(const Context * context,Buffer * buffer)229 void State::setGenericBufferBinding<BufferBinding::TransformFeedback>(const Context *context,
230                                                                       Buffer *buffer)
231 {
232     if (context->isWebGL())
233     {
234         UpdateTFBufferBindingWebGL(context, &mBoundBuffers[BufferBinding::TransformFeedback], false,
235                                    buffer);
236     }
237     else
238     {
239         mBoundBuffers[BufferBinding::TransformFeedback].set(context, buffer);
240     }
241 }
242 
243 template <>
setGenericBufferBinding(const Context * context,Buffer * buffer)244 void State::setGenericBufferBinding<BufferBinding::ElementArray>(const Context *context,
245                                                                  Buffer *buffer)
246 {
247     Buffer *oldBuffer = mVertexArray->mState.mElementArrayBuffer.get();
248     if (oldBuffer)
249     {
250         oldBuffer->removeObserver(&mVertexArray->mState.mElementArrayBuffer);
251         oldBuffer->removeContentsObserver(mVertexArray, kElementArrayBufferIndex);
252         if (context->isWebGL())
253         {
254             oldBuffer->onNonTFBindingChanged(-1);
255         }
256         oldBuffer->release(context);
257     }
258     mVertexArray->mState.mElementArrayBuffer.assign(buffer);
259     if (buffer)
260     {
261         buffer->addObserver(&mVertexArray->mState.mElementArrayBuffer);
262         buffer->addContentsObserver(mVertexArray, kElementArrayBufferIndex);
263         if (context->isWebGL())
264         {
265             buffer->onNonTFBindingChanged(1);
266         }
267         buffer->addRef();
268     }
269     mVertexArray->mDirtyBits.set(VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
270     mVertexArray->mIndexRangeCache.invalidate();
271     mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
272 }
273 
274 const angle::PackedEnumMap<BufferBinding, State::BufferBindingSetter> State::kBufferSetters = {{
275     GetBufferBindingSetter<BufferBinding::Array>(),
276     GetBufferBindingSetter<BufferBinding::AtomicCounter>(),
277     GetBufferBindingSetter<BufferBinding::CopyRead>(),
278     GetBufferBindingSetter<BufferBinding::CopyWrite>(),
279     GetBufferBindingSetter<BufferBinding::DispatchIndirect>(),
280     GetBufferBindingSetter<BufferBinding::DrawIndirect>(),
281     GetBufferBindingSetter<BufferBinding::ElementArray>(),
282     GetBufferBindingSetter<BufferBinding::PixelPack>(),
283     GetBufferBindingSetter<BufferBinding::PixelUnpack>(),
284     GetBufferBindingSetter<BufferBinding::ShaderStorage>(),
285     GetBufferBindingSetter<BufferBinding::Texture>(),
286     GetBufferBindingSetter<BufferBinding::TransformFeedback>(),
287     GetBufferBindingSetter<BufferBinding::Uniform>(),
288 }};
289 
ActiveTexturesCache()290 ActiveTexturesCache::ActiveTexturesCache() : mTextures{} {}
291 
~ActiveTexturesCache()292 ActiveTexturesCache::~ActiveTexturesCache()
293 {
294     ASSERT(empty());
295 }
296 
clear()297 void ActiveTexturesCache::clear()
298 {
299     for (size_t textureIndex = 0; textureIndex < mTextures.size(); ++textureIndex)
300     {
301         reset(textureIndex);
302     }
303 }
304 
empty() const305 bool ActiveTexturesCache::empty() const
306 {
307     for (Texture *texture : mTextures)
308     {
309         if (texture)
310         {
311             return false;
312         }
313     }
314 
315     return true;
316 }
317 
reset(size_t textureIndex)318 ANGLE_INLINE void ActiveTexturesCache::reset(size_t textureIndex)
319 {
320     if (mTextures[textureIndex])
321     {
322         mTextures[textureIndex] = nullptr;
323     }
324 }
325 
set(size_t textureIndex,Texture * texture)326 ANGLE_INLINE void ActiveTexturesCache::set(size_t textureIndex, Texture *texture)
327 {
328     ASSERT(texture);
329     mTextures[textureIndex] = texture;
330 }
331 
PrivateState(const EGLenum clientType,const Version & clientVersion,EGLint profileMask,bool debug,bool bindGeneratesResourceCHROMIUM,bool clientArraysEnabled,bool robustResourceInit,bool programBinaryCacheEnabled)332 PrivateState::PrivateState(const EGLenum clientType,
333                            const Version &clientVersion,
334                            EGLint profileMask,
335                            bool debug,
336                            bool bindGeneratesResourceCHROMIUM,
337                            bool clientArraysEnabled,
338                            bool robustResourceInit,
339                            bool programBinaryCacheEnabled)
340     : mClientType(clientType),
341       mProfileMask(profileMask),
342       mClientVersion(clientVersion),
343       mDepthClearValue(0),
344       mStencilClearValue(0),
345       mScissorTest(false),
346       mSampleAlphaToCoverage(false),
347       mSampleCoverage(false),
348       mSampleCoverageValue(0),
349       mSampleCoverageInvert(false),
350       mSampleMask(false),
351       mMaxSampleMaskWords(0),
352       mIsSampleShadingEnabled(false),
353       mMinSampleShading(0.0f),
354       mStencilRef(0),
355       mStencilBackRef(0),
356       mLineWidth(0),
357       mGenerateMipmapHint(GL_NONE),
358       mFragmentShaderDerivativeHint(GL_NONE),
359       mNearZ(0),
360       mFarZ(0),
361       mProvokingVertex(gl::ProvokingVertexConvention::LastVertexConvention),
362       mActiveSampler(0),
363       mPrimitiveRestart(false),
364       mMultiSampling(false),
365       mSampleAlphaToOne(false),
366       mFramebufferSRGB(true),
367       mTextureRectangleEnabled(true),
368       mLogicOpEnabled(false),
369       mLogicOp(LogicalOperation::Copy),
370       mPatchVertices(3),
371       mPixelLocalStorageActivePlanes(0),
372       mNoSimultaneousConstantColorAndAlphaBlendFunc(false),
373       mSetBlendIndexedInvoked(false),
374       mSetBlendFactorsIndexedInvoked(false),
375       mSetBlendEquationsIndexedInvoked(false),
376       mBoundingBoxMinX(-1.0f),
377       mBoundingBoxMinY(-1.0f),
378       mBoundingBoxMinZ(-1.0f),
379       mBoundingBoxMinW(1.0f),
380       mBoundingBoxMaxX(1.0f),
381       mBoundingBoxMaxY(1.0f),
382       mBoundingBoxMaxZ(1.0f),
383       mBoundingBoxMaxW(1.0f),
384       mShadingRatePreserveAspectRatio(false),
385       mShadingRate(ShadingRate::Undefined),
386       mFetchPerSample(false),
387       mBindGeneratesResource(bindGeneratesResourceCHROMIUM),
388       mClientArraysEnabled(clientArraysEnabled),
389       mRobustResourceInit(robustResourceInit),
390       mProgramBinaryCacheEnabled(programBinaryCacheEnabled),
391       mDebug(debug)
392 {}
393 
394 PrivateState::~PrivateState() = default;
395 
initialize(Context * context)396 void PrivateState::initialize(Context *context)
397 {
398     mBlendStateExt = BlendStateExt(mCaps.maxDrawBuffers);
399 
400     setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f);
401 
402     mDepthClearValue   = 1.0f;
403     mStencilClearValue = 0;
404 
405     mScissorTest    = false;
406     mScissor.x      = 0;
407     mScissor.y      = 0;
408     mScissor.width  = 0;
409     mScissor.height = 0;
410 
411     mBlendColor.red   = 0;
412     mBlendColor.green = 0;
413     mBlendColor.blue  = 0;
414     mBlendColor.alpha = 0;
415 
416     mStencilRef     = 0;
417     mStencilBackRef = 0;
418 
419     mSampleCoverage       = false;
420     mSampleCoverageValue  = 1.0f;
421     mSampleCoverageInvert = false;
422 
423     mMaxSampleMaskWords = static_cast<GLuint>(mCaps.maxSampleMaskWords);
424     mSampleMask         = false;
425     mSampleMaskValues.fill(~GLbitfield(0));
426 
427     mGenerateMipmapHint           = GL_DONT_CARE;
428     mFragmentShaderDerivativeHint = GL_DONT_CARE;
429 
430     mLineWidth = 1.0f;
431 
432     mViewport.x      = 0;
433     mViewport.y      = 0;
434     mViewport.width  = 0;
435     mViewport.height = 0;
436     mNearZ           = 0.0f;
437     mFarZ            = 1.0f;
438 
439     mClipOrigin    = ClipOrigin::LowerLeft;
440     mClipDepthMode = ClipDepthMode::NegativeOneToOne;
441 
442     mActiveSampler = 0;
443 
444     mVertexAttribCurrentValues.resize(mCaps.maxVertexAttributes);
445 
446     // Set all indexes in state attributes type mask to float (default)
447     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
448     {
449         SetComponentTypeMask(ComponentType::Float, i, &mCurrentValuesTypeMask);
450     }
451 
452     mAllAttribsMask = AttributesMask(angle::BitMask<uint32_t>(mCaps.maxVertexAttributes));
453 
454     mMultiSampling    = true;
455     mSampleAlphaToOne = false;
456 
457     mCoverageModulation = GL_NONE;
458 
459     mPrimitiveRestart = false;
460 
461     mNoSimultaneousConstantColorAndAlphaBlendFunc =
462         context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
463         context->getExtensions().webglCompatibilityANGLE;
464 
465     mNoUnclampedBlendColor = context->getLimitations().noUnclampedBlendColor;
466 
467     // GLES1 emulation: Initialize state for GLES1 if version applies
468     // TODO(http://anglebug.com/3745): When on desktop client only do this in compatibility profile
469     if (context->getClientVersion() < Version(2, 0) || mClientType == EGL_OPENGL_API)
470     {
471         mGLES1State.initialize(context, this);
472     }
473 }
474 
initializeForCapture(const Context * context)475 void PrivateState::initializeForCapture(const Context *context)
476 {
477     mCaps       = context->getCaps();
478     mExtensions = context->getExtensions();
479 }
480 
reset()481 void PrivateState::reset()
482 {
483     mClipDistancesEnabled.reset();
484 }
485 
setColorClearValue(float red,float green,float blue,float alpha)486 void PrivateState::setColorClearValue(float red, float green, float blue, float alpha)
487 {
488     mColorClearValue.red   = red;
489     mColorClearValue.green = green;
490     mColorClearValue.blue  = blue;
491     mColorClearValue.alpha = alpha;
492     mDirtyBits.set(state::DIRTY_BIT_CLEAR_COLOR);
493 }
494 
setDepthClearValue(float depth)495 void PrivateState::setDepthClearValue(float depth)
496 {
497     mDepthClearValue = depth;
498     mDirtyBits.set(state::DIRTY_BIT_CLEAR_DEPTH);
499 }
500 
setStencilClearValue(int stencil)501 void PrivateState::setStencilClearValue(int stencil)
502 {
503     mStencilClearValue = stencil;
504     mDirtyBits.set(state::DIRTY_BIT_CLEAR_STENCIL);
505 }
506 
setColorMask(bool red,bool green,bool blue,bool alpha)507 void PrivateState::setColorMask(bool red, bool green, bool blue, bool alpha)
508 {
509     mBlendState.colorMaskRed   = red;
510     mBlendState.colorMaskGreen = green;
511     mBlendState.colorMaskBlue  = blue;
512     mBlendState.colorMaskAlpha = alpha;
513 
514     mBlendStateExt.setColorMask(red, green, blue, alpha);
515     mDirtyBits.set(state::DIRTY_BIT_COLOR_MASK);
516 }
517 
setColorMaskIndexed(bool red,bool green,bool blue,bool alpha,GLuint index)518 void PrivateState::setColorMaskIndexed(bool red, bool green, bool blue, bool alpha, GLuint index)
519 {
520     mBlendStateExt.setColorMaskIndexed(index, red, green, blue, alpha);
521     mDirtyBits.set(state::DIRTY_BIT_COLOR_MASK);
522 }
523 
setDepthMask(bool mask)524 void PrivateState::setDepthMask(bool mask)
525 {
526     if (mDepthStencil.depthMask != mask)
527     {
528         mDepthStencil.depthMask = mask;
529         mDirtyBits.set(state::DIRTY_BIT_DEPTH_MASK);
530     }
531 }
532 
setRasterizerDiscard(bool enabled)533 void PrivateState::setRasterizerDiscard(bool enabled)
534 {
535     if (mRasterizer.rasterizerDiscard != enabled)
536     {
537         mRasterizer.rasterizerDiscard = enabled;
538         mDirtyBits.set(state::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
539     }
540 }
541 
setPrimitiveRestart(bool enabled)542 void PrivateState::setPrimitiveRestart(bool enabled)
543 {
544     if (mPrimitiveRestart != enabled)
545     {
546         mPrimitiveRestart = enabled;
547         mDirtyBits.set(state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
548     }
549 }
550 
setCullFace(bool enabled)551 void PrivateState::setCullFace(bool enabled)
552 {
553     if (mRasterizer.cullFace != enabled)
554     {
555         mRasterizer.cullFace = enabled;
556         mDirtyBits.set(state::DIRTY_BIT_CULL_FACE_ENABLED);
557     }
558 }
559 
setCullMode(CullFaceMode mode)560 void PrivateState::setCullMode(CullFaceMode mode)
561 {
562     if (mRasterizer.cullMode != mode)
563     {
564         mRasterizer.cullMode = mode;
565         mDirtyBits.set(state::DIRTY_BIT_CULL_FACE);
566     }
567 }
568 
setFrontFace(GLenum front)569 void PrivateState::setFrontFace(GLenum front)
570 {
571     if (mRasterizer.frontFace != front)
572     {
573         mRasterizer.frontFace = front;
574         mDirtyBits.set(state::DIRTY_BIT_FRONT_FACE);
575     }
576 }
577 
setDepthClamp(bool enabled)578 void PrivateState::setDepthClamp(bool enabled)
579 {
580     if (mRasterizer.depthClamp != enabled)
581     {
582         mRasterizer.depthClamp = enabled;
583         mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
584         mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED);
585     }
586 }
587 
setDepthTest(bool enabled)588 void PrivateState::setDepthTest(bool enabled)
589 {
590     if (mDepthStencil.depthTest != enabled)
591     {
592         mDepthStencil.depthTest = enabled;
593         mDirtyBits.set(state::DIRTY_BIT_DEPTH_TEST_ENABLED);
594     }
595 }
596 
setDepthFunc(GLenum depthFunc)597 void PrivateState::setDepthFunc(GLenum depthFunc)
598 {
599     if (mDepthStencil.depthFunc != depthFunc)
600     {
601         mDepthStencil.depthFunc = depthFunc;
602         mDirtyBits.set(state::DIRTY_BIT_DEPTH_FUNC);
603     }
604 }
605 
setDepthRange(float zNear,float zFar)606 void PrivateState::setDepthRange(float zNear, float zFar)
607 {
608     if (mNearZ != zNear || mFarZ != zFar)
609     {
610         mNearZ = zNear;
611         mFarZ  = zFar;
612         mDirtyBits.set(state::DIRTY_BIT_DEPTH_RANGE);
613     }
614 }
615 
setClipControl(ClipOrigin origin,ClipDepthMode depth)616 void PrivateState::setClipControl(ClipOrigin origin, ClipDepthMode depth)
617 {
618     bool updated = false;
619     if (mClipOrigin != origin)
620     {
621         mClipOrigin = origin;
622         updated     = true;
623     }
624 
625     if (mClipDepthMode != depth)
626     {
627         mClipDepthMode = depth;
628         updated        = true;
629     }
630 
631     if (updated)
632     {
633         mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
634         mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_CLIP_CONTROL);
635     }
636 }
637 
setBlend(bool enabled)638 void PrivateState::setBlend(bool enabled)
639 {
640     if (mSetBlendIndexedInvoked || mBlendState.blend != enabled)
641     {
642         mBlendState.blend = enabled;
643 
644         mSetBlendIndexedInvoked = false;
645         mBlendStateExt.setEnabled(enabled);
646         mDirtyBits.set(state::DIRTY_BIT_BLEND_ENABLED);
647     }
648 }
649 
setBlendIndexed(bool enabled,GLuint index)650 void PrivateState::setBlendIndexed(bool enabled, GLuint index)
651 {
652     mSetBlendIndexedInvoked = true;
653     mBlendStateExt.setEnabledIndexed(index, enabled);
654     mDirtyBits.set(state::DIRTY_BIT_BLEND_ENABLED);
655 }
656 
hasConstantColor(GLenum sourceRGB,GLenum destRGB) const657 ANGLE_INLINE bool PrivateState::hasConstantColor(GLenum sourceRGB, GLenum destRGB) const
658 {
659     return sourceRGB == GL_CONSTANT_COLOR || sourceRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
660            destRGB == GL_CONSTANT_COLOR || destRGB == GL_ONE_MINUS_CONSTANT_COLOR;
661 }
662 
hasConstantAlpha(GLenum sourceRGB,GLenum destRGB) const663 ANGLE_INLINE bool PrivateState::hasConstantAlpha(GLenum sourceRGB, GLenum destRGB) const
664 {
665     return sourceRGB == GL_CONSTANT_ALPHA || sourceRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
666            destRGB == GL_CONSTANT_ALPHA || destRGB == GL_ONE_MINUS_CONSTANT_ALPHA;
667 }
668 
setBlendFactors(GLenum sourceRGB,GLenum destRGB,GLenum sourceAlpha,GLenum destAlpha)669 void PrivateState::setBlendFactors(GLenum sourceRGB,
670                                    GLenum destRGB,
671                                    GLenum sourceAlpha,
672                                    GLenum destAlpha)
673 {
674     if (!mSetBlendFactorsIndexedInvoked && mBlendState.sourceBlendRGB == sourceRGB &&
675         mBlendState.destBlendRGB == destRGB && mBlendState.sourceBlendAlpha == sourceAlpha &&
676         mBlendState.destBlendAlpha == destAlpha)
677     {
678         return;
679     }
680 
681     mBlendState.sourceBlendRGB   = sourceRGB;
682     mBlendState.destBlendRGB     = destRGB;
683     mBlendState.sourceBlendAlpha = sourceAlpha;
684     mBlendState.destBlendAlpha   = destAlpha;
685 
686     if (mNoSimultaneousConstantColorAndAlphaBlendFunc)
687     {
688         if (hasConstantColor(sourceRGB, destRGB))
689         {
690             mBlendFuncConstantColorDrawBuffers.set();
691         }
692         else
693         {
694             mBlendFuncConstantColorDrawBuffers.reset();
695         }
696 
697         if (hasConstantAlpha(sourceRGB, destRGB))
698         {
699             mBlendFuncConstantAlphaDrawBuffers.set();
700         }
701         else
702         {
703             mBlendFuncConstantAlphaDrawBuffers.reset();
704         }
705     }
706 
707     mSetBlendFactorsIndexedInvoked = false;
708     mBlendStateExt.setFactors(sourceRGB, destRGB, sourceAlpha, destAlpha);
709     mDirtyBits.set(state::DIRTY_BIT_BLEND_FUNCS);
710 }
711 
setBlendFactorsIndexed(GLenum sourceRGB,GLenum destRGB,GLenum sourceAlpha,GLenum destAlpha,GLuint index)712 void PrivateState::setBlendFactorsIndexed(GLenum sourceRGB,
713                                           GLenum destRGB,
714                                           GLenum sourceAlpha,
715                                           GLenum destAlpha,
716                                           GLuint index)
717 {
718     if (mNoSimultaneousConstantColorAndAlphaBlendFunc)
719     {
720         mBlendFuncConstantColorDrawBuffers.set(index, hasConstantColor(sourceRGB, destRGB));
721         mBlendFuncConstantAlphaDrawBuffers.set(index, hasConstantAlpha(sourceRGB, destRGB));
722     }
723 
724     mSetBlendFactorsIndexedInvoked = true;
725     mBlendStateExt.setFactorsIndexed(index, sourceRGB, destRGB, sourceAlpha, destAlpha);
726     mDirtyBits.set(state::DIRTY_BIT_BLEND_FUNCS);
727 }
728 
setBlendColor(float red,float green,float blue,float alpha)729 void PrivateState::setBlendColor(float red, float green, float blue, float alpha)
730 {
731     // In ES2 without render-to-float extensions, BlendColor clamps to [0,1] on store.
732     // On ES3+, or with render-to-float exts enabled, it does not clamp on store.
733     const bool isES2 = mClientVersion.major == 2;
734     const bool hasFloatBlending =
735         mExtensions.colorBufferFloatEXT || mExtensions.colorBufferHalfFloatEXT ||
736         mExtensions.colorBufferFloatRgbCHROMIUM || mExtensions.colorBufferFloatRgbaCHROMIUM;
737     if ((isES2 && !hasFloatBlending) || mNoUnclampedBlendColor)
738     {
739         red   = clamp01(red);
740         green = clamp01(green);
741         blue  = clamp01(blue);
742         alpha = clamp01(alpha);
743     }
744 
745     if (mBlendColor.red != red || mBlendColor.green != green || mBlendColor.blue != blue ||
746         mBlendColor.alpha != alpha)
747     {
748         mBlendColor.red   = red;
749         mBlendColor.green = green;
750         mBlendColor.blue  = blue;
751         mBlendColor.alpha = alpha;
752         mDirtyBits.set(state::DIRTY_BIT_BLEND_COLOR);
753     }
754 }
755 
setBlendEquation(GLenum rgbEquation,GLenum alphaEquation)756 void PrivateState::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
757 {
758     if (mSetBlendEquationsIndexedInvoked || mBlendState.blendEquationRGB != rgbEquation ||
759         mBlendState.blendEquationAlpha != alphaEquation)
760     {
761         mBlendState.blendEquationRGB   = rgbEquation;
762         mBlendState.blendEquationAlpha = alphaEquation;
763 
764         mSetBlendEquationsIndexedInvoked = false;
765         mBlendStateExt.setEquations(rgbEquation, alphaEquation);
766         mDirtyBits.set(state::DIRTY_BIT_BLEND_EQUATIONS);
767     }
768 }
769 
setBlendEquationIndexed(GLenum rgbEquation,GLenum alphaEquation,GLuint index)770 void PrivateState::setBlendEquationIndexed(GLenum rgbEquation, GLenum alphaEquation, GLuint index)
771 {
772     mSetBlendEquationsIndexedInvoked = true;
773     mBlendStateExt.setEquationsIndexed(index, rgbEquation, alphaEquation);
774     mDirtyBits.set(state::DIRTY_BIT_BLEND_EQUATIONS);
775 }
776 
setStencilTest(bool enabled)777 void PrivateState::setStencilTest(bool enabled)
778 {
779     if (mDepthStencil.stencilTest != enabled)
780     {
781         mDepthStencil.stencilTest = enabled;
782         mDirtyBits.set(state::DIRTY_BIT_STENCIL_TEST_ENABLED);
783     }
784 }
785 
setStencilParams(GLenum stencilFunc,GLint stencilRef,GLuint stencilMask)786 void PrivateState::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
787 {
788     if (mDepthStencil.stencilFunc != stencilFunc || mStencilRef != stencilRef ||
789         mDepthStencil.stencilMask != stencilMask)
790     {
791         mDepthStencil.stencilFunc = stencilFunc;
792         mStencilRef               = stencilRef;
793         mDepthStencil.stencilMask = stencilMask;
794         mDirtyBits.set(state::DIRTY_BIT_STENCIL_FUNCS_FRONT);
795     }
796 }
797 
setStencilBackParams(GLenum stencilBackFunc,GLint stencilBackRef,GLuint stencilBackMask)798 void PrivateState::setStencilBackParams(GLenum stencilBackFunc,
799                                         GLint stencilBackRef,
800                                         GLuint stencilBackMask)
801 {
802     if (mDepthStencil.stencilBackFunc != stencilBackFunc || mStencilBackRef != stencilBackRef ||
803         mDepthStencil.stencilBackMask != stencilBackMask)
804     {
805         mDepthStencil.stencilBackFunc = stencilBackFunc;
806         mStencilBackRef               = stencilBackRef;
807         mDepthStencil.stencilBackMask = stencilBackMask;
808         mDirtyBits.set(state::DIRTY_BIT_STENCIL_FUNCS_BACK);
809     }
810 }
811 
setStencilWritemask(GLuint stencilWritemask)812 void PrivateState::setStencilWritemask(GLuint stencilWritemask)
813 {
814     if (mDepthStencil.stencilWritemask != stencilWritemask)
815     {
816         mDepthStencil.stencilWritemask = stencilWritemask;
817         mDirtyBits.set(state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
818     }
819 }
820 
setStencilBackWritemask(GLuint stencilBackWritemask)821 void PrivateState::setStencilBackWritemask(GLuint stencilBackWritemask)
822 {
823     if (mDepthStencil.stencilBackWritemask != stencilBackWritemask)
824     {
825         mDepthStencil.stencilBackWritemask = stencilBackWritemask;
826         mDirtyBits.set(state::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
827     }
828 }
829 
setStencilOperations(GLenum stencilFail,GLenum stencilPassDepthFail,GLenum stencilPassDepthPass)830 void PrivateState::setStencilOperations(GLenum stencilFail,
831                                         GLenum stencilPassDepthFail,
832                                         GLenum stencilPassDepthPass)
833 {
834     if (mDepthStencil.stencilFail != stencilFail ||
835         mDepthStencil.stencilPassDepthFail != stencilPassDepthFail ||
836         mDepthStencil.stencilPassDepthPass != stencilPassDepthPass)
837     {
838         mDepthStencil.stencilFail          = stencilFail;
839         mDepthStencil.stencilPassDepthFail = stencilPassDepthFail;
840         mDepthStencil.stencilPassDepthPass = stencilPassDepthPass;
841         mDirtyBits.set(state::DIRTY_BIT_STENCIL_OPS_FRONT);
842     }
843 }
844 
setStencilBackOperations(GLenum stencilBackFail,GLenum stencilBackPassDepthFail,GLenum stencilBackPassDepthPass)845 void PrivateState::setStencilBackOperations(GLenum stencilBackFail,
846                                             GLenum stencilBackPassDepthFail,
847                                             GLenum stencilBackPassDepthPass)
848 {
849     if (mDepthStencil.stencilBackFail != stencilBackFail ||
850         mDepthStencil.stencilBackPassDepthFail != stencilBackPassDepthFail ||
851         mDepthStencil.stencilBackPassDepthPass != stencilBackPassDepthPass)
852     {
853         mDepthStencil.stencilBackFail          = stencilBackFail;
854         mDepthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail;
855         mDepthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass;
856         mDirtyBits.set(state::DIRTY_BIT_STENCIL_OPS_BACK);
857     }
858 }
859 
setPolygonMode(PolygonMode mode)860 void PrivateState::setPolygonMode(PolygonMode mode)
861 {
862     if (mRasterizer.polygonMode != mode)
863     {
864         mRasterizer.polygonMode = mode;
865         mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
866         mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_POLYGON_MODE);
867     }
868 }
869 
setPolygonOffsetPoint(bool enabled)870 void PrivateState::setPolygonOffsetPoint(bool enabled)
871 {
872     if (mRasterizer.polygonOffsetPoint != enabled)
873     {
874         mRasterizer.polygonOffsetPoint = enabled;
875         mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
876         mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_POINT_ENABLED);
877     }
878 }
879 
setPolygonOffsetLine(bool enabled)880 void PrivateState::setPolygonOffsetLine(bool enabled)
881 {
882     if (mRasterizer.polygonOffsetLine != enabled)
883     {
884         mRasterizer.polygonOffsetLine = enabled;
885         mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
886         mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED);
887     }
888 }
889 
setPolygonOffsetFill(bool enabled)890 void PrivateState::setPolygonOffsetFill(bool enabled)
891 {
892     if (mRasterizer.polygonOffsetFill != enabled)
893     {
894         mRasterizer.polygonOffsetFill = enabled;
895         mDirtyBits.set(state::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
896     }
897 }
898 
setPolygonOffsetParams(GLfloat factor,GLfloat units,GLfloat clamp)899 void PrivateState::setPolygonOffsetParams(GLfloat factor, GLfloat units, GLfloat clamp)
900 {
901     // An application can pass NaN values here, so handle this gracefully
902     mRasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor;
903     mRasterizer.polygonOffsetUnits  = units != units ? 0.0f : units;
904     mRasterizer.polygonOffsetClamp  = clamp != clamp ? 0.0f : clamp;
905     mDirtyBits.set(state::DIRTY_BIT_POLYGON_OFFSET);
906 }
907 
setSampleAlphaToCoverage(bool enabled)908 void PrivateState::setSampleAlphaToCoverage(bool enabled)
909 {
910     if (mSampleAlphaToCoverage != enabled)
911     {
912         mSampleAlphaToCoverage = enabled;
913         mDirtyBits.set(state::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
914     }
915 }
916 
setSampleCoverage(bool enabled)917 void PrivateState::setSampleCoverage(bool enabled)
918 {
919     if (mSampleCoverage != enabled)
920     {
921         mSampleCoverage = enabled;
922         mDirtyBits.set(state::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
923     }
924 }
925 
setSampleCoverageParams(GLclampf value,bool invert)926 void PrivateState::setSampleCoverageParams(GLclampf value, bool invert)
927 {
928     mSampleCoverageValue  = value;
929     mSampleCoverageInvert = invert;
930     mDirtyBits.set(state::DIRTY_BIT_SAMPLE_COVERAGE);
931 }
932 
setSampleMaskEnabled(bool enabled)933 void PrivateState::setSampleMaskEnabled(bool enabled)
934 {
935     if (mSampleMask != enabled)
936     {
937         mSampleMask = enabled;
938         mDirtyBits.set(state::DIRTY_BIT_SAMPLE_MASK_ENABLED);
939     }
940 }
941 
setSampleMaskParams(GLuint maskNumber,GLbitfield mask)942 void PrivateState::setSampleMaskParams(GLuint maskNumber, GLbitfield mask)
943 {
944     ASSERT(maskNumber < mMaxSampleMaskWords);
945     mSampleMaskValues[maskNumber] = mask;
946     mDirtyBits.set(state::DIRTY_BIT_SAMPLE_MASK);
947 }
948 
setSampleAlphaToOne(bool enabled)949 void PrivateState::setSampleAlphaToOne(bool enabled)
950 {
951     if (mSampleAlphaToOne != enabled)
952     {
953         mSampleAlphaToOne = enabled;
954         mDirtyBits.set(state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
955     }
956 }
957 
setMultisampling(bool enabled)958 void PrivateState::setMultisampling(bool enabled)
959 {
960     if (mMultiSampling != enabled)
961     {
962         mMultiSampling = enabled;
963         mDirtyBits.set(state::DIRTY_BIT_MULTISAMPLING);
964     }
965 }
966 
setSampleShading(bool enabled)967 void PrivateState::setSampleShading(bool enabled)
968 {
969     if (mIsSampleShadingEnabled != enabled)
970     {
971         mIsSampleShadingEnabled = enabled;
972         mMinSampleShading       = (enabled) ? 1.0f : mMinSampleShading;
973         mDirtyBits.set(state::DIRTY_BIT_SAMPLE_SHADING);
974     }
975 }
976 
setMinSampleShading(float value)977 void PrivateState::setMinSampleShading(float value)
978 {
979     value = gl::clamp01(value);
980 
981     if (mMinSampleShading != value)
982     {
983         mMinSampleShading = value;
984         mDirtyBits.set(state::DIRTY_BIT_SAMPLE_SHADING);
985     }
986 }
987 
setScissorTest(bool enabled)988 void PrivateState::setScissorTest(bool enabled)
989 {
990     if (mScissorTest != enabled)
991     {
992         mScissorTest = enabled;
993         mDirtyBits.set(state::DIRTY_BIT_SCISSOR_TEST_ENABLED);
994     }
995 }
996 
setScissorParams(GLint x,GLint y,GLsizei width,GLsizei height)997 void PrivateState::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
998 {
999     // Skip if same scissor info
1000     if (mScissor.x != x || mScissor.y != y || mScissor.width != width || mScissor.height != height)
1001     {
1002         mScissor.x      = x;
1003         mScissor.y      = y;
1004         mScissor.width  = width;
1005         mScissor.height = height;
1006         mDirtyBits.set(state::DIRTY_BIT_SCISSOR);
1007     }
1008 }
1009 
setDither(bool enabled)1010 void PrivateState::setDither(bool enabled)
1011 {
1012     if (mRasterizer.dither != enabled)
1013     {
1014         mRasterizer.dither = enabled;
1015         mDirtyBits.set(state::DIRTY_BIT_DITHER_ENABLED);
1016     }
1017 }
1018 
setViewportParams(GLint x,GLint y,GLsizei width,GLsizei height)1019 void PrivateState::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
1020 {
1021     // [OpenGL ES 2.0.25] section 2.12.1 page 45:
1022     // Viewport width and height are clamped to implementation-dependent maximums when specified.
1023     width  = std::min(width, mCaps.maxViewportWidth);
1024     height = std::min(height, mCaps.maxViewportHeight);
1025 
1026     // Skip if same viewport info
1027     if (mViewport.x != x || mViewport.y != y || mViewport.width != width ||
1028         mViewport.height != height)
1029     {
1030         mViewport.x      = x;
1031         mViewport.y      = y;
1032         mViewport.width  = width;
1033         mViewport.height = height;
1034         mDirtyBits.set(state::DIRTY_BIT_VIEWPORT);
1035     }
1036 }
1037 
setShadingRate(GLenum rate)1038 void PrivateState::setShadingRate(GLenum rate)
1039 {
1040     mShadingRate = FromGLenum<ShadingRate>(rate);
1041     mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
1042     mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_SHADING_RATE);
1043 }
1044 
setPackAlignment(GLint alignment)1045 void PrivateState::setPackAlignment(GLint alignment)
1046 {
1047     mPack.alignment = alignment;
1048     mDirtyBits.set(state::DIRTY_BIT_PACK_STATE);
1049 }
1050 
setPackReverseRowOrder(bool reverseRowOrder)1051 void PrivateState::setPackReverseRowOrder(bool reverseRowOrder)
1052 {
1053     mPack.reverseRowOrder = reverseRowOrder;
1054     mDirtyBits.set(state::DIRTY_BIT_PACK_STATE);
1055 }
1056 
setPackRowLength(GLint rowLength)1057 void PrivateState::setPackRowLength(GLint rowLength)
1058 {
1059     mPack.rowLength = rowLength;
1060     mDirtyBits.set(state::DIRTY_BIT_PACK_STATE);
1061 }
1062 
setPackSkipRows(GLint skipRows)1063 void PrivateState::setPackSkipRows(GLint skipRows)
1064 {
1065     mPack.skipRows = skipRows;
1066     mDirtyBits.set(state::DIRTY_BIT_PACK_STATE);
1067 }
1068 
setPackSkipPixels(GLint skipPixels)1069 void PrivateState::setPackSkipPixels(GLint skipPixels)
1070 {
1071     mPack.skipPixels = skipPixels;
1072     mDirtyBits.set(state::DIRTY_BIT_PACK_STATE);
1073 }
1074 
setUnpackAlignment(GLint alignment)1075 void PrivateState::setUnpackAlignment(GLint alignment)
1076 {
1077     mUnpack.alignment = alignment;
1078     mDirtyBits.set(state::DIRTY_BIT_UNPACK_STATE);
1079 }
1080 
setUnpackRowLength(GLint rowLength)1081 void PrivateState::setUnpackRowLength(GLint rowLength)
1082 {
1083     mUnpack.rowLength = rowLength;
1084     mDirtyBits.set(state::DIRTY_BIT_UNPACK_STATE);
1085 }
1086 
setUnpackImageHeight(GLint imageHeight)1087 void PrivateState::setUnpackImageHeight(GLint imageHeight)
1088 {
1089     mUnpack.imageHeight = imageHeight;
1090     mDirtyBits.set(state::DIRTY_BIT_UNPACK_STATE);
1091 }
1092 
setUnpackSkipImages(GLint skipImages)1093 void PrivateState::setUnpackSkipImages(GLint skipImages)
1094 {
1095     mUnpack.skipImages = skipImages;
1096     mDirtyBits.set(state::DIRTY_BIT_UNPACK_STATE);
1097 }
1098 
setUnpackSkipRows(GLint skipRows)1099 void PrivateState::setUnpackSkipRows(GLint skipRows)
1100 {
1101     mUnpack.skipRows = skipRows;
1102     mDirtyBits.set(state::DIRTY_BIT_UNPACK_STATE);
1103 }
1104 
setUnpackSkipPixels(GLint skipPixels)1105 void PrivateState::setUnpackSkipPixels(GLint skipPixels)
1106 {
1107     mUnpack.skipPixels = skipPixels;
1108     mDirtyBits.set(state::DIRTY_BIT_UNPACK_STATE);
1109 }
1110 
setCoverageModulation(GLenum components)1111 void PrivateState::setCoverageModulation(GLenum components)
1112 {
1113     if (mCoverageModulation != components)
1114     {
1115         mCoverageModulation = components;
1116         mDirtyBits.set(state::DIRTY_BIT_COVERAGE_MODULATION);
1117     }
1118 }
1119 
setFramebufferSRGB(bool sRGB)1120 void PrivateState::setFramebufferSRGB(bool sRGB)
1121 {
1122     if (mFramebufferSRGB != sRGB)
1123     {
1124         mFramebufferSRGB = sRGB;
1125         mDirtyBits.set(state::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE);
1126         mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
1127         mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS);
1128     }
1129 }
1130 
setPatchVertices(GLuint value)1131 void PrivateState::setPatchVertices(GLuint value)
1132 {
1133     if (mPatchVertices != value)
1134     {
1135         mPatchVertices = value;
1136         mDirtyBits.set(state::DIRTY_BIT_PATCH_VERTICES);
1137     }
1138 }
1139 
setPixelLocalStorageActivePlanes(GLsizei n)1140 void PrivateState::setPixelLocalStorageActivePlanes(GLsizei n)
1141 {
1142     mPixelLocalStorageActivePlanes = n;
1143 }
1144 
setLineWidth(GLfloat width)1145 void PrivateState::setLineWidth(GLfloat width)
1146 {
1147     mLineWidth = width;
1148     mDirtyBits.set(state::DIRTY_BIT_LINE_WIDTH);
1149 }
1150 
setGenerateMipmapHint(GLenum hint)1151 void PrivateState::setGenerateMipmapHint(GLenum hint)
1152 {
1153     mGenerateMipmapHint = hint;
1154     mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
1155     mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_MIPMAP_GENERATION_HINT);
1156 }
1157 
setFragmentShaderDerivativeHint(GLenum hint)1158 void PrivateState::setFragmentShaderDerivativeHint(GLenum hint)
1159 {
1160     mFragmentShaderDerivativeHint = hint;
1161     mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
1162     mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT);
1163     // Note: This hint could be propagated to shader translator so we can write ddx, ddx_coarse, or
1164     // ddx_fine depending on the hint.  Ignore for now. It is valid for implementations to ignore
1165     // the hint.
1166 }
1167 
setActiveSampler(unsigned int active)1168 void PrivateState::setActiveSampler(unsigned int active)
1169 {
1170     mActiveSampler = active;
1171 }
1172 
getAndResetDirtyCurrentValues() const1173 AttributesMask PrivateState::getAndResetDirtyCurrentValues() const
1174 {
1175     AttributesMask retVal = mDirtyCurrentValues;
1176     mDirtyCurrentValues.reset();
1177     return retVal;
1178 }
1179 
setClipDistanceEnable(int idx,bool enable)1180 void PrivateState::setClipDistanceEnable(int idx, bool enable)
1181 {
1182     if (enable)
1183     {
1184         mClipDistancesEnabled.set(idx);
1185     }
1186     else
1187     {
1188         mClipDistancesEnabled.reset(idx);
1189     }
1190 
1191     mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
1192     mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES);
1193 }
1194 
setBoundingBox(GLfloat minX,GLfloat minY,GLfloat minZ,GLfloat minW,GLfloat maxX,GLfloat maxY,GLfloat maxZ,GLfloat maxW)1195 void PrivateState::setBoundingBox(GLfloat minX,
1196                                   GLfloat minY,
1197                                   GLfloat minZ,
1198                                   GLfloat minW,
1199                                   GLfloat maxX,
1200                                   GLfloat maxY,
1201                                   GLfloat maxZ,
1202                                   GLfloat maxW)
1203 {
1204     mBoundingBoxMinX = minX;
1205     mBoundingBoxMinY = minY;
1206     mBoundingBoxMinZ = minZ;
1207     mBoundingBoxMinW = minW;
1208     mBoundingBoxMaxX = maxX;
1209     mBoundingBoxMaxY = maxY;
1210     mBoundingBoxMaxZ = maxZ;
1211     mBoundingBoxMaxW = maxW;
1212 }
1213 
setLogicOpEnabled(bool enabled)1214 void PrivateState::setLogicOpEnabled(bool enabled)
1215 {
1216     if (mLogicOpEnabled != enabled)
1217     {
1218         mLogicOpEnabled = enabled;
1219         mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
1220         mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED);
1221     }
1222 }
1223 
setLogicOp(LogicalOperation opcode)1224 void PrivateState::setLogicOp(LogicalOperation opcode)
1225 {
1226     if (mLogicOp != opcode)
1227     {
1228         mLogicOp = opcode;
1229         mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
1230         mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_LOGIC_OP);
1231     }
1232 }
1233 
setVertexAttribf(GLuint index,const GLfloat values[4])1234 void PrivateState::setVertexAttribf(GLuint index, const GLfloat values[4])
1235 {
1236     ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
1237     mVertexAttribCurrentValues[index].setFloatValues(values);
1238     mDirtyBits.set(state::DIRTY_BIT_CURRENT_VALUES);
1239     mDirtyCurrentValues.set(index);
1240     SetComponentTypeMask(ComponentType::Float, index, &mCurrentValuesTypeMask);
1241 }
1242 
setVertexAttribu(GLuint index,const GLuint values[4])1243 void PrivateState::setVertexAttribu(GLuint index, const GLuint values[4])
1244 {
1245     ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
1246     mVertexAttribCurrentValues[index].setUnsignedIntValues(values);
1247     mDirtyBits.set(state::DIRTY_BIT_CURRENT_VALUES);
1248     mDirtyCurrentValues.set(index);
1249     SetComponentTypeMask(ComponentType::UnsignedInt, index, &mCurrentValuesTypeMask);
1250 }
1251 
setVertexAttribi(GLuint index,const GLint values[4])1252 void PrivateState::setVertexAttribi(GLuint index, const GLint values[4])
1253 {
1254     ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
1255     mVertexAttribCurrentValues[index].setIntValues(values);
1256     mDirtyBits.set(state::DIRTY_BIT_CURRENT_VALUES);
1257     mDirtyCurrentValues.set(index);
1258     SetComponentTypeMask(ComponentType::Int, index, &mCurrentValuesTypeMask);
1259 }
1260 
setEnableFeature(GLenum feature,bool enabled)1261 void PrivateState::setEnableFeature(GLenum feature, bool enabled)
1262 {
1263     switch (feature)
1264     {
1265         case GL_MULTISAMPLE_EXT:
1266             setMultisampling(enabled);
1267             return;
1268         case GL_SAMPLE_ALPHA_TO_ONE_EXT:
1269             setSampleAlphaToOne(enabled);
1270             return;
1271         case GL_CULL_FACE:
1272             setCullFace(enabled);
1273             return;
1274         case GL_POLYGON_OFFSET_POINT_NV:
1275             setPolygonOffsetPoint(enabled);
1276             return;
1277         case GL_POLYGON_OFFSET_LINE_NV:
1278             setPolygonOffsetLine(enabled);
1279             return;
1280         case GL_POLYGON_OFFSET_FILL:
1281             setPolygonOffsetFill(enabled);
1282             return;
1283         case GL_DEPTH_CLAMP_EXT:
1284             setDepthClamp(enabled);
1285             return;
1286         case GL_SAMPLE_ALPHA_TO_COVERAGE:
1287             setSampleAlphaToCoverage(enabled);
1288             return;
1289         case GL_SAMPLE_COVERAGE:
1290             setSampleCoverage(enabled);
1291             return;
1292         case GL_SCISSOR_TEST:
1293             setScissorTest(enabled);
1294             return;
1295         case GL_STENCIL_TEST:
1296             setStencilTest(enabled);
1297             return;
1298         case GL_DEPTH_TEST:
1299             setDepthTest(enabled);
1300             return;
1301         case GL_BLEND:
1302             setBlend(enabled);
1303             return;
1304         case GL_DITHER:
1305             setDither(enabled);
1306             return;
1307         case GL_COLOR_LOGIC_OP:
1308             if (mClientVersion.major == 1)
1309             {
1310                 // Handle logicOp in GLES1 through the GLES1 state management and emulation.
1311                 // Otherwise this state could be set as part of ANGLE_logic_op.
1312                 break;
1313             }
1314             setLogicOpEnabled(enabled);
1315             return;
1316         case GL_PRIMITIVE_RESTART_FIXED_INDEX:
1317             setPrimitiveRestart(enabled);
1318             return;
1319         case GL_RASTERIZER_DISCARD:
1320             setRasterizerDiscard(enabled);
1321             return;
1322         case GL_SAMPLE_MASK:
1323             setSampleMaskEnabled(enabled);
1324             return;
1325         case GL_DEBUG_OUTPUT_SYNCHRONOUS:
1326             mDebug.setOutputSynchronous(enabled);
1327             return;
1328         case GL_DEBUG_OUTPUT:
1329             mDebug.setOutputEnabled(enabled);
1330             return;
1331         case GL_FRAMEBUFFER_SRGB_EXT:
1332             setFramebufferSRGB(enabled);
1333             return;
1334         case GL_TEXTURE_RECTANGLE_ANGLE:
1335             mTextureRectangleEnabled = enabled;
1336             return;
1337         case GL_SAMPLE_SHADING:
1338             setSampleShading(enabled);
1339             return;
1340         // GL_APPLE_clip_distance / GL_EXT_clip_cull_distance / GL_ANGLE_clip_cull_distance
1341         case GL_CLIP_DISTANCE0_EXT:
1342         case GL_CLIP_DISTANCE1_EXT:
1343         case GL_CLIP_DISTANCE2_EXT:
1344         case GL_CLIP_DISTANCE3_EXT:
1345         case GL_CLIP_DISTANCE4_EXT:
1346         case GL_CLIP_DISTANCE5_EXT:
1347         case GL_CLIP_DISTANCE6_EXT:
1348         case GL_CLIP_DISTANCE7_EXT:
1349             // NOTE(hqle): These enums are conflicted with GLES1's enums, need
1350             // to do additional check here:
1351             if (mClientVersion.major >= 2)
1352             {
1353                 setClipDistanceEnable(feature - GL_CLIP_DISTANCE0_EXT, enabled);
1354                 return;
1355             }
1356             break;
1357         case GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM:
1358             mShadingRatePreserveAspectRatio = enabled;
1359             return;
1360         case GL_FETCH_PER_SAMPLE_ARM:
1361             mFetchPerSample = enabled;
1362             return;
1363         default:
1364             break;
1365     }
1366 
1367     ASSERT(mClientVersion.major == 1);
1368 
1369     // GLES1 emulation. Need to separate from main switch due to conflict enum between
1370     // GL_CLIP_DISTANCE0_EXT & GL_CLIP_PLANE0
1371     switch (feature)
1372     {
1373         case GL_ALPHA_TEST:
1374             mGLES1State.mAlphaTestEnabled = enabled;
1375             break;
1376         case GL_TEXTURE_2D:
1377             mGLES1State.setTextureEnabled(mActiveSampler, TextureType::_2D, enabled);
1378             break;
1379         case GL_TEXTURE_CUBE_MAP:
1380             mGLES1State.setTextureEnabled(mActiveSampler, TextureType::CubeMap, enabled);
1381             break;
1382         case GL_LIGHTING:
1383             mGLES1State.mLightingEnabled = enabled;
1384             break;
1385         case GL_LIGHT0:
1386         case GL_LIGHT1:
1387         case GL_LIGHT2:
1388         case GL_LIGHT3:
1389         case GL_LIGHT4:
1390         case GL_LIGHT5:
1391         case GL_LIGHT6:
1392         case GL_LIGHT7:
1393             mGLES1State.mLights[feature - GL_LIGHT0].enabled = enabled;
1394             break;
1395         case GL_NORMALIZE:
1396             mGLES1State.mNormalizeEnabled = enabled;
1397             break;
1398         case GL_RESCALE_NORMAL:
1399             mGLES1State.mRescaleNormalEnabled = enabled;
1400             break;
1401         case GL_COLOR_MATERIAL:
1402             mGLES1State.mColorMaterialEnabled = enabled;
1403             break;
1404         case GL_CLIP_PLANE0:
1405         case GL_CLIP_PLANE1:
1406         case GL_CLIP_PLANE2:
1407         case GL_CLIP_PLANE3:
1408         case GL_CLIP_PLANE4:
1409         case GL_CLIP_PLANE5:
1410             mGLES1State.mClipPlanes[feature - GL_CLIP_PLANE0].enabled = enabled;
1411             break;
1412         case GL_FOG:
1413             mGLES1State.mFogEnabled = enabled;
1414             break;
1415         case GL_POINT_SMOOTH:
1416             mGLES1State.mPointSmoothEnabled = enabled;
1417             break;
1418         case GL_LINE_SMOOTH:
1419             mGLES1State.mLineSmoothEnabled = enabled;
1420             break;
1421         case GL_POINT_SPRITE_OES:
1422             mGLES1State.mPointSpriteEnabled = enabled;
1423             break;
1424         case GL_COLOR_LOGIC_OP:
1425             mGLES1State.setLogicOpEnabled(enabled);
1426             break;
1427         default:
1428             UNREACHABLE();
1429     }
1430 }
1431 
setEnableFeatureIndexed(GLenum feature,bool enabled,GLuint index)1432 void PrivateState::setEnableFeatureIndexed(GLenum feature, bool enabled, GLuint index)
1433 {
1434     switch (feature)
1435     {
1436         case GL_BLEND:
1437             setBlendIndexed(enabled, index);
1438             break;
1439         default:
1440             UNREACHABLE();
1441     }
1442 }
1443 
getEnableFeature(GLenum feature) const1444 bool PrivateState::getEnableFeature(GLenum feature) const
1445 {
1446     switch (feature)
1447     {
1448         case GL_MULTISAMPLE_EXT:
1449             return isMultisamplingEnabled();
1450         case GL_SAMPLE_ALPHA_TO_ONE_EXT:
1451             return isSampleAlphaToOneEnabled();
1452         case GL_CULL_FACE:
1453             return isCullFaceEnabled();
1454         case GL_POLYGON_OFFSET_POINT_NV:
1455             return isPolygonOffsetPointEnabled();
1456         case GL_POLYGON_OFFSET_LINE_NV:
1457             return isPolygonOffsetLineEnabled();
1458         case GL_POLYGON_OFFSET_FILL:
1459             return isPolygonOffsetFillEnabled();
1460         case GL_DEPTH_CLAMP_EXT:
1461             return isDepthClampEnabled();
1462         case GL_SAMPLE_ALPHA_TO_COVERAGE:
1463             return isSampleAlphaToCoverageEnabled();
1464         case GL_SAMPLE_COVERAGE:
1465             return isSampleCoverageEnabled();
1466         case GL_SCISSOR_TEST:
1467             return isScissorTestEnabled();
1468         case GL_STENCIL_TEST:
1469             return isStencilTestEnabled();
1470         case GL_DEPTH_TEST:
1471             return isDepthTestEnabled();
1472         case GL_BLEND:
1473             return isBlendEnabled();
1474         case GL_DITHER:
1475             return isDitherEnabled();
1476         case GL_COLOR_LOGIC_OP:
1477             if (mClientVersion.major == 1)
1478             {
1479                 // Handle logicOp in GLES1 through the GLES1 state management and emulation.
1480                 break;
1481             }
1482             return isLogicOpEnabled();
1483         case GL_PRIMITIVE_RESTART_FIXED_INDEX:
1484             return isPrimitiveRestartEnabled();
1485         case GL_RASTERIZER_DISCARD:
1486             return isRasterizerDiscardEnabled();
1487         case GL_SAMPLE_MASK:
1488             return isSampleMaskEnabled();
1489         case GL_DEBUG_OUTPUT_SYNCHRONOUS:
1490             return mDebug.isOutputSynchronous();
1491         case GL_DEBUG_OUTPUT:
1492             return mDebug.isOutputEnabled();
1493         case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
1494             return isBindGeneratesResourceEnabled();
1495         case GL_CLIENT_ARRAYS_ANGLE:
1496             return areClientArraysEnabled();
1497         case GL_FRAMEBUFFER_SRGB_EXT:
1498             return getFramebufferSRGB();
1499         case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1500             return mRobustResourceInit;
1501         case GL_PROGRAM_CACHE_ENABLED_ANGLE:
1502             return mProgramBinaryCacheEnabled;
1503         case GL_TEXTURE_RECTANGLE_ANGLE:
1504             return mTextureRectangleEnabled;
1505         case GL_SAMPLE_SHADING:
1506             return isSampleShadingEnabled();
1507         // GL_APPLE_clip_distance / GL_EXT_clip_cull_distance / GL_ANGLE_clip_cull_distance
1508         case GL_CLIP_DISTANCE0_EXT:
1509         case GL_CLIP_DISTANCE1_EXT:
1510         case GL_CLIP_DISTANCE2_EXT:
1511         case GL_CLIP_DISTANCE3_EXT:
1512         case GL_CLIP_DISTANCE4_EXT:
1513         case GL_CLIP_DISTANCE5_EXT:
1514         case GL_CLIP_DISTANCE6_EXT:
1515         case GL_CLIP_DISTANCE7_EXT:
1516             if (mClientVersion.major >= 2)
1517             {
1518                 // If GLES version is 1, the GL_CLIP_DISTANCE0_EXT enum will be used as
1519                 // GL_CLIP_PLANE0 instead.
1520                 return mClipDistancesEnabled.test(feature - GL_CLIP_DISTANCE0_EXT);
1521             }
1522             break;
1523         case GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM:
1524             return mShadingRatePreserveAspectRatio;
1525         case GL_FETCH_PER_SAMPLE_ARM:
1526             return mFetchPerSample;
1527     }
1528 
1529     ASSERT(mClientVersion.major == 1);
1530 
1531     switch (feature)
1532     {
1533         // GLES1 emulation
1534         case GL_ALPHA_TEST:
1535             return mGLES1State.mAlphaTestEnabled;
1536         case GL_VERTEX_ARRAY:
1537             return mGLES1State.mVertexArrayEnabled;
1538         case GL_NORMAL_ARRAY:
1539             return mGLES1State.mNormalArrayEnabled;
1540         case GL_COLOR_ARRAY:
1541             return mGLES1State.mColorArrayEnabled;
1542         case GL_POINT_SIZE_ARRAY_OES:
1543             return mGLES1State.mPointSizeArrayEnabled;
1544         case GL_TEXTURE_COORD_ARRAY:
1545             return mGLES1State.mTexCoordArrayEnabled[mGLES1State.mClientActiveTexture];
1546         case GL_TEXTURE_2D:
1547             return mGLES1State.isTextureTargetEnabled(getActiveSampler(), TextureType::_2D);
1548         case GL_TEXTURE_CUBE_MAP:
1549             return mGLES1State.isTextureTargetEnabled(getActiveSampler(), TextureType::CubeMap);
1550         case GL_LIGHTING:
1551             return mGLES1State.mLightingEnabled;
1552         case GL_LIGHT0:
1553         case GL_LIGHT1:
1554         case GL_LIGHT2:
1555         case GL_LIGHT3:
1556         case GL_LIGHT4:
1557         case GL_LIGHT5:
1558         case GL_LIGHT6:
1559         case GL_LIGHT7:
1560             return mGLES1State.mLights[feature - GL_LIGHT0].enabled;
1561         case GL_NORMALIZE:
1562             return mGLES1State.mNormalizeEnabled;
1563         case GL_RESCALE_NORMAL:
1564             return mGLES1State.mRescaleNormalEnabled;
1565         case GL_COLOR_MATERIAL:
1566             return mGLES1State.mColorMaterialEnabled;
1567         case GL_CLIP_PLANE0:
1568         case GL_CLIP_PLANE1:
1569         case GL_CLIP_PLANE2:
1570         case GL_CLIP_PLANE3:
1571         case GL_CLIP_PLANE4:
1572         case GL_CLIP_PLANE5:
1573             return mGLES1State.mClipPlanes[feature - GL_CLIP_PLANE0].enabled;
1574         case GL_FOG:
1575             return mGLES1State.mFogEnabled;
1576         case GL_POINT_SMOOTH:
1577             return mGLES1State.mPointSmoothEnabled;
1578         case GL_LINE_SMOOTH:
1579             return mGLES1State.mLineSmoothEnabled;
1580         case GL_POINT_SPRITE_OES:
1581             return mGLES1State.mPointSpriteEnabled;
1582         case GL_COLOR_LOGIC_OP:
1583             return mGLES1State.mLogicOpEnabled;
1584         default:
1585             UNREACHABLE();
1586             return false;
1587     }
1588 }
1589 
getEnableFeatureIndexed(GLenum feature,GLuint index) const1590 bool PrivateState::getEnableFeatureIndexed(GLenum feature, GLuint index) const
1591 {
1592     switch (feature)
1593     {
1594         case GL_BLEND:
1595             return isBlendEnabledIndexed(index);
1596         default:
1597             UNREACHABLE();
1598             return false;
1599     }
1600 }
1601 
getBooleanv(GLenum pname,GLboolean * params) const1602 void PrivateState::getBooleanv(GLenum pname, GLboolean *params) const
1603 {
1604     switch (pname)
1605     {
1606         case GL_SAMPLE_COVERAGE_INVERT:
1607             *params = mSampleCoverageInvert;
1608             break;
1609         case GL_DEPTH_WRITEMASK:
1610             *params = mDepthStencil.depthMask;
1611             break;
1612         case GL_COLOR_WRITEMASK:
1613         {
1614             // non-indexed get returns the state of draw buffer zero
1615             bool r, g, b, a;
1616             mBlendStateExt.getColorMaskIndexed(0, &r, &g, &b, &a);
1617             params[0] = r;
1618             params[1] = g;
1619             params[2] = b;
1620             params[3] = a;
1621             break;
1622         }
1623         case GL_CULL_FACE:
1624             *params = mRasterizer.cullFace;
1625             break;
1626         case GL_POLYGON_OFFSET_POINT_NV:
1627             *params = mRasterizer.polygonOffsetPoint;
1628             break;
1629         case GL_POLYGON_OFFSET_LINE_NV:
1630             *params = mRasterizer.polygonOffsetLine;
1631             break;
1632         case GL_POLYGON_OFFSET_FILL:
1633             *params = mRasterizer.polygonOffsetFill;
1634             break;
1635         case GL_DEPTH_CLAMP_EXT:
1636             *params = mRasterizer.depthClamp;
1637             break;
1638         case GL_SAMPLE_ALPHA_TO_COVERAGE:
1639             *params = mSampleAlphaToCoverage;
1640             break;
1641         case GL_SAMPLE_COVERAGE:
1642             *params = mSampleCoverage;
1643             break;
1644         case GL_SAMPLE_MASK:
1645             *params = mSampleMask;
1646             break;
1647         case GL_SCISSOR_TEST:
1648             *params = mScissorTest;
1649             break;
1650         case GL_STENCIL_TEST:
1651             *params = mDepthStencil.stencilTest;
1652             break;
1653         case GL_DEPTH_TEST:
1654             *params = mDepthStencil.depthTest;
1655             break;
1656         case GL_BLEND:
1657             // non-indexed get returns the state of draw buffer zero
1658             *params = mBlendStateExt.getEnabledMask().test(0);
1659             break;
1660         case GL_DITHER:
1661             *params = mRasterizer.dither;
1662             break;
1663         case GL_COLOR_LOGIC_OP:
1664             if (mClientVersion.major == 1)
1665             {
1666                 // Handle logicOp in GLES1 through the GLES1 state management.
1667                 *params = getEnableFeature(pname);
1668             }
1669             else
1670             {
1671                 *params = mLogicOpEnabled;
1672             }
1673             break;
1674         case GL_PRIMITIVE_RESTART_FIXED_INDEX:
1675             *params = mPrimitiveRestart;
1676             break;
1677         case GL_RASTERIZER_DISCARD:
1678             *params = isRasterizerDiscardEnabled() ? GL_TRUE : GL_FALSE;
1679             break;
1680         case GL_DEBUG_OUTPUT_SYNCHRONOUS:
1681             *params = mDebug.isOutputSynchronous() ? GL_TRUE : GL_FALSE;
1682             break;
1683         case GL_DEBUG_OUTPUT:
1684             *params = mDebug.isOutputEnabled() ? GL_TRUE : GL_FALSE;
1685             break;
1686         case GL_MULTISAMPLE_EXT:
1687             *params = mMultiSampling;
1688             break;
1689         case GL_SAMPLE_ALPHA_TO_ONE_EXT:
1690             *params = mSampleAlphaToOne;
1691             break;
1692         case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
1693             *params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE;
1694             break;
1695         case GL_CLIENT_ARRAYS_ANGLE:
1696             *params = areClientArraysEnabled() ? GL_TRUE : GL_FALSE;
1697             break;
1698         case GL_FRAMEBUFFER_SRGB_EXT:
1699             *params = getFramebufferSRGB() ? GL_TRUE : GL_FALSE;
1700             break;
1701         case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1702             *params = mRobustResourceInit ? GL_TRUE : GL_FALSE;
1703             break;
1704         case GL_PROGRAM_CACHE_ENABLED_ANGLE:
1705             *params = mProgramBinaryCacheEnabled ? GL_TRUE : GL_FALSE;
1706             break;
1707         case GL_TEXTURE_RECTANGLE_ANGLE:
1708             *params = mTextureRectangleEnabled ? GL_TRUE : GL_FALSE;
1709             break;
1710         case GL_LIGHT_MODEL_TWO_SIDE:
1711             *params = IsLightModelTwoSided(&mGLES1State);
1712             break;
1713         case GL_SAMPLE_SHADING:
1714             *params = mIsSampleShadingEnabled;
1715             break;
1716         case GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED:
1717             *params = isPrimitiveRestartEnabled() && getExtensions().tessellationShaderAny();
1718             break;
1719         case GL_ROBUST_FRAGMENT_SHADER_OUTPUT_ANGLE:
1720             *params = mExtensions.robustFragmentShaderOutputANGLE ? GL_TRUE : GL_FALSE;
1721             break;
1722         // GL_APPLE_clip_distance / GL_EXT_clip_cull_distance / GL_ANGLE_clip_cull_distance
1723         case GL_CLIP_DISTANCE0_EXT:
1724         case GL_CLIP_DISTANCE1_EXT:
1725         case GL_CLIP_DISTANCE2_EXT:
1726         case GL_CLIP_DISTANCE3_EXT:
1727         case GL_CLIP_DISTANCE4_EXT:
1728         case GL_CLIP_DISTANCE5_EXT:
1729         case GL_CLIP_DISTANCE6_EXT:
1730         case GL_CLIP_DISTANCE7_EXT:
1731             if (mClientVersion.major >= 2)
1732             {
1733                 // If GLES version is 1, the GL_CLIP_DISTANCE0_EXT enum will be used as
1734                 // GL_CLIP_PLANE0 instead.
1735                 *params = mClipDistancesEnabled.test(pname - GL_CLIP_DISTANCE0_EXT);
1736             }
1737             break;
1738         // GL_ARM_shader_framebuffer_fetch
1739         case GL_FETCH_PER_SAMPLE_ARM:
1740             *params = mFetchPerSample;
1741             break;
1742         // GL_ARM_shader_framebuffer_fetch
1743         case GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM:
1744             *params = mCaps.fragmentShaderFramebufferFetchMRT;
1745             break;
1746         default:
1747             if (mClientVersion.major == 1)
1748             {
1749                 *params = getEnableFeature(pname);
1750             }
1751             else
1752             {
1753                 UNREACHABLE();
1754             }
1755             break;
1756     }
1757 }
1758 
getFloatv(GLenum pname,GLfloat * params) const1759 void PrivateState::getFloatv(GLenum pname, GLfloat *params) const
1760 {
1761     switch (pname)
1762     {
1763         case GL_LINE_WIDTH:
1764             *params = mLineWidth;
1765             break;
1766         case GL_SAMPLE_COVERAGE_VALUE:
1767             *params = mSampleCoverageValue;
1768             break;
1769         case GL_DEPTH_CLEAR_VALUE:
1770             *params = mDepthClearValue;
1771             break;
1772         case GL_POLYGON_OFFSET_FACTOR:
1773             *params = mRasterizer.polygonOffsetFactor;
1774             break;
1775         case GL_POLYGON_OFFSET_UNITS:
1776             *params = mRasterizer.polygonOffsetUnits;
1777             break;
1778         case GL_POLYGON_OFFSET_CLAMP_EXT:
1779             *params = mRasterizer.polygonOffsetClamp;
1780             break;
1781         case GL_DEPTH_RANGE:
1782             params[0] = mNearZ;
1783             params[1] = mFarZ;
1784             break;
1785         case GL_COLOR_CLEAR_VALUE:
1786             params[0] = mColorClearValue.red;
1787             params[1] = mColorClearValue.green;
1788             params[2] = mColorClearValue.blue;
1789             params[3] = mColorClearValue.alpha;
1790             break;
1791         case GL_BLEND_COLOR:
1792             params[0] = mBlendColor.red;
1793             params[1] = mBlendColor.green;
1794             params[2] = mBlendColor.blue;
1795             params[3] = mBlendColor.alpha;
1796             break;
1797         case GL_MULTISAMPLE_EXT:
1798             *params = static_cast<GLfloat>(mMultiSampling);
1799             break;
1800         case GL_SAMPLE_ALPHA_TO_ONE_EXT:
1801             *params = static_cast<GLfloat>(mSampleAlphaToOne);
1802             break;
1803         case GL_COVERAGE_MODULATION_CHROMIUM:
1804             params[0] = static_cast<GLfloat>(mCoverageModulation);
1805             break;
1806         case GL_ALPHA_TEST_REF:
1807             *params = mGLES1State.mAlphaTestParameters.ref;
1808             break;
1809         case GL_CURRENT_COLOR:
1810         {
1811             const auto &color = mGLES1State.mCurrentColor;
1812             params[0]         = color.red;
1813             params[1]         = color.green;
1814             params[2]         = color.blue;
1815             params[3]         = color.alpha;
1816             break;
1817         }
1818         case GL_CURRENT_NORMAL:
1819         {
1820             const auto &normal = mGLES1State.mCurrentNormal;
1821             params[0]          = normal[0];
1822             params[1]          = normal[1];
1823             params[2]          = normal[2];
1824             break;
1825         }
1826         case GL_CURRENT_TEXTURE_COORDS:
1827         {
1828             const auto &texcoord = mGLES1State.mCurrentTextureCoords[mActiveSampler];
1829             params[0]            = texcoord.s;
1830             params[1]            = texcoord.t;
1831             params[2]            = texcoord.r;
1832             params[3]            = texcoord.q;
1833             break;
1834         }
1835         case GL_MODELVIEW_MATRIX:
1836             memcpy(params, mGLES1State.mModelviewMatrices.back().constData(), 16 * sizeof(GLfloat));
1837             break;
1838         case GL_PROJECTION_MATRIX:
1839             memcpy(params, mGLES1State.mProjectionMatrices.back().constData(),
1840                    16 * sizeof(GLfloat));
1841             break;
1842         case GL_TEXTURE_MATRIX:
1843             memcpy(params, mGLES1State.mTextureMatrices[mActiveSampler].back().constData(),
1844                    16 * sizeof(GLfloat));
1845             break;
1846         case GL_LIGHT_MODEL_AMBIENT:
1847             GetLightModelParameters(&mGLES1State, pname, params);
1848             break;
1849         case GL_FOG_MODE:
1850         case GL_FOG_DENSITY:
1851         case GL_FOG_START:
1852         case GL_FOG_END:
1853         case GL_FOG_COLOR:
1854             GetFogParameters(&mGLES1State, pname, params);
1855             break;
1856         case GL_POINT_SIZE:
1857             GetPointSize(&mGLES1State, params);
1858             break;
1859         case GL_POINT_SIZE_MIN:
1860         case GL_POINT_SIZE_MAX:
1861         case GL_POINT_FADE_THRESHOLD_SIZE:
1862         case GL_POINT_DISTANCE_ATTENUATION:
1863             GetPointParameter(&mGLES1State, FromGLenum<PointParameter>(pname), params);
1864             break;
1865         case GL_MIN_SAMPLE_SHADING_VALUE:
1866             *params = mMinSampleShading;
1867             break;
1868         // GL_ARM_shader_framebuffer_fetch
1869         case GL_FETCH_PER_SAMPLE_ARM:
1870             *params = mFetchPerSample ? 1.0f : 0.0f;
1871             break;
1872         // GL_ARM_shader_framebuffer_fetch
1873         case GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM:
1874             *params = mCaps.fragmentShaderFramebufferFetchMRT ? 1.0f : 0.0f;
1875             break;
1876         default:
1877             UNREACHABLE();
1878             break;
1879     }
1880 }
1881 
getIntegerv(GLenum pname,GLint * params) const1882 void PrivateState::getIntegerv(GLenum pname, GLint *params) const
1883 {
1884     // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1885     // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1886     // GetIntegerv as its native query function. As it would require conversion in any
1887     // case, this should make no difference to the calling application. You may find it in
1888     // State::getFloatv.
1889     switch (pname)
1890     {
1891         case GL_PACK_ALIGNMENT:
1892             *params = mPack.alignment;
1893             break;
1894         case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
1895             *params = mPack.reverseRowOrder;
1896             break;
1897         case GL_PACK_ROW_LENGTH:
1898             *params = mPack.rowLength;
1899             break;
1900         case GL_PACK_SKIP_ROWS:
1901             *params = mPack.skipRows;
1902             break;
1903         case GL_PACK_SKIP_PIXELS:
1904             *params = mPack.skipPixels;
1905             break;
1906         case GL_UNPACK_ALIGNMENT:
1907             *params = mUnpack.alignment;
1908             break;
1909         case GL_UNPACK_ROW_LENGTH:
1910             *params = mUnpack.rowLength;
1911             break;
1912         case GL_UNPACK_IMAGE_HEIGHT:
1913             *params = mUnpack.imageHeight;
1914             break;
1915         case GL_UNPACK_SKIP_IMAGES:
1916             *params = mUnpack.skipImages;
1917             break;
1918         case GL_UNPACK_SKIP_ROWS:
1919             *params = mUnpack.skipRows;
1920             break;
1921         case GL_UNPACK_SKIP_PIXELS:
1922             *params = mUnpack.skipPixels;
1923             break;
1924         case GL_GENERATE_MIPMAP_HINT:
1925             *params = mGenerateMipmapHint;
1926             break;
1927         case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
1928             *params = mFragmentShaderDerivativeHint;
1929             break;
1930         case GL_ACTIVE_TEXTURE:
1931             *params = (static_cast<GLint>(mActiveSampler) + GL_TEXTURE0);
1932             break;
1933         case GL_STENCIL_FUNC:
1934             *params = mDepthStencil.stencilFunc;
1935             break;
1936         case GL_STENCIL_REF:
1937             *params = mStencilRef;
1938             break;
1939         case GL_STENCIL_VALUE_MASK:
1940             *params = CastMaskValue(mDepthStencil.stencilMask);
1941             break;
1942         case GL_STENCIL_BACK_FUNC:
1943             *params = mDepthStencil.stencilBackFunc;
1944             break;
1945         case GL_STENCIL_BACK_REF:
1946             *params = mStencilBackRef;
1947             break;
1948         case GL_STENCIL_BACK_VALUE_MASK:
1949             *params = CastMaskValue(mDepthStencil.stencilBackMask);
1950             break;
1951         case GL_STENCIL_FAIL:
1952             *params = mDepthStencil.stencilFail;
1953             break;
1954         case GL_STENCIL_PASS_DEPTH_FAIL:
1955             *params = mDepthStencil.stencilPassDepthFail;
1956             break;
1957         case GL_STENCIL_PASS_DEPTH_PASS:
1958             *params = mDepthStencil.stencilPassDepthPass;
1959             break;
1960         case GL_STENCIL_BACK_FAIL:
1961             *params = mDepthStencil.stencilBackFail;
1962             break;
1963         case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1964             *params = mDepthStencil.stencilBackPassDepthFail;
1965             break;
1966         case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1967             *params = mDepthStencil.stencilBackPassDepthPass;
1968             break;
1969         case GL_DEPTH_FUNC:
1970             *params = mDepthStencil.depthFunc;
1971             break;
1972         case GL_BLEND_SRC_RGB:
1973             // non-indexed get returns the state of draw buffer zero
1974             *params = ToGLenum(mBlendStateExt.getSrcColorIndexed(0));
1975             break;
1976         case GL_BLEND_SRC_ALPHA:
1977             *params = ToGLenum(mBlendStateExt.getSrcAlphaIndexed(0));
1978             break;
1979         case GL_BLEND_DST_RGB:
1980             *params = ToGLenum(mBlendStateExt.getDstColorIndexed(0));
1981             break;
1982         case GL_BLEND_DST_ALPHA:
1983             *params = ToGLenum(mBlendStateExt.getDstAlphaIndexed(0));
1984             break;
1985         case GL_BLEND_EQUATION_RGB:
1986             *params = ToGLenum(mBlendStateExt.getEquationColorIndexed(0));
1987             break;
1988         case GL_BLEND_EQUATION_ALPHA:
1989             *params = ToGLenum(mBlendStateExt.getEquationAlphaIndexed(0));
1990             break;
1991         case GL_STENCIL_WRITEMASK:
1992             *params = CastMaskValue(mDepthStencil.stencilWritemask);
1993             break;
1994         case GL_STENCIL_BACK_WRITEMASK:
1995             *params = CastMaskValue(mDepthStencil.stencilBackWritemask);
1996             break;
1997         case GL_STENCIL_CLEAR_VALUE:
1998             *params = mStencilClearValue;
1999             break;
2000         case GL_VIEWPORT:
2001             params[0] = mViewport.x;
2002             params[1] = mViewport.y;
2003             params[2] = mViewport.width;
2004             params[3] = mViewport.height;
2005             break;
2006         case GL_SCISSOR_BOX:
2007             params[0] = mScissor.x;
2008             params[1] = mScissor.y;
2009             params[2] = mScissor.width;
2010             params[3] = mScissor.height;
2011             break;
2012         case GL_POLYGON_MODE_NV:
2013             *params = ToGLenum(mRasterizer.polygonMode);
2014             break;
2015         case GL_CULL_FACE_MODE:
2016             *params = ToGLenum(mRasterizer.cullMode);
2017             break;
2018         case GL_FRONT_FACE:
2019             *params = mRasterizer.frontFace;
2020             break;
2021 
2022         case GL_MULTISAMPLE_EXT:
2023             *params = static_cast<GLint>(mMultiSampling);
2024             break;
2025         case GL_SAMPLE_ALPHA_TO_ONE_EXT:
2026             *params = static_cast<GLint>(mSampleAlphaToOne);
2027             break;
2028         case GL_COVERAGE_MODULATION_CHROMIUM:
2029             *params = static_cast<GLint>(mCoverageModulation);
2030             break;
2031         case GL_ALPHA_TEST_FUNC:
2032             *params = ToGLenum(mGLES1State.mAlphaTestParameters.func);
2033             break;
2034         case GL_CLIENT_ACTIVE_TEXTURE:
2035             *params = mGLES1State.mClientActiveTexture + GL_TEXTURE0;
2036             break;
2037         case GL_MATRIX_MODE:
2038             *params = ToGLenum(mGLES1State.mMatrixMode);
2039             break;
2040         case GL_SHADE_MODEL:
2041             *params = ToGLenum(mGLES1State.mShadeModel);
2042             break;
2043         case GL_MODELVIEW_STACK_DEPTH:
2044         case GL_PROJECTION_STACK_DEPTH:
2045         case GL_TEXTURE_STACK_DEPTH:
2046             *params = mGLES1State.getCurrentMatrixStackDepth(pname);
2047             break;
2048         case GL_LOGIC_OP_MODE:
2049             *params = ToGLenum(mGLES1State.mLogicOp);
2050             break;
2051         case GL_BLEND_SRC:
2052             // non-indexed get returns the state of draw buffer zero
2053             *params = ToGLenum(mBlendStateExt.getSrcColorIndexed(0));
2054             break;
2055         case GL_BLEND_DST:
2056             *params = ToGLenum(mBlendStateExt.getDstColorIndexed(0));
2057             break;
2058         case GL_PERSPECTIVE_CORRECTION_HINT:
2059         case GL_POINT_SMOOTH_HINT:
2060         case GL_LINE_SMOOTH_HINT:
2061         case GL_FOG_HINT:
2062             *params = mGLES1State.getHint(pname);
2063             break;
2064 
2065         // GL_ANGLE_provoking_vertex
2066         case GL_PROVOKING_VERTEX_ANGLE:
2067             *params = ToGLenum(mProvokingVertex);
2068             break;
2069 
2070         case GL_PATCH_VERTICES:
2071             *params = mPatchVertices;
2072             break;
2073 
2074         // GL_EXT_clip_control
2075         case GL_CLIP_ORIGIN_EXT:
2076             *params = ToGLenum(mClipOrigin);
2077             break;
2078         case GL_CLIP_DEPTH_MODE_EXT:
2079             *params = ToGLenum(mClipDepthMode);
2080             break;
2081 
2082         // GL_QCOM_shading_rate
2083         case GL_SHADING_RATE_QCOM:
2084             *params = ToGLenum(mShadingRate);
2085             break;
2086 
2087         // GL_ANGLE_shader_pixel_local_storage
2088         case GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE:
2089             *params = mPixelLocalStorageActivePlanes;
2090             break;
2091 
2092         // GL_ARM_shader_framebuffer_fetch
2093         case GL_FETCH_PER_SAMPLE_ARM:
2094             *params = mFetchPerSample ? 1 : 0;
2095             break;
2096 
2097         // GL_ARM_shader_framebuffer_fetch
2098         case GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM:
2099             *params = mCaps.fragmentShaderFramebufferFetchMRT ? 1 : 0;
2100             break;
2101 
2102         default:
2103             UNREACHABLE();
2104             break;
2105     }
2106 }
2107 
getIntegeri_v(GLenum target,GLuint index,GLint * data) const2108 void PrivateState::getIntegeri_v(GLenum target, GLuint index, GLint *data) const
2109 {
2110     switch (target)
2111     {
2112         case GL_BLEND_SRC_RGB:
2113             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2114             *data = ToGLenum(mBlendStateExt.getSrcColorIndexed(index));
2115             break;
2116         case GL_BLEND_SRC_ALPHA:
2117             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2118             *data = ToGLenum(mBlendStateExt.getSrcAlphaIndexed(index));
2119             break;
2120         case GL_BLEND_DST_RGB:
2121             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2122             *data = ToGLenum(mBlendStateExt.getDstColorIndexed(index));
2123             break;
2124         case GL_BLEND_DST_ALPHA:
2125             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2126             *data = ToGLenum(mBlendStateExt.getDstAlphaIndexed(index));
2127             break;
2128         case GL_BLEND_EQUATION_RGB:
2129             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2130             *data = ToGLenum(mBlendStateExt.getEquationColorIndexed(index));
2131             break;
2132         case GL_BLEND_EQUATION_ALPHA:
2133             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2134             *data = ToGLenum(mBlendStateExt.getEquationAlphaIndexed(index));
2135             break;
2136         case GL_SAMPLE_MASK_VALUE:
2137             ASSERT(static_cast<size_t>(index) < mSampleMaskValues.size());
2138             *data = mSampleMaskValues[index];
2139             break;
2140         default:
2141             UNREACHABLE();
2142             break;
2143     }
2144 }
2145 
getBooleani_v(GLenum target,GLuint index,GLboolean * data) const2146 void PrivateState::getBooleani_v(GLenum target, GLuint index, GLboolean *data) const
2147 {
2148     switch (target)
2149     {
2150         case GL_COLOR_WRITEMASK:
2151         {
2152             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2153             bool r, g, b, a;
2154             mBlendStateExt.getColorMaskIndexed(index, &r, &g, &b, &a);
2155             data[0] = r;
2156             data[1] = g;
2157             data[2] = b;
2158             data[3] = a;
2159             break;
2160         }
2161         default:
2162             UNREACHABLE();
2163             break;
2164     }
2165 }
2166 
State(const State * shareContextState,egl::ShareGroup * shareGroup,TextureManager * shareTextures,SemaphoreManager * shareSemaphores,egl::ContextMutex * contextMutex,const OverlayType * overlay,const EGLenum clientType,const Version & clientVersion,EGLint profileMask,bool debug,bool bindGeneratesResourceCHROMIUM,bool clientArraysEnabled,bool robustResourceInit,bool programBinaryCacheEnabled,EGLenum contextPriority,bool hasRobustAccess,bool hasProtectedContent)2167 State::State(const State *shareContextState,
2168              egl::ShareGroup *shareGroup,
2169              TextureManager *shareTextures,
2170              SemaphoreManager *shareSemaphores,
2171              egl::ContextMutex *contextMutex,
2172              const OverlayType *overlay,
2173              const EGLenum clientType,
2174              const Version &clientVersion,
2175              EGLint profileMask,
2176              bool debug,
2177              bool bindGeneratesResourceCHROMIUM,
2178              bool clientArraysEnabled,
2179              bool robustResourceInit,
2180              bool programBinaryCacheEnabled,
2181              EGLenum contextPriority,
2182              bool hasRobustAccess,
2183              bool hasProtectedContent)
2184     : mID({gIDCounter++}),
2185       mContextPriority(contextPriority),
2186       mHasRobustAccess(hasRobustAccess),
2187       mHasProtectedContent(hasProtectedContent),
2188       mIsDebugContext(debug),
2189       mShareGroup(shareGroup),
2190       mContextMutex(contextMutex),
2191       mBufferManager(AllocateOrGetSharedResourceManager(shareContextState, &State::mBufferManager)),
2192       mShaderProgramManager(
2193           AllocateOrGetSharedResourceManager(shareContextState, &State::mShaderProgramManager)),
2194       mTextureManager(AllocateOrGetSharedResourceManager(shareContextState,
2195                                                          &State::mTextureManager,
2196                                                          shareTextures)),
2197       mRenderbufferManager(
2198           AllocateOrGetSharedResourceManager(shareContextState, &State::mRenderbufferManager)),
2199       mSamplerManager(
2200           AllocateOrGetSharedResourceManager(shareContextState, &State::mSamplerManager)),
2201       mSyncManager(AllocateOrGetSharedResourceManager(shareContextState, &State::mSyncManager)),
2202       mFramebufferManager(new FramebufferManager()),
2203       mProgramPipelineManager(new ProgramPipelineManager()),
2204       mMemoryObjectManager(
2205           AllocateOrGetSharedResourceManager(shareContextState, &State::mMemoryObjectManager)),
2206       mSemaphoreManager(AllocateOrGetSharedResourceManager(shareContextState,
2207                                                            &State::mSemaphoreManager,
2208                                                            shareSemaphores)),
2209       mReadFramebuffer(nullptr),
2210       mDrawFramebuffer(nullptr),
2211       mProgram(nullptr),
2212       mVertexArray(nullptr),
2213       mDisplayTextureShareGroup(shareTextures != nullptr),
2214       mMaxShaderCompilerThreads(std::numeric_limits<GLuint>::max()),
2215       mOverlay(overlay),
2216       mPrivateState(clientType,
2217                     clientVersion,
2218                     profileMask,
2219                     debug,
2220                     bindGeneratesResourceCHROMIUM,
2221                     clientArraysEnabled,
2222                     robustResourceInit,
2223                     programBinaryCacheEnabled)
2224 {}
2225 
~State()2226 State::~State() {}
2227 
initialize(Context * context)2228 void State::initialize(Context *context)
2229 {
2230     const Extensions &nativeExtensions = context->getImplementation()->getNativeExtensions();
2231     const Version &clientVersion       = context->getClientVersion();
2232 
2233     mPrivateState.initialize(context);
2234 
2235     mUniformBuffers.resize(getCaps().maxUniformBufferBindings);
2236 
2237     mSamplerTextures[TextureType::_2D].resize(getCaps().maxCombinedTextureImageUnits);
2238     mSamplerTextures[TextureType::CubeMap].resize(getCaps().maxCombinedTextureImageUnits);
2239     if (clientVersion >= Version(3, 0) || nativeExtensions.texture3DOES)
2240     {
2241         mSamplerTextures[TextureType::_3D].resize(getCaps().maxCombinedTextureImageUnits);
2242     }
2243     if (clientVersion >= Version(3, 0))
2244     {
2245         mSamplerTextures[TextureType::_2DArray].resize(getCaps().maxCombinedTextureImageUnits);
2246     }
2247     if (clientVersion >= Version(3, 1) || nativeExtensions.textureMultisampleANGLE)
2248     {
2249         mSamplerTextures[TextureType::_2DMultisample].resize(
2250             getCaps().maxCombinedTextureImageUnits);
2251     }
2252     if (clientVersion >= Version(3, 1))
2253     {
2254         mSamplerTextures[TextureType::_2DMultisampleArray].resize(
2255             getCaps().maxCombinedTextureImageUnits);
2256 
2257         mAtomicCounterBuffers.resize(getCaps().maxAtomicCounterBufferBindings);
2258         mShaderStorageBuffers.resize(getCaps().maxShaderStorageBufferBindings);
2259     }
2260     if (clientVersion >= Version(3, 1) ||
2261         (context->getImplementation()->getNativePixelLocalStorageOptions().type ==
2262          ShPixelLocalStorageType::ImageLoadStore))
2263     {
2264         mImageUnits.resize(getCaps().maxImageUnits);
2265     }
2266     if (clientVersion >= Version(3, 1) || nativeExtensions.textureCubeMapArrayAny())
2267     {
2268         mSamplerTextures[TextureType::CubeMapArray].resize(getCaps().maxCombinedTextureImageUnits);
2269     }
2270     if (clientVersion >= Version(3, 1) || nativeExtensions.textureCubeMapArrayAny())
2271     {
2272         mSamplerTextures[TextureType::Buffer].resize(getCaps().maxCombinedTextureImageUnits);
2273     }
2274     if (nativeExtensions.textureRectangleANGLE)
2275     {
2276         mSamplerTextures[TextureType::Rectangle].resize(getCaps().maxCombinedTextureImageUnits);
2277     }
2278     if (nativeExtensions.EGLImageExternalOES || nativeExtensions.EGLStreamConsumerExternalNV)
2279     {
2280         mSamplerTextures[TextureType::External].resize(getCaps().maxCombinedTextureImageUnits);
2281     }
2282     if (nativeExtensions.videoTextureWEBGL)
2283     {
2284         mSamplerTextures[TextureType::VideoImage].resize(getCaps().maxCombinedTextureImageUnits);
2285     }
2286     mCompleteTextureBindings.reserve(getCaps().maxCombinedTextureImageUnits);
2287     for (int32_t textureIndex = 0; textureIndex < getCaps().maxCombinedTextureImageUnits;
2288          ++textureIndex)
2289     {
2290         mCompleteTextureBindings.emplace_back(context, textureIndex);
2291     }
2292 
2293     mSamplers.resize(getCaps().maxCombinedTextureImageUnits);
2294 
2295     for (QueryType type : angle::AllEnums<QueryType>())
2296     {
2297         mActiveQueries[type].set(context, nullptr);
2298     }
2299 
2300     mProgram = nullptr;
2301     UninstallExecutable(context, &mExecutable);
2302 
2303     mReadFramebuffer = nullptr;
2304     mDrawFramebuffer = nullptr;
2305 
2306     getDebug().setMaxLoggedMessages(getCaps().maxDebugLoggedMessages);
2307 }
2308 
reset(const Context * context)2309 void State::reset(const Context *context)
2310 {
2311     // Force a sync so clear doesn't end up dereferencing stale pointers.
2312     (void)syncActiveTextures(context, Command::Other);
2313     mActiveTexturesCache.clear();
2314 
2315     for (TextureBindingVector &bindingVec : mSamplerTextures)
2316     {
2317         for (BindingPointer<Texture> &texBinding : bindingVec)
2318         {
2319             texBinding.set(context, nullptr);
2320         }
2321     }
2322     for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++)
2323     {
2324         mSamplers[samplerIdx].set(context, nullptr);
2325     }
2326 
2327     for (ImageUnit &imageUnit : mImageUnits)
2328     {
2329         imageUnit.texture.set(context, nullptr);
2330         imageUnit.level   = 0;
2331         imageUnit.layered = false;
2332         imageUnit.layer   = 0;
2333         imageUnit.access  = GL_READ_ONLY;
2334         imageUnit.format  = GL_R32UI;
2335     }
2336 
2337     mRenderbuffer.set(context, nullptr);
2338 
2339     for (BufferBinding type : angle::AllEnums<BufferBinding>())
2340     {
2341         UpdateBufferBinding(context, &mBoundBuffers[type], nullptr, type);
2342     }
2343 
2344     UninstallExecutable(context, &mExecutable);
2345     if (mProgram)
2346     {
2347         mProgram->release(context);
2348     }
2349     mProgram = nullptr;
2350     mProgramPipeline.set(context, nullptr);
2351 
2352     if (mTransformFeedback.get())
2353     {
2354         mTransformFeedback->onBindingChanged(context, false);
2355     }
2356     mTransformFeedback.set(context, nullptr);
2357 
2358     for (QueryType type : angle::AllEnums<QueryType>())
2359     {
2360         mActiveQueries[type].set(context, nullptr);
2361     }
2362 
2363     for (OffsetBindingPointer<Buffer> &buf : mUniformBuffers)
2364     {
2365         UpdateIndexedBufferBinding(context, &buf, nullptr, BufferBinding::Uniform, 0, 0);
2366     }
2367     mBoundUniformBuffersMask.reset();
2368 
2369     for (OffsetBindingPointer<Buffer> &buf : mAtomicCounterBuffers)
2370     {
2371         UpdateIndexedBufferBinding(context, &buf, nullptr, BufferBinding::AtomicCounter, 0, 0);
2372     }
2373     mBoundAtomicCounterBuffersMask.reset();
2374 
2375     for (OffsetBindingPointer<Buffer> &buf : mShaderStorageBuffers)
2376     {
2377         UpdateIndexedBufferBinding(context, &buf, nullptr, BufferBinding::ShaderStorage, 0, 0);
2378     }
2379     mBoundShaderStorageBuffersMask.reset();
2380 
2381     mPrivateState.reset();
2382 
2383     setAllDirtyBits();
2384 }
2385 
unsetActiveTextures(const ActiveTextureMask & textureMask)2386 ANGLE_INLINE void State::unsetActiveTextures(const ActiveTextureMask &textureMask)
2387 {
2388     // Unset any relevant bound textures.
2389     for (size_t textureIndex : textureMask)
2390     {
2391         mActiveTexturesCache.reset(textureIndex);
2392         mCompleteTextureBindings[textureIndex].reset();
2393     }
2394 }
2395 
updateActiveTextureStateOnSync(const Context * context,size_t textureIndex,const Sampler * sampler,Texture * texture)2396 ANGLE_INLINE void State::updateActiveTextureStateOnSync(const Context *context,
2397                                                         size_t textureIndex,
2398                                                         const Sampler *sampler,
2399                                                         Texture *texture)
2400 {
2401     if (!texture || !texture->isSamplerComplete(context, sampler))
2402     {
2403         mActiveTexturesCache.reset(textureIndex);
2404     }
2405     else
2406     {
2407         mActiveTexturesCache.set(textureIndex, texture);
2408     }
2409 
2410     mDirtyBits.set(state::DIRTY_BIT_TEXTURE_BINDINGS);
2411 }
2412 
setActiveTextureDirty(size_t textureIndex,Texture * texture)2413 ANGLE_INLINE void State::setActiveTextureDirty(size_t textureIndex, Texture *texture)
2414 {
2415     mDirtyObjects.set(state::DIRTY_OBJECT_ACTIVE_TEXTURES);
2416     mDirtyActiveTextures.set(textureIndex);
2417 
2418     if (!texture)
2419     {
2420         return;
2421     }
2422 
2423     if (texture->hasAnyDirtyBit())
2424     {
2425         setTextureDirty(textureIndex);
2426     }
2427 
2428     if (isRobustResourceInitEnabled() && texture->initState() == InitState::MayNeedInit)
2429     {
2430         mDirtyObjects.set(state::DIRTY_OBJECT_TEXTURES_INIT);
2431     }
2432 
2433     // This cache is updated immediately because we use the cache in the validation layer.
2434     // If we defer the update until syncState it's too late and we've already passed validation.
2435     if (texture && mExecutable)
2436     {
2437         // It is invalid to try to sample a non-yuv texture with a yuv sampler.
2438         mTexturesIncompatibleWithSamplers[textureIndex] =
2439             mExecutable->getActiveYUVSamplers().test(textureIndex) && !texture->isYUV();
2440 
2441         if (isWebGL())
2442         {
2443             const Sampler *sampler = mSamplers[textureIndex].get();
2444             const SamplerState &samplerState =
2445                 sampler ? sampler->getSamplerState() : texture->getSamplerState();
2446             if (!texture->getTextureState().compatibleWithSamplerFormatForWebGL(
2447                     mExecutable->getSamplerFormatForTextureUnitIndex(textureIndex), samplerState))
2448             {
2449                 mTexturesIncompatibleWithSamplers[textureIndex] = true;
2450             }
2451         }
2452     }
2453     else
2454     {
2455         mTexturesIncompatibleWithSamplers[textureIndex] = false;
2456     }
2457 }
2458 
updateTextureBinding(const Context * context,size_t textureIndex,Texture * texture)2459 ANGLE_INLINE void State::updateTextureBinding(const Context *context,
2460                                               size_t textureIndex,
2461                                               Texture *texture)
2462 {
2463     mCompleteTextureBindings[textureIndex].bind(texture);
2464     mActiveTexturesCache.reset(textureIndex);
2465     setActiveTextureDirty(textureIndex, texture);
2466 }
2467 
allActiveDrawBufferChannelsMasked() const2468 bool State::allActiveDrawBufferChannelsMasked() const
2469 {
2470     // Compare current color mask with all-disabled color mask, while ignoring disabled draw
2471     // buffers.
2472     return (getBlendStateExt().compareColorMask(0) & mDrawFramebuffer->getDrawBufferMask()).none();
2473 }
2474 
anyActiveDrawBufferChannelMasked() const2475 bool State::anyActiveDrawBufferChannelMasked() const
2476 {
2477     // Compare current color mask with all-enabled color mask, while ignoring disabled draw
2478     // buffers.
2479     return (getBlendStateExt().compareColorMask(getBlendStateExt().getAllColorMaskBits()) &
2480             mDrawFramebuffer->getDrawBufferMask())
2481         .any();
2482 }
2483 
setSamplerTexture(const Context * context,TextureType type,Texture * texture)2484 void State::setSamplerTexture(const Context *context, TextureType type, Texture *texture)
2485 {
2486     if (mExecutable && mExecutable->getActiveSamplersMask()[getActiveSampler()] &&
2487         IsTextureCompatibleWithSampler(type,
2488                                        mExecutable->getActiveSamplerTypes()[getActiveSampler()]))
2489     {
2490         updateTextureBinding(context, getActiveSampler(), texture);
2491     }
2492 
2493     mSamplerTextures[type][getActiveSampler()].set(context, texture);
2494 
2495     mDirtyBits.set(state::DIRTY_BIT_TEXTURE_BINDINGS);
2496 }
2497 
getTargetTexture(TextureType type) const2498 Texture *State::getTargetTexture(TextureType type) const
2499 {
2500     return getSamplerTexture(getActiveSampler(), type);
2501 }
2502 
getSamplerTextureId(unsigned int sampler,TextureType type) const2503 TextureID State::getSamplerTextureId(unsigned int sampler, TextureType type) const
2504 {
2505     ASSERT(sampler < mSamplerTextures[type].size());
2506     return mSamplerTextures[type][sampler].id();
2507 }
2508 
detachTexture(Context * context,const TextureMap & zeroTextures,TextureID texture)2509 void State::detachTexture(Context *context, const TextureMap &zeroTextures, TextureID texture)
2510 {
2511     // Textures have a detach method on State rather than a simple
2512     // removeBinding, because the zero/null texture objects are managed
2513     // separately, and don't have to go through the Context's maps or
2514     // the ResourceManager.
2515 
2516     // [OpenGL ES 2.0.24] section 3.8 page 84:
2517     // If a texture object is deleted, it is as if all texture units which are bound to that texture
2518     // object are rebound to texture object zero
2519 
2520     for (TextureType type : angle::AllEnums<TextureType>())
2521     {
2522         TextureBindingVector &textureVector = mSamplerTextures[type];
2523 
2524         for (size_t bindingIndex = 0; bindingIndex < textureVector.size(); ++bindingIndex)
2525         {
2526             BindingPointer<Texture> &binding = textureVector[bindingIndex];
2527             if (binding.id() == texture)
2528             {
2529                 // Zero textures are the "default" textures instead of NULL
2530                 Texture *zeroTexture = zeroTextures[type].get();
2531                 ASSERT(zeroTexture != nullptr);
2532                 if (mCompleteTextureBindings[bindingIndex].getSubject() == binding.get())
2533                 {
2534                     updateTextureBinding(context, bindingIndex, zeroTexture);
2535                 }
2536                 binding.set(context, zeroTexture);
2537             }
2538         }
2539     }
2540 
2541     for (auto &bindingImageUnit : mImageUnits)
2542     {
2543         if (bindingImageUnit.texture.id() == texture)
2544         {
2545             bindingImageUnit.texture.set(context, nullptr);
2546             bindingImageUnit.level   = 0;
2547             bindingImageUnit.layered = false;
2548             bindingImageUnit.layer   = 0;
2549             bindingImageUnit.access  = GL_READ_ONLY;
2550             bindingImageUnit.format  = GL_R32UI;
2551         }
2552     }
2553 
2554     // [OpenGL ES 2.0.24] section 4.4 page 112:
2555     // If a texture object is deleted while its image is attached to the currently bound
2556     // framebuffer, then it is as if Texture2DAttachment had been called, with a texture of 0, for
2557     // each attachment point to which this image was attached in the currently bound framebuffer.
2558 
2559     if (mReadFramebuffer && mReadFramebuffer->detachTexture(context, texture))
2560     {
2561         mDirtyObjects.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
2562     }
2563 
2564     if (mDrawFramebuffer && mDrawFramebuffer->detachTexture(context, texture))
2565     {
2566         setDrawFramebufferDirty();
2567     }
2568 }
2569 
initializeZeroTextures(const Context * context,const TextureMap & zeroTextures)2570 void State::initializeZeroTextures(const Context *context, const TextureMap &zeroTextures)
2571 {
2572     for (TextureType type : angle::AllEnums<TextureType>())
2573     {
2574         for (size_t textureUnit = 0; textureUnit < mSamplerTextures[type].size(); ++textureUnit)
2575         {
2576             mSamplerTextures[type][textureUnit].set(context, zeroTextures[type].get());
2577         }
2578     }
2579 }
2580 
invalidateTextureBindings(TextureType type)2581 void State::invalidateTextureBindings(TextureType type)
2582 {
2583     mDirtyBits.set(state::DIRTY_BIT_TEXTURE_BINDINGS);
2584 }
2585 
setSamplerBinding(const Context * context,GLuint textureUnit,Sampler * sampler)2586 void State::setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler)
2587 {
2588     if (mSamplers[textureUnit].get() == sampler)
2589     {
2590         return;
2591     }
2592 
2593     mSamplers[textureUnit].set(context, sampler);
2594     mDirtyBits.set(state::DIRTY_BIT_SAMPLER_BINDINGS);
2595     // This is overly conservative as it assumes the sampler has never been bound.
2596     setSamplerDirty(textureUnit);
2597     onActiveTextureChange(context, textureUnit);
2598 }
2599 
detachSampler(const Context * context,SamplerID sampler)2600 void State::detachSampler(const Context *context, SamplerID sampler)
2601 {
2602     // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124:
2603     // If a sampler object that is currently bound to one or more texture units is
2604     // deleted, it is as though BindSampler is called once for each texture unit to
2605     // which the sampler is bound, with unit set to the texture unit and sampler set to zero.
2606     for (size_t i = 0; i < mSamplers.size(); i++)
2607     {
2608         if (mSamplers[i].id() == sampler)
2609         {
2610             setSamplerBinding(context, static_cast<GLuint>(i), nullptr);
2611         }
2612     }
2613 }
2614 
setRenderbufferBinding(const Context * context,Renderbuffer * renderbuffer)2615 void State::setRenderbufferBinding(const Context *context, Renderbuffer *renderbuffer)
2616 {
2617     mRenderbuffer.set(context, renderbuffer);
2618     mDirtyBits.set(state::DIRTY_BIT_RENDERBUFFER_BINDING);
2619 }
2620 
detachRenderbuffer(Context * context,RenderbufferID renderbuffer)2621 void State::detachRenderbuffer(Context *context, RenderbufferID renderbuffer)
2622 {
2623     // [OpenGL ES 2.0.24] section 4.4 page 109:
2624     // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though
2625     // BindRenderbuffer had been executed with the target RENDERBUFFER and name of zero.
2626 
2627     if (mRenderbuffer.id() == renderbuffer)
2628     {
2629         setRenderbufferBinding(context, nullptr);
2630     }
2631 
2632     // [OpenGL ES 2.0.24] section 4.4 page 111:
2633     // If a renderbuffer object is deleted while its image is attached to the currently bound
2634     // framebuffer, then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of
2635     // 0, for each attachment point to which this image was attached in the currently bound
2636     // framebuffer.
2637 
2638     Framebuffer *readFramebuffer = mReadFramebuffer;
2639     Framebuffer *drawFramebuffer = mDrawFramebuffer;
2640 
2641     if (readFramebuffer && readFramebuffer->detachRenderbuffer(context, renderbuffer))
2642     {
2643         mDirtyObjects.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
2644     }
2645 
2646     if (drawFramebuffer && drawFramebuffer != readFramebuffer)
2647     {
2648         if (drawFramebuffer->detachRenderbuffer(context, renderbuffer))
2649         {
2650             setDrawFramebufferDirty();
2651         }
2652     }
2653 }
2654 
setReadFramebufferBinding(Framebuffer * framebuffer)2655 void State::setReadFramebufferBinding(Framebuffer *framebuffer)
2656 {
2657     if (mReadFramebuffer == framebuffer)
2658         return;
2659 
2660     mReadFramebuffer = framebuffer;
2661     mDirtyBits.set(state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
2662 
2663     if (mReadFramebuffer && mReadFramebuffer->hasAnyDirtyBit())
2664     {
2665         mDirtyObjects.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
2666     }
2667 }
2668 
setDrawFramebufferBinding(Framebuffer * framebuffer)2669 void State::setDrawFramebufferBinding(Framebuffer *framebuffer)
2670 {
2671     if (mDrawFramebuffer == framebuffer)
2672         return;
2673 
2674     mDrawFramebuffer = framebuffer;
2675     mDirtyBits.set(state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
2676 
2677     if (mDrawFramebuffer)
2678     {
2679         mDrawFramebuffer->setWriteControlMode(getFramebufferSRGB() ? SrgbWriteControlMode::Default
2680                                                                    : SrgbWriteControlMode::Linear);
2681 
2682         if (mDrawFramebuffer->hasAnyDirtyBit())
2683         {
2684             mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
2685         }
2686 
2687         if (isRobustResourceInitEnabled() && mDrawFramebuffer->hasResourceThatNeedsInit())
2688         {
2689             mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS);
2690         }
2691     }
2692 }
2693 
getTargetFramebuffer(GLenum target) const2694 Framebuffer *State::getTargetFramebuffer(GLenum target) const
2695 {
2696     switch (target)
2697     {
2698         case GL_READ_FRAMEBUFFER_ANGLE:
2699             return mReadFramebuffer;
2700         case GL_DRAW_FRAMEBUFFER_ANGLE:
2701         case GL_FRAMEBUFFER:
2702             return mDrawFramebuffer;
2703         default:
2704             UNREACHABLE();
2705             return nullptr;
2706     }
2707 }
2708 
getDefaultFramebuffer() const2709 Framebuffer *State::getDefaultFramebuffer() const
2710 {
2711     return mFramebufferManager->getDefaultFramebuffer();
2712 }
2713 
removeReadFramebufferBinding(FramebufferID framebuffer)2714 bool State::removeReadFramebufferBinding(FramebufferID framebuffer)
2715 {
2716     if (mReadFramebuffer != nullptr && mReadFramebuffer->id() == framebuffer)
2717     {
2718         setReadFramebufferBinding(nullptr);
2719         return true;
2720     }
2721 
2722     return false;
2723 }
2724 
removeDrawFramebufferBinding(FramebufferID framebuffer)2725 bool State::removeDrawFramebufferBinding(FramebufferID framebuffer)
2726 {
2727     if (mReadFramebuffer != nullptr && mDrawFramebuffer->id() == framebuffer)
2728     {
2729         setDrawFramebufferBinding(nullptr);
2730         return true;
2731     }
2732 
2733     return false;
2734 }
2735 
setVertexArrayBinding(const Context * context,VertexArray * vertexArray)2736 void State::setVertexArrayBinding(const Context *context, VertexArray *vertexArray)
2737 {
2738     if (mVertexArray == vertexArray)
2739     {
2740         return;
2741     }
2742 
2743     if (mVertexArray)
2744     {
2745         mVertexArray->onBindingChanged(context, -1);
2746     }
2747     if (vertexArray)
2748     {
2749         vertexArray->onBindingChanged(context, 1);
2750     }
2751 
2752     mVertexArray = vertexArray;
2753     mDirtyBits.set(state::DIRTY_BIT_VERTEX_ARRAY_BINDING);
2754 
2755     if (mVertexArray && mVertexArray->hasAnyDirtyBit())
2756     {
2757         mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
2758     }
2759 }
2760 
removeVertexArrayBinding(const Context * context,VertexArrayID vertexArray)2761 bool State::removeVertexArrayBinding(const Context *context, VertexArrayID vertexArray)
2762 {
2763     if (mVertexArray && mVertexArray->id().value == vertexArray.value)
2764     {
2765         mVertexArray->onBindingChanged(context, -1);
2766         mVertexArray = nullptr;
2767         mDirtyBits.set(state::DIRTY_BIT_VERTEX_ARRAY_BINDING);
2768         mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
2769         return true;
2770     }
2771 
2772     return false;
2773 }
2774 
getVertexArrayId() const2775 VertexArrayID State::getVertexArrayId() const
2776 {
2777     ASSERT(mVertexArray != nullptr);
2778     return mVertexArray->id();
2779 }
2780 
bindVertexBuffer(const Context * context,GLuint bindingIndex,Buffer * boundBuffer,GLintptr offset,GLsizei stride)2781 void State::bindVertexBuffer(const Context *context,
2782                              GLuint bindingIndex,
2783                              Buffer *boundBuffer,
2784                              GLintptr offset,
2785                              GLsizei stride)
2786 {
2787     getVertexArray()->bindVertexBuffer(context, bindingIndex, boundBuffer, offset, stride);
2788     mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
2789 }
2790 
setVertexAttribFormat(GLuint attribIndex,GLint size,VertexAttribType type,bool normalized,bool pureInteger,GLuint relativeOffset)2791 void State::setVertexAttribFormat(GLuint attribIndex,
2792                                   GLint size,
2793                                   VertexAttribType type,
2794                                   bool normalized,
2795                                   bool pureInteger,
2796                                   GLuint relativeOffset)
2797 {
2798     getVertexArray()->setVertexAttribFormat(attribIndex, size, type, normalized, pureInteger,
2799                                             relativeOffset);
2800     mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
2801 }
2802 
setVertexBindingDivisor(const Context * context,GLuint bindingIndex,GLuint divisor)2803 void State::setVertexBindingDivisor(const Context *context, GLuint bindingIndex, GLuint divisor)
2804 {
2805     getVertexArray()->setVertexBindingDivisor(context, bindingIndex, divisor);
2806     mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
2807 }
2808 
setProgram(const Context * context,Program * newProgram)2809 angle::Result State::setProgram(const Context *context, Program *newProgram)
2810 {
2811     if (newProgram && !newProgram->isLinked())
2812     {
2813         // Protect against applications that disable validation and try to use a program that was
2814         // not successfully linked.
2815         WARN() << "Attempted to use a program that was not successfully linked";
2816         return angle::Result::Continue;
2817     }
2818 
2819     if (mProgram != newProgram)
2820     {
2821         if (mProgram)
2822         {
2823             unsetActiveTextures(mExecutable->getActiveSamplersMask());
2824             mProgram->release(context);
2825         }
2826 
2827         mProgram = newProgram;
2828 
2829         if (mProgram)
2830         {
2831             newProgram->addRef();
2832             ANGLE_TRY(installProgramExecutable(context));
2833         }
2834         else if (mProgramPipeline.get() == nullptr)
2835         {
2836             UninstallExecutable(context, &mExecutable);
2837         }
2838         else if (mProgramPipeline->isLinked())
2839         {
2840             ANGLE_TRY(installProgramPipelineExecutableIfNotAlready(context));
2841         }
2842 
2843         // Note that rendering is undefined if glUseProgram(0) is called. But ANGLE will generate
2844         // an error if the app tries to draw in this case.
2845 
2846         mDirtyBits.set(state::DIRTY_BIT_PROGRAM_BINDING);
2847     }
2848 
2849     return angle::Result::Continue;
2850 }
2851 
setTransformFeedbackBinding(const Context * context,TransformFeedback * transformFeedback)2852 void State::setTransformFeedbackBinding(const Context *context,
2853                                         TransformFeedback *transformFeedback)
2854 {
2855     if (transformFeedback == mTransformFeedback.get())
2856         return;
2857     if (mTransformFeedback.get())
2858         mTransformFeedback->onBindingChanged(context, false);
2859     mTransformFeedback.set(context, transformFeedback);
2860     if (mTransformFeedback.get())
2861         mTransformFeedback->onBindingChanged(context, true);
2862     mDirtyBits.set(state::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING);
2863 }
2864 
removeTransformFeedbackBinding(const Context * context,TransformFeedbackID transformFeedback)2865 bool State::removeTransformFeedbackBinding(const Context *context,
2866                                            TransformFeedbackID transformFeedback)
2867 {
2868     if (mTransformFeedback.id() == transformFeedback)
2869     {
2870         if (mTransformFeedback.get())
2871             mTransformFeedback->onBindingChanged(context, false);
2872         mTransformFeedback.set(context, nullptr);
2873         return true;
2874     }
2875 
2876     return false;
2877 }
2878 
setProgramPipelineBinding(const Context * context,ProgramPipeline * pipeline)2879 angle::Result State::setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline)
2880 {
2881     if (mProgramPipeline.get() == pipeline)
2882     {
2883         return angle::Result::Continue;
2884     }
2885 
2886     if (mProgramPipeline.get())
2887     {
2888         unsetActiveTextures(mProgramPipeline->getExecutable().getActiveSamplersMask());
2889     }
2890 
2891     mProgramPipeline.set(context, pipeline);
2892     mDirtyBits.set(state::DIRTY_BIT_PROGRAM_BINDING);
2893 
2894     // A bound Program always overrides the ProgramPipeline, so only update the
2895     // current ProgramExecutable if there isn't currently a Program bound.
2896     if (!mProgram)
2897     {
2898         if (mProgramPipeline.get() && mProgramPipeline->isLinked())
2899         {
2900             ANGLE_TRY(installProgramPipelineExecutableIfNotAlready(context));
2901         }
2902     }
2903 
2904     return angle::Result::Continue;
2905 }
2906 
detachProgramPipeline(const Context * context,ProgramPipelineID pipeline)2907 void State::detachProgramPipeline(const Context *context, ProgramPipelineID pipeline)
2908 {
2909     mProgramPipeline.set(context, nullptr);
2910 
2911     // A bound Program always overrides the ProgramPipeline, so only update the
2912     // current ProgramExecutable if there isn't currently a Program bound.
2913     if (!mProgram)
2914     {
2915         UninstallExecutable(context, &mExecutable);
2916     }
2917 }
2918 
isQueryActive(QueryType type) const2919 bool State::isQueryActive(QueryType type) const
2920 {
2921     const Query *query = mActiveQueries[type].get();
2922     if (query != nullptr)
2923     {
2924         return true;
2925     }
2926 
2927     QueryType alternativeType;
2928     if (GetAlternativeQueryType(type, &alternativeType))
2929     {
2930         query = mActiveQueries[alternativeType].get();
2931         return query != nullptr;
2932     }
2933 
2934     return false;
2935 }
2936 
isQueryActive(Query * query) const2937 bool State::isQueryActive(Query *query) const
2938 {
2939     for (auto &queryPointer : mActiveQueries)
2940     {
2941         if (queryPointer.get() == query)
2942         {
2943             return true;
2944         }
2945     }
2946 
2947     return false;
2948 }
2949 
setActiveQuery(const Context * context,QueryType type,Query * query)2950 void State::setActiveQuery(const Context *context, QueryType type, Query *query)
2951 {
2952     mActiveQueries[type].set(context, query);
2953 }
2954 
getActiveQueryId(QueryType type) const2955 QueryID State::getActiveQueryId(QueryType type) const
2956 {
2957     const Query *query = getActiveQuery(type);
2958     if (query)
2959     {
2960         return query->id();
2961     }
2962     return {0};
2963 }
2964 
getActiveQuery(QueryType type) const2965 Query *State::getActiveQuery(QueryType type) const
2966 {
2967     return mActiveQueries[type].get();
2968 }
2969 
setIndexedBufferBinding(const Context * context,BufferBinding target,GLuint index,Buffer * buffer,GLintptr offset,GLsizeiptr size)2970 angle::Result State::setIndexedBufferBinding(const Context *context,
2971                                              BufferBinding target,
2972                                              GLuint index,
2973                                              Buffer *buffer,
2974                                              GLintptr offset,
2975                                              GLsizeiptr size)
2976 {
2977     setBufferBinding(context, target, buffer);
2978 
2979     switch (target)
2980     {
2981         case BufferBinding::TransformFeedback:
2982             ANGLE_TRY(mTransformFeedback->bindIndexedBuffer(context, index, buffer, offset, size));
2983             setBufferBinding(context, target, buffer);
2984             break;
2985         case BufferBinding::Uniform:
2986             mBoundUniformBuffersMask.set(index, buffer != nullptr);
2987             UpdateIndexedBufferBinding(context, &mUniformBuffers[index], buffer, target, offset,
2988                                        size);
2989             onUniformBufferStateChange(index);
2990             break;
2991         case BufferBinding::AtomicCounter:
2992             mBoundAtomicCounterBuffersMask.set(index, buffer != nullptr);
2993             UpdateIndexedBufferBinding(context, &mAtomicCounterBuffers[index], buffer, target,
2994                                        offset, size);
2995             break;
2996         case BufferBinding::ShaderStorage:
2997             mBoundShaderStorageBuffersMask.set(index, buffer != nullptr);
2998             UpdateIndexedBufferBinding(context, &mShaderStorageBuffers[index], buffer, target,
2999                                        offset, size);
3000             break;
3001         default:
3002             UNREACHABLE();
3003             break;
3004     }
3005 
3006     return angle::Result::Continue;
3007 }
3008 
getIndexedUniformBuffer(size_t index) const3009 const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index) const
3010 {
3011     ASSERT(index < mUniformBuffers.size());
3012     return mUniformBuffers[index];
3013 }
3014 
getIndexedAtomicCounterBuffer(size_t index) const3015 const OffsetBindingPointer<Buffer> &State::getIndexedAtomicCounterBuffer(size_t index) const
3016 {
3017     ASSERT(index < mAtomicCounterBuffers.size());
3018     return mAtomicCounterBuffers[index];
3019 }
3020 
getIndexedShaderStorageBuffer(size_t index) const3021 const OffsetBindingPointer<Buffer> &State::getIndexedShaderStorageBuffer(size_t index) const
3022 {
3023     ASSERT(index < mShaderStorageBuffers.size());
3024     return mShaderStorageBuffers[index];
3025 }
3026 
detachBuffer(Context * context,const Buffer * buffer)3027 angle::Result State::detachBuffer(Context *context, const Buffer *buffer)
3028 {
3029     BufferID bufferID = buffer->id();
3030     for (gl::BufferBinding target : angle::AllEnums<BufferBinding>())
3031     {
3032         if (mBoundBuffers[target].id() == bufferID)
3033         {
3034             UpdateBufferBinding(context, &mBoundBuffers[target], nullptr, target);
3035         }
3036     }
3037 
3038     TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
3039     if (curTransformFeedback)
3040     {
3041         ANGLE_TRY(curTransformFeedback->detachBuffer(context, bufferID));
3042         context->getStateCache().onActiveTransformFeedbackChange(context);
3043     }
3044 
3045     if (mVertexArray && mVertexArray->detachBuffer(context, bufferID))
3046     {
3047         mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
3048         context->getStateCache().onVertexArrayStateChange(context);
3049     }
3050 
3051     for (size_t uniformBufferIndex : mBoundUniformBuffersMask)
3052     {
3053         OffsetBindingPointer<Buffer> &binding = mUniformBuffers[uniformBufferIndex];
3054 
3055         if (binding.id() == bufferID)
3056         {
3057             UpdateIndexedBufferBinding(context, &binding, nullptr, BufferBinding::Uniform, 0, 0);
3058             mBoundUniformBuffersMask.reset(uniformBufferIndex);
3059         }
3060     }
3061 
3062     for (size_t atomicCounterBufferIndex : mBoundAtomicCounterBuffersMask)
3063     {
3064         OffsetBindingPointer<Buffer> &binding = mAtomicCounterBuffers[atomicCounterBufferIndex];
3065 
3066         if (binding.id() == bufferID)
3067         {
3068             UpdateIndexedBufferBinding(context, &binding, nullptr, BufferBinding::AtomicCounter, 0,
3069                                        0);
3070             mBoundAtomicCounterBuffersMask.reset(atomicCounterBufferIndex);
3071         }
3072     }
3073 
3074     for (size_t shaderStorageBufferIndex : mBoundShaderStorageBuffersMask)
3075     {
3076         OffsetBindingPointer<Buffer> &binding = mShaderStorageBuffers[shaderStorageBufferIndex];
3077 
3078         if (binding.id() == bufferID)
3079         {
3080             UpdateIndexedBufferBinding(context, &binding, nullptr, BufferBinding::ShaderStorage, 0,
3081                                        0);
3082             mBoundShaderStorageBuffersMask.reset(shaderStorageBufferIndex);
3083         }
3084     }
3085 
3086     return angle::Result::Continue;
3087 }
3088 
setEnableVertexAttribArray(unsigned int attribNum,bool enabled)3089 void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
3090 {
3091     getVertexArray()->enableAttribute(attribNum, enabled);
3092     mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
3093 }
3094 
setVertexAttribDivisor(const Context * context,GLuint index,GLuint divisor)3095 void State::setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor)
3096 {
3097     getVertexArray()->setVertexAttribDivisor(context, index, divisor);
3098     mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
3099 }
3100 
getVertexAttribPointer(unsigned int attribNum) const3101 const void *State::getVertexAttribPointer(unsigned int attribNum) const
3102 {
3103     return getVertexArray()->getVertexAttribute(attribNum).pointer;
3104 }
3105 
getBooleanv(GLenum pname,GLboolean * params) const3106 void State::getBooleanv(GLenum pname, GLboolean *params) const
3107 {
3108     switch (pname)
3109     {
3110         case GL_TRANSFORM_FEEDBACK_ACTIVE:
3111             *params = getCurrentTransformFeedback()->isActive() ? GL_TRUE : GL_FALSE;
3112             break;
3113         case GL_TRANSFORM_FEEDBACK_PAUSED:
3114             *params = getCurrentTransformFeedback()->isPaused() ? GL_TRUE : GL_FALSE;
3115             break;
3116         default:
3117             mPrivateState.getBooleanv(pname, params);
3118     }
3119 }
3120 
getIntegerv(const Context * context,GLenum pname,GLint * params) const3121 angle::Result State::getIntegerv(const Context *context, GLenum pname, GLint *params) const
3122 {
3123     if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
3124     {
3125         size_t drawBuffer = (pname - GL_DRAW_BUFFER0_EXT);
3126         ASSERT(drawBuffer < static_cast<size_t>(getCaps().maxDrawBuffers));
3127         Framebuffer *framebuffer = mDrawFramebuffer;
3128         // The default framebuffer may have fewer draw buffer states than a user-created one. The
3129         // user is always allowed to query up to GL_MAX_DRAWBUFFERS so just return GL_NONE here if
3130         // the draw buffer is out of range for this framebuffer.
3131         *params = drawBuffer < framebuffer->getDrawbufferStateCount()
3132                       ? framebuffer->getDrawBufferState(drawBuffer)
3133                       : GL_NONE;
3134         return angle::Result::Continue;
3135     }
3136 
3137     switch (pname)
3138     {
3139         case GL_ARRAY_BUFFER_BINDING:
3140             *params = mBoundBuffers[BufferBinding::Array].id().value;
3141             break;
3142         case GL_DRAW_INDIRECT_BUFFER_BINDING:
3143             *params = mBoundBuffers[BufferBinding::DrawIndirect].id().value;
3144             break;
3145         case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3146         {
3147             Buffer *elementArrayBuffer = getVertexArray()->getElementArrayBuffer();
3148             *params                    = elementArrayBuffer ? elementArrayBuffer->id().value : 0;
3149             break;
3150         }
3151         case GL_DRAW_FRAMEBUFFER_BINDING:
3152             static_assert(GL_DRAW_FRAMEBUFFER_BINDING == GL_DRAW_FRAMEBUFFER_BINDING_ANGLE,
3153                           "Enum mismatch");
3154             *params = mDrawFramebuffer->id().value;
3155             break;
3156         case GL_READ_FRAMEBUFFER_BINDING:
3157             static_assert(GL_READ_FRAMEBUFFER_BINDING == GL_READ_FRAMEBUFFER_BINDING_ANGLE,
3158                           "Enum mismatch");
3159             *params = mReadFramebuffer->id().value;
3160             break;
3161         case GL_RENDERBUFFER_BINDING:
3162             *params = mRenderbuffer.id().value;
3163             break;
3164         case GL_VERTEX_ARRAY_BINDING:
3165             *params = mVertexArray->id().value;
3166             break;
3167         case GL_CURRENT_PROGRAM:
3168             *params = mProgram ? mProgram->id().value : 0;
3169             break;
3170         case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3171             *params = mReadFramebuffer->getImplementationColorReadType(context);
3172             break;
3173         case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3174             *params = mReadFramebuffer->getImplementationColorReadFormat(context);
3175             break;
3176         case GL_SAMPLE_BUFFERS:
3177         case GL_SAMPLES:
3178         {
3179             Framebuffer *framebuffer = mDrawFramebuffer;
3180             if (framebuffer->isComplete(context))
3181             {
3182                 GLint samples = framebuffer->getSamples(context);
3183                 switch (pname)
3184                 {
3185                     case GL_SAMPLE_BUFFERS:
3186                         if (samples != 0)
3187                         {
3188                             *params = 1;
3189                         }
3190                         else
3191                         {
3192                             *params = 0;
3193                         }
3194                         break;
3195                     case GL_SAMPLES:
3196                         *params = samples;
3197                         break;
3198                 }
3199             }
3200             else
3201             {
3202                 *params = 0;
3203             }
3204         }
3205         break;
3206         case GL_RED_BITS:
3207         case GL_GREEN_BITS:
3208         case GL_BLUE_BITS:
3209         case GL_ALPHA_BITS:
3210         {
3211             Framebuffer *framebuffer                 = getDrawFramebuffer();
3212             const FramebufferAttachment *colorbuffer = framebuffer->getFirstColorAttachment();
3213 
3214             if (colorbuffer)
3215             {
3216                 switch (pname)
3217                 {
3218                     case GL_RED_BITS:
3219                         *params = colorbuffer->getRedSize();
3220                         break;
3221                     case GL_GREEN_BITS:
3222                         *params = colorbuffer->getGreenSize();
3223                         break;
3224                     case GL_BLUE_BITS:
3225                         *params = colorbuffer->getBlueSize();
3226                         break;
3227                     case GL_ALPHA_BITS:
3228                         *params = colorbuffer->getAlphaSize();
3229                         break;
3230                 }
3231             }
3232             else
3233             {
3234                 *params = 0;
3235             }
3236         }
3237         break;
3238         case GL_DEPTH_BITS:
3239         {
3240             const Framebuffer *framebuffer           = getDrawFramebuffer();
3241             const FramebufferAttachment *depthbuffer = framebuffer->getDepthAttachment();
3242 
3243             if (depthbuffer)
3244             {
3245                 *params = depthbuffer->getDepthSize();
3246             }
3247             else
3248             {
3249                 *params = 0;
3250             }
3251         }
3252         break;
3253         case GL_STENCIL_BITS:
3254         {
3255             const Framebuffer *framebuffer             = getDrawFramebuffer();
3256             const FramebufferAttachment *stencilbuffer = framebuffer->getStencilAttachment();
3257 
3258             if (stencilbuffer)
3259             {
3260                 *params = stencilbuffer->getStencilSize();
3261             }
3262             else
3263             {
3264                 *params = 0;
3265             }
3266         }
3267         break;
3268         case GL_TEXTURE_BINDING_2D:
3269             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3270             *params = getSamplerTextureId(getActiveSampler(), TextureType::_2D).value;
3271             break;
3272         case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
3273             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3274             *params = getSamplerTextureId(getActiveSampler(), TextureType::Rectangle).value;
3275             break;
3276         case GL_TEXTURE_BINDING_CUBE_MAP:
3277             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3278             *params = getSamplerTextureId(getActiveSampler(), TextureType::CubeMap).value;
3279             break;
3280         case GL_TEXTURE_BINDING_3D:
3281             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3282             *params = getSamplerTextureId(getActiveSampler(), TextureType::_3D).value;
3283             break;
3284         case GL_TEXTURE_BINDING_2D_ARRAY:
3285             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3286             *params = getSamplerTextureId(getActiveSampler(), TextureType::_2DArray).value;
3287             break;
3288         case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
3289             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3290             *params = getSamplerTextureId(getActiveSampler(), TextureType::_2DMultisample).value;
3291             break;
3292         case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
3293             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3294             *params =
3295                 getSamplerTextureId(getActiveSampler(), TextureType::_2DMultisampleArray).value;
3296             break;
3297         case GL_TEXTURE_BINDING_CUBE_MAP_ARRAY:
3298             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3299             *params = getSamplerTextureId(getActiveSampler(), TextureType::CubeMapArray).value;
3300             break;
3301         case GL_TEXTURE_BINDING_EXTERNAL_OES:
3302             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3303             *params = getSamplerTextureId(getActiveSampler(), TextureType::External).value;
3304             break;
3305 
3306         // GL_OES_texture_buffer
3307         case GL_TEXTURE_BINDING_BUFFER:
3308             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3309             *params = getSamplerTextureId(getActiveSampler(), TextureType::Buffer).value;
3310             break;
3311         case GL_TEXTURE_BUFFER_BINDING:
3312             *params = mBoundBuffers[BufferBinding::Texture].id().value;
3313             break;
3314 
3315         case GL_UNIFORM_BUFFER_BINDING:
3316             *params = mBoundBuffers[BufferBinding::Uniform].id().value;
3317             break;
3318         case GL_TRANSFORM_FEEDBACK_BINDING:
3319             *params = mTransformFeedback.id().value;
3320             break;
3321         case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
3322             *params = mBoundBuffers[BufferBinding::TransformFeedback].id().value;
3323             break;
3324         case GL_COPY_READ_BUFFER_BINDING:
3325             *params = mBoundBuffers[BufferBinding::CopyRead].id().value;
3326             break;
3327         case GL_COPY_WRITE_BUFFER_BINDING:
3328             *params = mBoundBuffers[BufferBinding::CopyWrite].id().value;
3329             break;
3330         case GL_PIXEL_PACK_BUFFER_BINDING:
3331             *params = mBoundBuffers[BufferBinding::PixelPack].id().value;
3332             break;
3333         case GL_PIXEL_UNPACK_BUFFER_BINDING:
3334             *params = mBoundBuffers[BufferBinding::PixelUnpack].id().value;
3335             break;
3336 
3337         case GL_READ_BUFFER:
3338             *params = mReadFramebuffer->getReadBufferState();
3339             break;
3340         case GL_SAMPLER_BINDING:
3341             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3342             *params = getSamplerId(getActiveSampler()).value;
3343             break;
3344         case GL_DEBUG_LOGGED_MESSAGES:
3345             *params = static_cast<GLint>(getDebug().getMessageCount());
3346             break;
3347         case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
3348             *params = static_cast<GLint>(getDebug().getNextMessageLength());
3349             break;
3350         case GL_DEBUG_GROUP_STACK_DEPTH:
3351             *params = static_cast<GLint>(getDebug().getGroupStackDepth());
3352             break;
3353         case GL_ATOMIC_COUNTER_BUFFER_BINDING:
3354             *params = mBoundBuffers[BufferBinding::AtomicCounter].id().value;
3355             break;
3356         case GL_SHADER_STORAGE_BUFFER_BINDING:
3357             *params = mBoundBuffers[BufferBinding::ShaderStorage].id().value;
3358             break;
3359         case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
3360             *params = mBoundBuffers[BufferBinding::DispatchIndirect].id().value;
3361             break;
3362 
3363         case GL_PROGRAM_PIPELINE_BINDING:
3364         {
3365             ProgramPipeline *pipeline = getProgramPipeline();
3366             if (pipeline)
3367             {
3368                 *params = pipeline->id().value;
3369             }
3370             else
3371             {
3372                 *params = 0;
3373             }
3374             break;
3375         }
3376 
3377         default:
3378             mPrivateState.getIntegerv(pname, params);
3379             break;
3380     }
3381 
3382     return angle::Result::Continue;
3383 }
3384 
getPointerv(const Context * context,GLenum pname,void ** params) const3385 void State::getPointerv(const Context *context, GLenum pname, void **params) const
3386 {
3387     switch (pname)
3388     {
3389         case GL_DEBUG_CALLBACK_FUNCTION:
3390             *params = reinterpret_cast<void *>(getDebug().getCallback());
3391             break;
3392         case GL_DEBUG_CALLBACK_USER_PARAM:
3393             *params = const_cast<void *>(getDebug().getUserParam());
3394             break;
3395         case GL_VERTEX_ARRAY_POINTER:
3396         case GL_NORMAL_ARRAY_POINTER:
3397         case GL_COLOR_ARRAY_POINTER:
3398         case GL_TEXTURE_COORD_ARRAY_POINTER:
3399         case GL_POINT_SIZE_ARRAY_POINTER_OES:
3400             QueryVertexAttribPointerv(getVertexArray()->getVertexAttribute(
3401                                           context->vertexArrayIndex(ParamToVertexArrayType(pname))),
3402                                       GL_VERTEX_ATTRIB_ARRAY_POINTER, params);
3403             return;
3404         default:
3405             UNREACHABLE();
3406             break;
3407     }
3408 }
3409 
getIntegeri_v(const Context * context,GLenum target,GLuint index,GLint * data) const3410 void State::getIntegeri_v(const Context *context, GLenum target, GLuint index, GLint *data) const
3411 {
3412     switch (target)
3413     {
3414         case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
3415             ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
3416             *data = mTransformFeedback->getIndexedBuffer(index).id().value;
3417             break;
3418         case GL_UNIFORM_BUFFER_BINDING:
3419             ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
3420             *data = mUniformBuffers[index].id().value;
3421             break;
3422         case GL_ATOMIC_COUNTER_BUFFER_BINDING:
3423             ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
3424             *data = mAtomicCounterBuffers[index].id().value;
3425             break;
3426         case GL_SHADER_STORAGE_BUFFER_BINDING:
3427             ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
3428             *data = mShaderStorageBuffers[index].id().value;
3429             break;
3430         case GL_VERTEX_BINDING_BUFFER:
3431             ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
3432             *data = mVertexArray->getVertexBinding(index).getBuffer().id().value;
3433             break;
3434         case GL_VERTEX_BINDING_DIVISOR:
3435             ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
3436             *data = mVertexArray->getVertexBinding(index).getDivisor();
3437             break;
3438         case GL_VERTEX_BINDING_OFFSET:
3439             ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
3440             *data = static_cast<GLuint>(mVertexArray->getVertexBinding(index).getOffset());
3441             break;
3442         case GL_VERTEX_BINDING_STRIDE:
3443             ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
3444             *data = mVertexArray->getVertexBinding(index).getStride();
3445             break;
3446         case GL_IMAGE_BINDING_NAME:
3447             ASSERT(static_cast<size_t>(index) < mImageUnits.size());
3448             *data = mImageUnits[index].texture.id().value;
3449             break;
3450         case GL_IMAGE_BINDING_LEVEL:
3451             ASSERT(static_cast<size_t>(index) < mImageUnits.size());
3452             *data = mImageUnits[index].level;
3453             break;
3454         case GL_IMAGE_BINDING_LAYER:
3455             ASSERT(static_cast<size_t>(index) < mImageUnits.size());
3456             *data = mImageUnits[index].layer;
3457             break;
3458         case GL_IMAGE_BINDING_ACCESS:
3459             ASSERT(static_cast<size_t>(index) < mImageUnits.size());
3460             *data = mImageUnits[index].access;
3461             break;
3462         case GL_IMAGE_BINDING_FORMAT:
3463             ASSERT(static_cast<size_t>(index) < mImageUnits.size());
3464             *data = mImageUnits[index].format;
3465             break;
3466         default:
3467             mPrivateState.getIntegeri_v(target, index, data);
3468             break;
3469     }
3470 }
3471 
getInteger64i_v(GLenum target,GLuint index,GLint64 * data) const3472 void State::getInteger64i_v(GLenum target, GLuint index, GLint64 *data) const
3473 {
3474     switch (target)
3475     {
3476         case GL_TRANSFORM_FEEDBACK_BUFFER_START:
3477             ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
3478             *data = mTransformFeedback->getIndexedBuffer(index).getOffset();
3479             break;
3480         case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
3481             ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
3482             *data = mTransformFeedback->getIndexedBuffer(index).getSize();
3483             break;
3484         case GL_UNIFORM_BUFFER_START:
3485             ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
3486             *data = mUniformBuffers[index].getOffset();
3487             break;
3488         case GL_UNIFORM_BUFFER_SIZE:
3489             ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
3490             *data = mUniformBuffers[index].getSize();
3491             break;
3492         case GL_ATOMIC_COUNTER_BUFFER_START:
3493             ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
3494             *data = mAtomicCounterBuffers[index].getOffset();
3495             break;
3496         case GL_ATOMIC_COUNTER_BUFFER_SIZE:
3497             ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
3498             *data = mAtomicCounterBuffers[index].getSize();
3499             break;
3500         case GL_SHADER_STORAGE_BUFFER_START:
3501             ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
3502             *data = mShaderStorageBuffers[index].getOffset();
3503             break;
3504         case GL_SHADER_STORAGE_BUFFER_SIZE:
3505             ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
3506             *data = mShaderStorageBuffers[index].getSize();
3507             break;
3508         default:
3509             UNREACHABLE();
3510             break;
3511     }
3512 }
3513 
getBooleani_v(GLenum target,GLuint index,GLboolean * data) const3514 void State::getBooleani_v(GLenum target, GLuint index, GLboolean *data) const
3515 {
3516     switch (target)
3517     {
3518         case GL_IMAGE_BINDING_LAYERED:
3519             ASSERT(static_cast<size_t>(index) < mImageUnits.size());
3520             *data = mImageUnits[index].layered;
3521             break;
3522         default:
3523             mPrivateState.getBooleani_v(target, index, data);
3524             break;
3525     }
3526 }
3527 
3528 // TODO(http://anglebug.com/3889): Remove this helper function after blink and chromium part
3529 // refactor done.
getTextureForActiveSampler(TextureType type,size_t index)3530 Texture *State::getTextureForActiveSampler(TextureType type, size_t index)
3531 {
3532     if (type != TextureType::VideoImage)
3533     {
3534         return mSamplerTextures[type][index].get();
3535     }
3536 
3537     ASSERT(type == TextureType::VideoImage);
3538 
3539     Texture *candidateTexture = mSamplerTextures[type][index].get();
3540     if (candidateTexture->getWidth(TextureTarget::VideoImage, 0) == 0 ||
3541         candidateTexture->getHeight(TextureTarget::VideoImage, 0) == 0 ||
3542         candidateTexture->getDepth(TextureTarget::VideoImage, 0) == 0)
3543     {
3544         return mSamplerTextures[TextureType::_2D][index].get();
3545     }
3546 
3547     return mSamplerTextures[type][index].get();
3548 }
3549 
syncActiveTextures(const Context * context,Command command)3550 angle::Result State::syncActiveTextures(const Context *context, Command command)
3551 {
3552     if (mDirtyActiveTextures.none())
3553     {
3554         return angle::Result::Continue;
3555     }
3556 
3557     for (size_t textureUnit : mDirtyActiveTextures)
3558     {
3559         if (mExecutable)
3560         {
3561             TextureType type       = mExecutable->getActiveSamplerTypes()[textureUnit];
3562             Texture *activeTexture = (type != TextureType::InvalidEnum)
3563                                          ? getTextureForActiveSampler(type, textureUnit)
3564                                          : nullptr;
3565             const Sampler *sampler = mSamplers[textureUnit].get();
3566 
3567             updateActiveTextureStateOnSync(context, textureUnit, sampler, activeTexture);
3568         }
3569     }
3570 
3571     mDirtyActiveTextures.reset();
3572     return angle::Result::Continue;
3573 }
3574 
syncTexturesInit(const Context * context,Command command)3575 angle::Result State::syncTexturesInit(const Context *context, Command command)
3576 {
3577     ASSERT(isRobustResourceInitEnabled());
3578 
3579     if (!mProgram)
3580         return angle::Result::Continue;
3581 
3582     for (size_t textureUnitIndex : mExecutable->getActiveSamplersMask())
3583     {
3584         Texture *texture = mActiveTexturesCache[textureUnitIndex];
3585         if (texture)
3586         {
3587             ANGLE_TRY(texture->ensureInitialized(context));
3588         }
3589     }
3590     return angle::Result::Continue;
3591 }
3592 
syncImagesInit(const Context * context,Command command)3593 angle::Result State::syncImagesInit(const Context *context, Command command)
3594 {
3595     ASSERT(isRobustResourceInitEnabled());
3596     ASSERT(mExecutable);
3597     for (size_t imageUnitIndex : mExecutable->getActiveImagesMask())
3598     {
3599         Texture *texture = mImageUnits[imageUnitIndex].texture.get();
3600         if (texture)
3601         {
3602             ANGLE_TRY(texture->ensureInitialized(context));
3603         }
3604     }
3605     return angle::Result::Continue;
3606 }
3607 
syncReadAttachments(const Context * context,Command command)3608 angle::Result State::syncReadAttachments(const Context *context, Command command)
3609 {
3610     ASSERT(mReadFramebuffer);
3611     ASSERT(isRobustResourceInitEnabled());
3612     return mReadFramebuffer->ensureReadAttachmentsInitialized(context);
3613 }
3614 
syncDrawAttachments(const Context * context,Command command)3615 angle::Result State::syncDrawAttachments(const Context *context, Command command)
3616 {
3617     ASSERT(mDrawFramebuffer);
3618     ASSERT(isRobustResourceInitEnabled());
3619     return mDrawFramebuffer->ensureDrawAttachmentsInitialized(context);
3620 }
3621 
syncReadFramebuffer(const Context * context,Command command)3622 angle::Result State::syncReadFramebuffer(const Context *context, Command command)
3623 {
3624     ASSERT(mReadFramebuffer);
3625     return mReadFramebuffer->syncState(context, GL_READ_FRAMEBUFFER, command);
3626 }
3627 
syncDrawFramebuffer(const Context * context,Command command)3628 angle::Result State::syncDrawFramebuffer(const Context *context, Command command)
3629 {
3630     ASSERT(mDrawFramebuffer);
3631     mDrawFramebuffer->setWriteControlMode(context->getState().getFramebufferSRGB()
3632                                               ? SrgbWriteControlMode::Default
3633                                               : SrgbWriteControlMode::Linear);
3634     return mDrawFramebuffer->syncState(context, GL_DRAW_FRAMEBUFFER, command);
3635 }
3636 
syncTextures(const Context * context,Command command)3637 angle::Result State::syncTextures(const Context *context, Command command)
3638 {
3639     if (mDirtyTextures.none())
3640         return angle::Result::Continue;
3641 
3642     for (size_t textureIndex : mDirtyTextures)
3643     {
3644         Texture *texture = mActiveTexturesCache[textureIndex];
3645         if (texture && texture->hasAnyDirtyBit())
3646         {
3647             ANGLE_TRY(texture->syncState(context, Command::Other));
3648         }
3649     }
3650 
3651     mDirtyTextures.reset();
3652     return angle::Result::Continue;
3653 }
3654 
syncImages(const Context * context,Command command)3655 angle::Result State::syncImages(const Context *context, Command command)
3656 {
3657     if (mDirtyImages.none())
3658         return angle::Result::Continue;
3659 
3660     for (size_t imageUnitIndex : mDirtyImages)
3661     {
3662         Texture *texture = mImageUnits[imageUnitIndex].texture.get();
3663         if (texture && texture->hasAnyDirtyBit())
3664         {
3665             ANGLE_TRY(texture->syncState(context, Command::Other));
3666         }
3667     }
3668 
3669     mDirtyImages.reset();
3670     return angle::Result::Continue;
3671 }
3672 
syncSamplers(const Context * context,Command command)3673 angle::Result State::syncSamplers(const Context *context, Command command)
3674 {
3675     if (mDirtySamplers.none())
3676         return angle::Result::Continue;
3677 
3678     for (size_t samplerIndex : mDirtySamplers)
3679     {
3680         BindingPointer<Sampler> &sampler = mSamplers[samplerIndex];
3681         if (sampler.get() && sampler->isDirty())
3682         {
3683             ANGLE_TRY(sampler->syncState(context));
3684         }
3685     }
3686 
3687     mDirtySamplers.reset();
3688 
3689     return angle::Result::Continue;
3690 }
3691 
syncVertexArray(const Context * context,Command command)3692 angle::Result State::syncVertexArray(const Context *context, Command command)
3693 {
3694     ASSERT(mVertexArray);
3695     return mVertexArray->syncState(context);
3696 }
3697 
syncProgramPipelineObject(const Context * context,Command command)3698 angle::Result State::syncProgramPipelineObject(const Context *context, Command command)
3699 {
3700     // If a ProgramPipeline is bound, ensure it is linked.
3701     if (mProgramPipeline.get())
3702     {
3703         mProgramPipeline->resolveLink(context);
3704     }
3705     return angle::Result::Continue;
3706 }
3707 
syncDirtyObject(const Context * context,GLenum target)3708 angle::Result State::syncDirtyObject(const Context *context, GLenum target)
3709 {
3710     state::DirtyObjects localSet;
3711 
3712     switch (target)
3713     {
3714         case GL_READ_FRAMEBUFFER:
3715             localSet.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
3716             break;
3717         case GL_DRAW_FRAMEBUFFER:
3718             localSet.set(state::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
3719             break;
3720         default:
3721             UNREACHABLE();
3722             break;
3723     }
3724 
3725     return syncDirtyObjects(context, localSet, Command::Other);
3726 }
3727 
setObjectDirty(GLenum target)3728 void State::setObjectDirty(GLenum target)
3729 {
3730     switch (target)
3731     {
3732         case GL_READ_FRAMEBUFFER:
3733             mDirtyObjects.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
3734             break;
3735         case GL_DRAW_FRAMEBUFFER:
3736             setDrawFramebufferDirty();
3737             break;
3738         case GL_FRAMEBUFFER:
3739             mDirtyObjects.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
3740             setDrawFramebufferDirty();
3741             break;
3742         case GL_VERTEX_ARRAY:
3743             mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
3744             break;
3745         default:
3746             break;
3747     }
3748 }
3749 
installProgramExecutable(const Context * context)3750 angle::Result State::installProgramExecutable(const Context *context)
3751 {
3752     // OpenGL Spec:
3753     // "If LinkProgram or ProgramBinary successfully re-links a program object
3754     //  that was already in use as a result of a previous call to UseProgram, then the
3755     //  generated executable code will be installed as part of the current rendering state."
3756     ASSERT(mProgram->isLinked());
3757 
3758     mDirtyBits.set(state::DIRTY_BIT_PROGRAM_EXECUTABLE);
3759 
3760     // Make sure the program binary is cached if needed and not already.  This is automatically done
3761     // on program destruction, but is done here anyway to support situations like Android apps that
3762     // are typically killed instead of cleanly closed.
3763     mProgram->cacheProgramBinaryIfNecessary(context);
3764 
3765     // The bound Program always overrides the ProgramPipeline, so install the executable regardless
3766     // of whether a program pipeline is bound.
3767     InstallExecutable(context, mProgram->getSharedExecutable(), &mExecutable);
3768     return onExecutableChange(context);
3769 }
3770 
installProgramPipelineExecutable(const Context * context)3771 angle::Result State::installProgramPipelineExecutable(const Context *context)
3772 {
3773     ASSERT(mProgramPipeline->isLinked());
3774 
3775     mDirtyBits.set(state::DIRTY_BIT_PROGRAM_EXECUTABLE);
3776 
3777     // A bound Program always overrides the ProgramPipeline, so only update the current
3778     // ProgramExecutable if there isn't currently a Program bound.
3779     if (mProgram == nullptr)
3780     {
3781         InstallExecutable(context, mProgramPipeline->getSharedExecutable(), &mExecutable);
3782         return onExecutableChange(context);
3783     }
3784 
3785     return angle::Result::Continue;
3786 }
3787 
installProgramPipelineExecutableIfNotAlready(const Context * context)3788 angle::Result State::installProgramPipelineExecutableIfNotAlready(const Context *context)
3789 {
3790     // If a program pipeline is bound, then unbound and bound again, its executable will still be
3791     // set, and there is no need to reinstall it.
3792     if (mExecutable.get() == mProgramPipeline->getSharedExecutable().get())
3793     {
3794         return onExecutableChange(context);
3795     }
3796     return installProgramPipelineExecutable(context);
3797 }
3798 
onExecutableChange(const Context * context)3799 angle::Result State::onExecutableChange(const Context *context)
3800 {
3801     // Set any bound textures.
3802     const ActiveTextureTypeArray &textureTypes = mExecutable->getActiveSamplerTypes();
3803 
3804     for (size_t textureIndex : mExecutable->getActiveSamplersMask())
3805     {
3806         TextureType type = textureTypes[textureIndex];
3807 
3808         // This can happen if there is a conflicting texture type.
3809         if (type == TextureType::InvalidEnum)
3810             continue;
3811 
3812         Texture *texture = getTextureForActiveSampler(type, textureIndex);
3813         updateTextureBinding(context, textureIndex, texture);
3814     }
3815 
3816     for (size_t imageUnitIndex : mExecutable->getActiveImagesMask())
3817     {
3818         Texture *image = mImageUnits[imageUnitIndex].texture.get();
3819         if (!image)
3820             continue;
3821 
3822         if (image->hasAnyDirtyBit())
3823         {
3824             ANGLE_TRY(image->syncState(context, Command::Other));
3825         }
3826 
3827         if (isRobustResourceInitEnabled() && image->initState() == InitState::MayNeedInit)
3828         {
3829             mDirtyObjects.set(state::DIRTY_OBJECT_IMAGES_INIT);
3830         }
3831     }
3832 
3833     // Mark uniform blocks as _not_ dirty. When an executable changes, the backends should already
3834     // reprocess all uniform blocks.  These dirty bits only track what's made dirty afterwards.
3835     mDirtyUniformBlocks.reset();
3836 
3837     return angle::Result::Continue;
3838 }
3839 
setTextureDirty(size_t textureUnitIndex)3840 void State::setTextureDirty(size_t textureUnitIndex)
3841 {
3842     mDirtyObjects.set(state::DIRTY_OBJECT_TEXTURES);
3843     mDirtyTextures.set(textureUnitIndex);
3844 }
3845 
setSamplerDirty(size_t samplerIndex)3846 void State::setSamplerDirty(size_t samplerIndex)
3847 {
3848     mDirtyObjects.set(state::DIRTY_OBJECT_SAMPLERS);
3849     mDirtySamplers.set(samplerIndex);
3850 }
3851 
setImageUnit(const Context * context,size_t unit,Texture * texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)3852 void State::setImageUnit(const Context *context,
3853                          size_t unit,
3854                          Texture *texture,
3855                          GLint level,
3856                          GLboolean layered,
3857                          GLint layer,
3858                          GLenum access,
3859                          GLenum format)
3860 {
3861     ASSERT(!mImageUnits.empty());
3862 
3863     ImageUnit &imageUnit = mImageUnits[unit];
3864 
3865     if (texture)
3866     {
3867         texture->onBindAsImageTexture();
3868     }
3869     imageUnit.texture.set(context, texture);
3870     imageUnit.level   = level;
3871     imageUnit.layered = layered;
3872     imageUnit.layer   = layer;
3873     imageUnit.access  = access;
3874     imageUnit.format  = format;
3875     mDirtyBits.set(state::DIRTY_BIT_IMAGE_BINDINGS);
3876 
3877     onImageStateChange(context, unit);
3878 }
3879 
setMaxShaderCompilerThreads(GLuint count)3880 void State::setMaxShaderCompilerThreads(GLuint count)
3881 {
3882     mMaxShaderCompilerThreads = count;
3883 }
3884 
3885 // Handle a dirty texture event.
onActiveTextureChange(const Context * context,size_t textureUnit)3886 void State::onActiveTextureChange(const Context *context, size_t textureUnit)
3887 {
3888     if (mExecutable)
3889     {
3890         TextureType type       = mExecutable->getActiveSamplerTypes()[textureUnit];
3891         Texture *activeTexture = (type != TextureType::InvalidEnum)
3892                                      ? getTextureForActiveSampler(type, textureUnit)
3893                                      : nullptr;
3894         updateTextureBinding(context, textureUnit, activeTexture);
3895 
3896         mExecutable->onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
3897     }
3898 }
3899 
onActiveTextureStateChange(const Context * context,size_t textureUnit)3900 void State::onActiveTextureStateChange(const Context *context, size_t textureUnit)
3901 {
3902     if (mExecutable)
3903     {
3904         TextureType type       = mExecutable->getActiveSamplerTypes()[textureUnit];
3905         Texture *activeTexture = (type != TextureType::InvalidEnum)
3906                                      ? getTextureForActiveSampler(type, textureUnit)
3907                                      : nullptr;
3908         setActiveTextureDirty(textureUnit, activeTexture);
3909     }
3910 }
3911 
onImageStateChange(const Context * context,size_t unit)3912 void State::onImageStateChange(const Context *context, size_t unit)
3913 {
3914     if (mExecutable)
3915     {
3916         const ImageUnit &image = mImageUnits[unit];
3917 
3918         // Have nothing to do here if no texture bound
3919         if (!image.texture.get())
3920             return;
3921 
3922         if (image.texture->hasAnyDirtyBit())
3923         {
3924             mDirtyImages.set(unit);
3925             mDirtyObjects.set(state::DIRTY_OBJECT_IMAGES);
3926         }
3927 
3928         if (isRobustResourceInitEnabled() && image.texture->initState() == InitState::MayNeedInit)
3929         {
3930             mDirtyObjects.set(state::DIRTY_OBJECT_IMAGES_INIT);
3931         }
3932 
3933         mExecutable->onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
3934     }
3935 }
3936 
onUniformBufferStateChange(size_t uniformBufferIndex)3937 void State::onUniformBufferStateChange(size_t uniformBufferIndex)
3938 {
3939     if (mExecutable)
3940     {
3941         // When a buffer at a given binding changes, set all blocks mapped to it dirty.
3942         mDirtyUniformBlocks |=
3943             mExecutable->getUniformBufferBlocksMappedToBinding(uniformBufferIndex);
3944     }
3945     // This could be represented by a different dirty bit. Using the same one keeps it simple.
3946     mDirtyBits.set(state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
3947 }
3948 
onAtomicCounterBufferStateChange(size_t atomicCounterBufferIndex)3949 void State::onAtomicCounterBufferStateChange(size_t atomicCounterBufferIndex)
3950 {
3951     mDirtyBits.set(state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
3952 }
3953 
onShaderStorageBufferStateChange(size_t shaderStorageBufferIndex)3954 void State::onShaderStorageBufferStateChange(size_t shaderStorageBufferIndex)
3955 {
3956     mDirtyBits.set(state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
3957 }
3958 
initializeForCapture(const Context * context)3959 void State::initializeForCapture(const Context *context)
3960 {
3961     mPrivateState.initializeForCapture(context);
3962 
3963     // This little kludge gets around the frame capture "constness". It should be safe because
3964     // nothing in the context is modified in a non-compatible way during capture.
3965     Context *mutableContext = const_cast<Context *>(context);
3966     initialize(mutableContext);
3967 }
3968 
3969 }  // namespace gl
3970