• 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       mTextureFilteringHint(GL_NONE),
359       mFragmentShaderDerivativeHint(GL_NONE),
360       mNearZ(0),
361       mFarZ(0),
362       mProvokingVertex(gl::ProvokingVertexConvention::LastVertexConvention),
363       mActiveSampler(0),
364       mPrimitiveRestart(false),
365       mMultiSampling(false),
366       mSampleAlphaToOne(false),
367       mFramebufferSRGB(true),
368       mTextureRectangleEnabled(true),
369       mLogicOpEnabled(false),
370       mLogicOp(LogicalOperation::Copy),
371       mPatchVertices(3),
372       mPixelLocalStorageActivePlanes(0),
373       mNoSimultaneousConstantColorAndAlphaBlendFunc(false),
374       mSetBlendIndexedInvoked(false),
375       mSetBlendFactorsIndexedInvoked(false),
376       mSetBlendEquationsIndexedInvoked(false),
377       mBoundingBoxMinX(-1.0f),
378       mBoundingBoxMinY(-1.0f),
379       mBoundingBoxMinZ(-1.0f),
380       mBoundingBoxMinW(1.0f),
381       mBoundingBoxMaxX(1.0f),
382       mBoundingBoxMaxY(1.0f),
383       mBoundingBoxMaxZ(1.0f),
384       mBoundingBoxMaxW(1.0f),
385       mShadingRatePreserveAspectRatio(false),
386       mShadingRate(ShadingRate::Undefined),
387       mFetchPerSample(false),
388       mBindGeneratesResource(bindGeneratesResourceCHROMIUM),
389       mClientArraysEnabled(clientArraysEnabled),
390       mRobustResourceInit(robustResourceInit),
391       mProgramBinaryCacheEnabled(programBinaryCacheEnabled),
392       mDebug(debug)
393 {}
394 
395 PrivateState::~PrivateState() = default;
396 
initialize(Context * context)397 void PrivateState::initialize(Context *context)
398 {
399     mBlendStateExt = BlendStateExt(mCaps.maxDrawBuffers);
400 
401     setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f);
402 
403     mDepthClearValue   = 1.0f;
404     mStencilClearValue = 0;
405 
406     mScissorTest    = false;
407     mScissor.x      = 0;
408     mScissor.y      = 0;
409     mScissor.width  = 0;
410     mScissor.height = 0;
411 
412     mBlendColor.red   = 0;
413     mBlendColor.green = 0;
414     mBlendColor.blue  = 0;
415     mBlendColor.alpha = 0;
416 
417     mStencilRef     = 0;
418     mStencilBackRef = 0;
419 
420     mSampleCoverage       = false;
421     mSampleCoverageValue  = 1.0f;
422     mSampleCoverageInvert = false;
423 
424     mMaxSampleMaskWords = static_cast<GLuint>(mCaps.maxSampleMaskWords);
425     mSampleMask         = false;
426     mSampleMaskValues.fill(~GLbitfield(0));
427 
428     mGenerateMipmapHint           = GL_DONT_CARE;
429     mTextureFilteringHint         = GL_DONT_CARE;
430     mFragmentShaderDerivativeHint = GL_DONT_CARE;
431 
432     mLineWidth = 1.0f;
433 
434     mViewport.x      = 0;
435     mViewport.y      = 0;
436     mViewport.width  = 0;
437     mViewport.height = 0;
438     mNearZ           = 0.0f;
439     mFarZ            = 1.0f;
440 
441     mClipOrigin    = ClipOrigin::LowerLeft;
442     mClipDepthMode = ClipDepthMode::NegativeOneToOne;
443 
444     mActiveSampler = 0;
445 
446     mVertexAttribCurrentValues.resize(mCaps.maxVertexAttributes);
447 
448     // Set all indexes in state attributes type mask to float (default)
449     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
450     {
451         SetComponentTypeMask(ComponentType::Float, i, &mCurrentValuesTypeMask);
452     }
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 
setTextureFilteringHint(GLenum hint)1158 void PrivateState::setTextureFilteringHint(GLenum hint)
1159 {
1160     mTextureFilteringHint = hint;
1161     // Note: we don't add a dirty bit for this flag as it's not expected to be toggled at
1162     // runtime.
1163 }
1164 
setFragmentShaderDerivativeHint(GLenum hint)1165 void PrivateState::setFragmentShaderDerivativeHint(GLenum hint)
1166 {
1167     mFragmentShaderDerivativeHint = hint;
1168     mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
1169     mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT);
1170     // Note: This hint could be propagated to shader translator so we can write ddx, ddx_coarse, or
1171     // ddx_fine depending on the hint.  Ignore for now. It is valid for implementations to ignore
1172     // the hint.
1173 }
1174 
setActiveSampler(unsigned int active)1175 void PrivateState::setActiveSampler(unsigned int active)
1176 {
1177     mActiveSampler = active;
1178 }
1179 
getAndResetDirtyCurrentValues() const1180 AttributesMask PrivateState::getAndResetDirtyCurrentValues() const
1181 {
1182     AttributesMask retVal = mDirtyCurrentValues;
1183     mDirtyCurrentValues.reset();
1184     return retVal;
1185 }
1186 
setClipDistanceEnable(int idx,bool enable)1187 void PrivateState::setClipDistanceEnable(int idx, bool enable)
1188 {
1189     if (enable)
1190     {
1191         mClipDistancesEnabled.set(idx);
1192     }
1193     else
1194     {
1195         mClipDistancesEnabled.reset(idx);
1196     }
1197 
1198     mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
1199     mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES);
1200 }
1201 
setBoundingBox(GLfloat minX,GLfloat minY,GLfloat minZ,GLfloat minW,GLfloat maxX,GLfloat maxY,GLfloat maxZ,GLfloat maxW)1202 void PrivateState::setBoundingBox(GLfloat minX,
1203                                   GLfloat minY,
1204                                   GLfloat minZ,
1205                                   GLfloat minW,
1206                                   GLfloat maxX,
1207                                   GLfloat maxY,
1208                                   GLfloat maxZ,
1209                                   GLfloat maxW)
1210 {
1211     mBoundingBoxMinX = minX;
1212     mBoundingBoxMinY = minY;
1213     mBoundingBoxMinZ = minZ;
1214     mBoundingBoxMinW = minW;
1215     mBoundingBoxMaxX = maxX;
1216     mBoundingBoxMaxY = maxY;
1217     mBoundingBoxMaxZ = maxZ;
1218     mBoundingBoxMaxW = maxW;
1219 }
1220 
setLogicOpEnabled(bool enabled)1221 void PrivateState::setLogicOpEnabled(bool enabled)
1222 {
1223     if (mLogicOpEnabled != enabled)
1224     {
1225         mLogicOpEnabled = enabled;
1226         mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
1227         mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED);
1228     }
1229 }
1230 
setLogicOp(LogicalOperation opcode)1231 void PrivateState::setLogicOp(LogicalOperation opcode)
1232 {
1233     if (mLogicOp != opcode)
1234     {
1235         mLogicOp = opcode;
1236         mDirtyBits.set(state::DIRTY_BIT_EXTENDED);
1237         mExtendedDirtyBits.set(state::EXTENDED_DIRTY_BIT_LOGIC_OP);
1238     }
1239 }
1240 
setVertexAttribf(GLuint index,const GLfloat values[4])1241 void PrivateState::setVertexAttribf(GLuint index, const GLfloat values[4])
1242 {
1243     ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
1244     mVertexAttribCurrentValues[index].setFloatValues(values);
1245     mDirtyBits.set(state::DIRTY_BIT_CURRENT_VALUES);
1246     mDirtyCurrentValues.set(index);
1247     SetComponentTypeMask(ComponentType::Float, index, &mCurrentValuesTypeMask);
1248 }
1249 
setVertexAttribu(GLuint index,const GLuint values[4])1250 void PrivateState::setVertexAttribu(GLuint index, const GLuint values[4])
1251 {
1252     ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
1253     mVertexAttribCurrentValues[index].setUnsignedIntValues(values);
1254     mDirtyBits.set(state::DIRTY_BIT_CURRENT_VALUES);
1255     mDirtyCurrentValues.set(index);
1256     SetComponentTypeMask(ComponentType::UnsignedInt, index, &mCurrentValuesTypeMask);
1257 }
1258 
setVertexAttribi(GLuint index,const GLint values[4])1259 void PrivateState::setVertexAttribi(GLuint index, const GLint values[4])
1260 {
1261     ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
1262     mVertexAttribCurrentValues[index].setIntValues(values);
1263     mDirtyBits.set(state::DIRTY_BIT_CURRENT_VALUES);
1264     mDirtyCurrentValues.set(index);
1265     SetComponentTypeMask(ComponentType::Int, index, &mCurrentValuesTypeMask);
1266 }
1267 
setEnableFeature(GLenum feature,bool enabled)1268 void PrivateState::setEnableFeature(GLenum feature, bool enabled)
1269 {
1270     switch (feature)
1271     {
1272         case GL_MULTISAMPLE_EXT:
1273             setMultisampling(enabled);
1274             return;
1275         case GL_SAMPLE_ALPHA_TO_ONE_EXT:
1276             setSampleAlphaToOne(enabled);
1277             return;
1278         case GL_CULL_FACE:
1279             setCullFace(enabled);
1280             return;
1281         case GL_POLYGON_OFFSET_POINT_NV:
1282             setPolygonOffsetPoint(enabled);
1283             return;
1284         case GL_POLYGON_OFFSET_LINE_NV:
1285             setPolygonOffsetLine(enabled);
1286             return;
1287         case GL_POLYGON_OFFSET_FILL:
1288             setPolygonOffsetFill(enabled);
1289             return;
1290         case GL_DEPTH_CLAMP_EXT:
1291             setDepthClamp(enabled);
1292             return;
1293         case GL_SAMPLE_ALPHA_TO_COVERAGE:
1294             setSampleAlphaToCoverage(enabled);
1295             return;
1296         case GL_SAMPLE_COVERAGE:
1297             setSampleCoverage(enabled);
1298             return;
1299         case GL_SCISSOR_TEST:
1300             setScissorTest(enabled);
1301             return;
1302         case GL_STENCIL_TEST:
1303             setStencilTest(enabled);
1304             return;
1305         case GL_DEPTH_TEST:
1306             setDepthTest(enabled);
1307             return;
1308         case GL_BLEND:
1309             setBlend(enabled);
1310             return;
1311         case GL_DITHER:
1312             setDither(enabled);
1313             return;
1314         case GL_COLOR_LOGIC_OP:
1315             if (mClientVersion.major == 1)
1316             {
1317                 // Handle logicOp in GLES1 through the GLES1 state management and emulation.
1318                 // Otherwise this state could be set as part of ANGLE_logic_op.
1319                 break;
1320             }
1321             setLogicOpEnabled(enabled);
1322             return;
1323         case GL_PRIMITIVE_RESTART_FIXED_INDEX:
1324             setPrimitiveRestart(enabled);
1325             return;
1326         case GL_RASTERIZER_DISCARD:
1327             setRasterizerDiscard(enabled);
1328             return;
1329         case GL_SAMPLE_MASK:
1330             setSampleMaskEnabled(enabled);
1331             return;
1332         case GL_DEBUG_OUTPUT_SYNCHRONOUS:
1333             mDebug.setOutputSynchronous(enabled);
1334             return;
1335         case GL_DEBUG_OUTPUT:
1336             mDebug.setOutputEnabled(enabled);
1337             return;
1338         case GL_FRAMEBUFFER_SRGB_EXT:
1339             setFramebufferSRGB(enabled);
1340             return;
1341         case GL_TEXTURE_RECTANGLE_ANGLE:
1342             mTextureRectangleEnabled = enabled;
1343             return;
1344         case GL_SAMPLE_SHADING:
1345             setSampleShading(enabled);
1346             return;
1347         // GL_APPLE_clip_distance / GL_EXT_clip_cull_distance / GL_ANGLE_clip_cull_distance
1348         case GL_CLIP_DISTANCE0_EXT:
1349         case GL_CLIP_DISTANCE1_EXT:
1350         case GL_CLIP_DISTANCE2_EXT:
1351         case GL_CLIP_DISTANCE3_EXT:
1352         case GL_CLIP_DISTANCE4_EXT:
1353         case GL_CLIP_DISTANCE5_EXT:
1354         case GL_CLIP_DISTANCE6_EXT:
1355         case GL_CLIP_DISTANCE7_EXT:
1356             // NOTE(hqle): These enums are conflicted with GLES1's enums, need
1357             // to do additional check here:
1358             if (mClientVersion.major >= 2)
1359             {
1360                 setClipDistanceEnable(feature - GL_CLIP_DISTANCE0_EXT, enabled);
1361                 return;
1362             }
1363             break;
1364         case GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM:
1365             mShadingRatePreserveAspectRatio = enabled;
1366             return;
1367         case GL_FETCH_PER_SAMPLE_ARM:
1368             mFetchPerSample = enabled;
1369             return;
1370         default:
1371             break;
1372     }
1373 
1374     ASSERT(mClientVersion.major == 1);
1375 
1376     // GLES1 emulation. Need to separate from main switch due to conflict enum between
1377     // GL_CLIP_DISTANCE0_EXT & GL_CLIP_PLANE0
1378     switch (feature)
1379     {
1380         case GL_ALPHA_TEST:
1381             mGLES1State.mAlphaTestEnabled = enabled;
1382             break;
1383         case GL_TEXTURE_2D:
1384             mGLES1State.mTexUnitEnables[mActiveSampler].set(TextureType::_2D, enabled);
1385             break;
1386         case GL_TEXTURE_CUBE_MAP:
1387             mGLES1State.mTexUnitEnables[mActiveSampler].set(TextureType::CubeMap, enabled);
1388             break;
1389         case GL_LIGHTING:
1390             mGLES1State.mLightingEnabled = enabled;
1391             break;
1392         case GL_LIGHT0:
1393         case GL_LIGHT1:
1394         case GL_LIGHT2:
1395         case GL_LIGHT3:
1396         case GL_LIGHT4:
1397         case GL_LIGHT5:
1398         case GL_LIGHT6:
1399         case GL_LIGHT7:
1400             mGLES1State.mLights[feature - GL_LIGHT0].enabled = enabled;
1401             break;
1402         case GL_NORMALIZE:
1403             mGLES1State.mNormalizeEnabled = enabled;
1404             break;
1405         case GL_RESCALE_NORMAL:
1406             mGLES1State.mRescaleNormalEnabled = enabled;
1407             break;
1408         case GL_COLOR_MATERIAL:
1409             mGLES1State.mColorMaterialEnabled = enabled;
1410             break;
1411         case GL_CLIP_PLANE0:
1412         case GL_CLIP_PLANE1:
1413         case GL_CLIP_PLANE2:
1414         case GL_CLIP_PLANE3:
1415         case GL_CLIP_PLANE4:
1416         case GL_CLIP_PLANE5:
1417             mGLES1State.mClipPlanes[feature - GL_CLIP_PLANE0].enabled = enabled;
1418             break;
1419         case GL_FOG:
1420             mGLES1State.mFogEnabled = enabled;
1421             break;
1422         case GL_POINT_SMOOTH:
1423             mGLES1State.mPointSmoothEnabled = enabled;
1424             break;
1425         case GL_LINE_SMOOTH:
1426             mGLES1State.mLineSmoothEnabled = enabled;
1427             break;
1428         case GL_POINT_SPRITE_OES:
1429             mGLES1State.mPointSpriteEnabled = enabled;
1430             break;
1431         case GL_COLOR_LOGIC_OP:
1432             mGLES1State.setLogicOpEnabled(enabled);
1433             break;
1434         default:
1435             UNREACHABLE();
1436     }
1437 }
1438 
setEnableFeatureIndexed(GLenum feature,bool enabled,GLuint index)1439 void PrivateState::setEnableFeatureIndexed(GLenum feature, bool enabled, GLuint index)
1440 {
1441     switch (feature)
1442     {
1443         case GL_BLEND:
1444             setBlendIndexed(enabled, index);
1445             break;
1446         default:
1447             UNREACHABLE();
1448     }
1449 }
1450 
getEnableFeature(GLenum feature) const1451 bool PrivateState::getEnableFeature(GLenum feature) const
1452 {
1453     switch (feature)
1454     {
1455         case GL_MULTISAMPLE_EXT:
1456             return isMultisamplingEnabled();
1457         case GL_SAMPLE_ALPHA_TO_ONE_EXT:
1458             return isSampleAlphaToOneEnabled();
1459         case GL_CULL_FACE:
1460             return isCullFaceEnabled();
1461         case GL_POLYGON_OFFSET_POINT_NV:
1462             return isPolygonOffsetPointEnabled();
1463         case GL_POLYGON_OFFSET_LINE_NV:
1464             return isPolygonOffsetLineEnabled();
1465         case GL_POLYGON_OFFSET_FILL:
1466             return isPolygonOffsetFillEnabled();
1467         case GL_DEPTH_CLAMP_EXT:
1468             return isDepthClampEnabled();
1469         case GL_SAMPLE_ALPHA_TO_COVERAGE:
1470             return isSampleAlphaToCoverageEnabled();
1471         case GL_SAMPLE_COVERAGE:
1472             return isSampleCoverageEnabled();
1473         case GL_SCISSOR_TEST:
1474             return isScissorTestEnabled();
1475         case GL_STENCIL_TEST:
1476             return isStencilTestEnabled();
1477         case GL_DEPTH_TEST:
1478             return isDepthTestEnabled();
1479         case GL_BLEND:
1480             return isBlendEnabled();
1481         case GL_DITHER:
1482             return isDitherEnabled();
1483         case GL_COLOR_LOGIC_OP:
1484             if (mClientVersion.major == 1)
1485             {
1486                 // Handle logicOp in GLES1 through the GLES1 state management and emulation.
1487                 break;
1488             }
1489             return isLogicOpEnabled();
1490         case GL_PRIMITIVE_RESTART_FIXED_INDEX:
1491             return isPrimitiveRestartEnabled();
1492         case GL_RASTERIZER_DISCARD:
1493             return isRasterizerDiscardEnabled();
1494         case GL_SAMPLE_MASK:
1495             return isSampleMaskEnabled();
1496         case GL_DEBUG_OUTPUT_SYNCHRONOUS:
1497             return mDebug.isOutputSynchronous();
1498         case GL_DEBUG_OUTPUT:
1499             return mDebug.isOutputEnabled();
1500         case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
1501             return isBindGeneratesResourceEnabled();
1502         case GL_CLIENT_ARRAYS_ANGLE:
1503             return areClientArraysEnabled();
1504         case GL_FRAMEBUFFER_SRGB_EXT:
1505             return getFramebufferSRGB();
1506         case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1507             return mRobustResourceInit;
1508         case GL_PROGRAM_CACHE_ENABLED_ANGLE:
1509             return mProgramBinaryCacheEnabled;
1510         case GL_TEXTURE_RECTANGLE_ANGLE:
1511             return mTextureRectangleEnabled;
1512         case GL_SAMPLE_SHADING:
1513             return isSampleShadingEnabled();
1514         // GL_APPLE_clip_distance / GL_EXT_clip_cull_distance / GL_ANGLE_clip_cull_distance
1515         case GL_CLIP_DISTANCE0_EXT:
1516         case GL_CLIP_DISTANCE1_EXT:
1517         case GL_CLIP_DISTANCE2_EXT:
1518         case GL_CLIP_DISTANCE3_EXT:
1519         case GL_CLIP_DISTANCE4_EXT:
1520         case GL_CLIP_DISTANCE5_EXT:
1521         case GL_CLIP_DISTANCE6_EXT:
1522         case GL_CLIP_DISTANCE7_EXT:
1523             if (mClientVersion.major >= 2)
1524             {
1525                 // If GLES version is 1, the GL_CLIP_DISTANCE0_EXT enum will be used as
1526                 // GL_CLIP_PLANE0 instead.
1527                 return mClipDistancesEnabled.test(feature - GL_CLIP_DISTANCE0_EXT);
1528             }
1529             break;
1530         case GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM:
1531             return mShadingRatePreserveAspectRatio;
1532         case GL_FETCH_PER_SAMPLE_ARM:
1533             return mFetchPerSample;
1534     }
1535 
1536     ASSERT(mClientVersion.major == 1);
1537 
1538     switch (feature)
1539     {
1540         // GLES1 emulation
1541         case GL_ALPHA_TEST:
1542             return mGLES1State.mAlphaTestEnabled;
1543         case GL_VERTEX_ARRAY:
1544             return mGLES1State.mVertexArrayEnabled;
1545         case GL_NORMAL_ARRAY:
1546             return mGLES1State.mNormalArrayEnabled;
1547         case GL_COLOR_ARRAY:
1548             return mGLES1State.mColorArrayEnabled;
1549         case GL_POINT_SIZE_ARRAY_OES:
1550             return mGLES1State.mPointSizeArrayEnabled;
1551         case GL_TEXTURE_COORD_ARRAY:
1552             return mGLES1State.mTexCoordArrayEnabled[mGLES1State.mClientActiveTexture];
1553         case GL_TEXTURE_2D:
1554             return mGLES1State.isTextureTargetEnabled(getActiveSampler(), TextureType::_2D);
1555         case GL_TEXTURE_CUBE_MAP:
1556             return mGLES1State.isTextureTargetEnabled(getActiveSampler(), TextureType::CubeMap);
1557         case GL_LIGHTING:
1558             return mGLES1State.mLightingEnabled;
1559         case GL_LIGHT0:
1560         case GL_LIGHT1:
1561         case GL_LIGHT2:
1562         case GL_LIGHT3:
1563         case GL_LIGHT4:
1564         case GL_LIGHT5:
1565         case GL_LIGHT6:
1566         case GL_LIGHT7:
1567             return mGLES1State.mLights[feature - GL_LIGHT0].enabled;
1568         case GL_NORMALIZE:
1569             return mGLES1State.mNormalizeEnabled;
1570         case GL_RESCALE_NORMAL:
1571             return mGLES1State.mRescaleNormalEnabled;
1572         case GL_COLOR_MATERIAL:
1573             return mGLES1State.mColorMaterialEnabled;
1574         case GL_CLIP_PLANE0:
1575         case GL_CLIP_PLANE1:
1576         case GL_CLIP_PLANE2:
1577         case GL_CLIP_PLANE3:
1578         case GL_CLIP_PLANE4:
1579         case GL_CLIP_PLANE5:
1580             return mGLES1State.mClipPlanes[feature - GL_CLIP_PLANE0].enabled;
1581         case GL_FOG:
1582             return mGLES1State.mFogEnabled;
1583         case GL_POINT_SMOOTH:
1584             return mGLES1State.mPointSmoothEnabled;
1585         case GL_LINE_SMOOTH:
1586             return mGLES1State.mLineSmoothEnabled;
1587         case GL_POINT_SPRITE_OES:
1588             return mGLES1State.mPointSpriteEnabled;
1589         case GL_COLOR_LOGIC_OP:
1590             return mGLES1State.mLogicOpEnabled;
1591         default:
1592             UNREACHABLE();
1593             return false;
1594     }
1595 }
1596 
getEnableFeatureIndexed(GLenum feature,GLuint index) const1597 bool PrivateState::getEnableFeatureIndexed(GLenum feature, GLuint index) const
1598 {
1599     switch (feature)
1600     {
1601         case GL_BLEND:
1602             return isBlendEnabledIndexed(index);
1603         default:
1604             UNREACHABLE();
1605             return false;
1606     }
1607 }
1608 
getBooleanv(GLenum pname,GLboolean * params) const1609 void PrivateState::getBooleanv(GLenum pname, GLboolean *params) const
1610 {
1611     switch (pname)
1612     {
1613         case GL_SAMPLE_COVERAGE_INVERT:
1614             *params = mSampleCoverageInvert;
1615             break;
1616         case GL_DEPTH_WRITEMASK:
1617             *params = mDepthStencil.depthMask;
1618             break;
1619         case GL_COLOR_WRITEMASK:
1620         {
1621             // non-indexed get returns the state of draw buffer zero
1622             bool r, g, b, a;
1623             mBlendStateExt.getColorMaskIndexed(0, &r, &g, &b, &a);
1624             params[0] = r;
1625             params[1] = g;
1626             params[2] = b;
1627             params[3] = a;
1628             break;
1629         }
1630         case GL_CULL_FACE:
1631             *params = mRasterizer.cullFace;
1632             break;
1633         case GL_POLYGON_OFFSET_POINT_NV:
1634             *params = mRasterizer.polygonOffsetPoint;
1635             break;
1636         case GL_POLYGON_OFFSET_LINE_NV:
1637             *params = mRasterizer.polygonOffsetLine;
1638             break;
1639         case GL_POLYGON_OFFSET_FILL:
1640             *params = mRasterizer.polygonOffsetFill;
1641             break;
1642         case GL_DEPTH_CLAMP_EXT:
1643             *params = mRasterizer.depthClamp;
1644             break;
1645         case GL_SAMPLE_ALPHA_TO_COVERAGE:
1646             *params = mSampleAlphaToCoverage;
1647             break;
1648         case GL_SAMPLE_COVERAGE:
1649             *params = mSampleCoverage;
1650             break;
1651         case GL_SAMPLE_MASK:
1652             *params = mSampleMask;
1653             break;
1654         case GL_SCISSOR_TEST:
1655             *params = mScissorTest;
1656             break;
1657         case GL_STENCIL_TEST:
1658             *params = mDepthStencil.stencilTest;
1659             break;
1660         case GL_DEPTH_TEST:
1661             *params = mDepthStencil.depthTest;
1662             break;
1663         case GL_BLEND:
1664             // non-indexed get returns the state of draw buffer zero
1665             *params = mBlendStateExt.getEnabledMask().test(0);
1666             break;
1667         case GL_DITHER:
1668             *params = mRasterizer.dither;
1669             break;
1670         case GL_COLOR_LOGIC_OP:
1671             ASSERT(mClientVersion.major > 1);
1672             *params = mLogicOpEnabled;
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().tessellationShaderEXT;
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             UNREACHABLE();
1748             break;
1749     }
1750 }
1751 
getFloatv(GLenum pname,GLfloat * params) const1752 void PrivateState::getFloatv(GLenum pname, GLfloat *params) const
1753 {
1754     switch (pname)
1755     {
1756         case GL_LINE_WIDTH:
1757             *params = mLineWidth;
1758             break;
1759         case GL_SAMPLE_COVERAGE_VALUE:
1760             *params = mSampleCoverageValue;
1761             break;
1762         case GL_DEPTH_CLEAR_VALUE:
1763             *params = mDepthClearValue;
1764             break;
1765         case GL_POLYGON_OFFSET_FACTOR:
1766             *params = mRasterizer.polygonOffsetFactor;
1767             break;
1768         case GL_POLYGON_OFFSET_UNITS:
1769             *params = mRasterizer.polygonOffsetUnits;
1770             break;
1771         case GL_POLYGON_OFFSET_CLAMP_EXT:
1772             *params = mRasterizer.polygonOffsetClamp;
1773             break;
1774         case GL_DEPTH_RANGE:
1775             params[0] = mNearZ;
1776             params[1] = mFarZ;
1777             break;
1778         case GL_COLOR_CLEAR_VALUE:
1779             params[0] = mColorClearValue.red;
1780             params[1] = mColorClearValue.green;
1781             params[2] = mColorClearValue.blue;
1782             params[3] = mColorClearValue.alpha;
1783             break;
1784         case GL_BLEND_COLOR:
1785             params[0] = mBlendColor.red;
1786             params[1] = mBlendColor.green;
1787             params[2] = mBlendColor.blue;
1788             params[3] = mBlendColor.alpha;
1789             break;
1790         case GL_MULTISAMPLE_EXT:
1791             *params = static_cast<GLfloat>(mMultiSampling);
1792             break;
1793         case GL_SAMPLE_ALPHA_TO_ONE_EXT:
1794             *params = static_cast<GLfloat>(mSampleAlphaToOne);
1795             break;
1796         case GL_COVERAGE_MODULATION_CHROMIUM:
1797             params[0] = static_cast<GLfloat>(mCoverageModulation);
1798             break;
1799         case GL_ALPHA_TEST_REF:
1800             *params = mGLES1State.mAlphaTestParameters.ref;
1801             break;
1802         case GL_CURRENT_COLOR:
1803         {
1804             const auto &color = mGLES1State.mCurrentColor;
1805             params[0]         = color.red;
1806             params[1]         = color.green;
1807             params[2]         = color.blue;
1808             params[3]         = color.alpha;
1809             break;
1810         }
1811         case GL_CURRENT_NORMAL:
1812         {
1813             const auto &normal = mGLES1State.mCurrentNormal;
1814             params[0]          = normal[0];
1815             params[1]          = normal[1];
1816             params[2]          = normal[2];
1817             break;
1818         }
1819         case GL_CURRENT_TEXTURE_COORDS:
1820         {
1821             const auto &texcoord = mGLES1State.mCurrentTextureCoords[mActiveSampler];
1822             params[0]            = texcoord.s;
1823             params[1]            = texcoord.t;
1824             params[2]            = texcoord.r;
1825             params[3]            = texcoord.q;
1826             break;
1827         }
1828         case GL_MODELVIEW_MATRIX:
1829             memcpy(params, mGLES1State.mModelviewMatrices.back().constData(), 16 * sizeof(GLfloat));
1830             break;
1831         case GL_PROJECTION_MATRIX:
1832             memcpy(params, mGLES1State.mProjectionMatrices.back().constData(),
1833                    16 * sizeof(GLfloat));
1834             break;
1835         case GL_TEXTURE_MATRIX:
1836             memcpy(params, mGLES1State.mTextureMatrices[mActiveSampler].back().constData(),
1837                    16 * sizeof(GLfloat));
1838             break;
1839         case GL_LIGHT_MODEL_AMBIENT:
1840             GetLightModelParameters(&mGLES1State, pname, params);
1841             break;
1842         case GL_FOG_MODE:
1843         case GL_FOG_DENSITY:
1844         case GL_FOG_START:
1845         case GL_FOG_END:
1846         case GL_FOG_COLOR:
1847             GetFogParameters(&mGLES1State, pname, params);
1848             break;
1849         case GL_POINT_SIZE:
1850             GetPointSize(&mGLES1State, params);
1851             break;
1852         case GL_POINT_SIZE_MIN:
1853         case GL_POINT_SIZE_MAX:
1854         case GL_POINT_FADE_THRESHOLD_SIZE:
1855         case GL_POINT_DISTANCE_ATTENUATION:
1856             GetPointParameter(&mGLES1State, FromGLenum<PointParameter>(pname), params);
1857             break;
1858         case GL_MIN_SAMPLE_SHADING_VALUE:
1859             *params = mMinSampleShading;
1860             break;
1861         // GL_ARM_shader_framebuffer_fetch
1862         case GL_FETCH_PER_SAMPLE_ARM:
1863             *params = mFetchPerSample ? 1.0f : 0.0f;
1864             break;
1865         // GL_ARM_shader_framebuffer_fetch
1866         case GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM:
1867             *params = mCaps.fragmentShaderFramebufferFetchMRT ? 1.0f : 0.0f;
1868             break;
1869         default:
1870             UNREACHABLE();
1871             break;
1872     }
1873 }
1874 
getIntegerv(GLenum pname,GLint * params) const1875 void PrivateState::getIntegerv(GLenum pname, GLint *params) const
1876 {
1877     // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1878     // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1879     // GetIntegerv as its native query function. As it would require conversion in any
1880     // case, this should make no difference to the calling application. You may find it in
1881     // State::getFloatv.
1882     switch (pname)
1883     {
1884         case GL_PACK_ALIGNMENT:
1885             *params = mPack.alignment;
1886             break;
1887         case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
1888             *params = mPack.reverseRowOrder;
1889             break;
1890         case GL_PACK_ROW_LENGTH:
1891             *params = mPack.rowLength;
1892             break;
1893         case GL_PACK_SKIP_ROWS:
1894             *params = mPack.skipRows;
1895             break;
1896         case GL_PACK_SKIP_PIXELS:
1897             *params = mPack.skipPixels;
1898             break;
1899         case GL_UNPACK_ALIGNMENT:
1900             *params = mUnpack.alignment;
1901             break;
1902         case GL_UNPACK_ROW_LENGTH:
1903             *params = mUnpack.rowLength;
1904             break;
1905         case GL_UNPACK_IMAGE_HEIGHT:
1906             *params = mUnpack.imageHeight;
1907             break;
1908         case GL_UNPACK_SKIP_IMAGES:
1909             *params = mUnpack.skipImages;
1910             break;
1911         case GL_UNPACK_SKIP_ROWS:
1912             *params = mUnpack.skipRows;
1913             break;
1914         case GL_UNPACK_SKIP_PIXELS:
1915             *params = mUnpack.skipPixels;
1916             break;
1917         case GL_GENERATE_MIPMAP_HINT:
1918             *params = mGenerateMipmapHint;
1919             break;
1920         case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
1921             *params = mTextureFilteringHint;
1922             break;
1923         case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
1924             *params = mFragmentShaderDerivativeHint;
1925             break;
1926         case GL_ACTIVE_TEXTURE:
1927             *params = (static_cast<GLint>(mActiveSampler) + GL_TEXTURE0);
1928             break;
1929         case GL_STENCIL_FUNC:
1930             *params = mDepthStencil.stencilFunc;
1931             break;
1932         case GL_STENCIL_REF:
1933             *params = mStencilRef;
1934             break;
1935         case GL_STENCIL_VALUE_MASK:
1936             *params = CastMaskValue(mDepthStencil.stencilMask);
1937             break;
1938         case GL_STENCIL_BACK_FUNC:
1939             *params = mDepthStencil.stencilBackFunc;
1940             break;
1941         case GL_STENCIL_BACK_REF:
1942             *params = mStencilBackRef;
1943             break;
1944         case GL_STENCIL_BACK_VALUE_MASK:
1945             *params = CastMaskValue(mDepthStencil.stencilBackMask);
1946             break;
1947         case GL_STENCIL_FAIL:
1948             *params = mDepthStencil.stencilFail;
1949             break;
1950         case GL_STENCIL_PASS_DEPTH_FAIL:
1951             *params = mDepthStencil.stencilPassDepthFail;
1952             break;
1953         case GL_STENCIL_PASS_DEPTH_PASS:
1954             *params = mDepthStencil.stencilPassDepthPass;
1955             break;
1956         case GL_STENCIL_BACK_FAIL:
1957             *params = mDepthStencil.stencilBackFail;
1958             break;
1959         case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1960             *params = mDepthStencil.stencilBackPassDepthFail;
1961             break;
1962         case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1963             *params = mDepthStencil.stencilBackPassDepthPass;
1964             break;
1965         case GL_DEPTH_FUNC:
1966             *params = mDepthStencil.depthFunc;
1967             break;
1968         case GL_BLEND_SRC_RGB:
1969             // non-indexed get returns the state of draw buffer zero
1970             *params = mBlendStateExt.getSrcColorIndexed(0);
1971             break;
1972         case GL_BLEND_SRC_ALPHA:
1973             *params = mBlendStateExt.getSrcAlphaIndexed(0);
1974             break;
1975         case GL_BLEND_DST_RGB:
1976             *params = mBlendStateExt.getDstColorIndexed(0);
1977             break;
1978         case GL_BLEND_DST_ALPHA:
1979             *params = mBlendStateExt.getDstAlphaIndexed(0);
1980             break;
1981         case GL_BLEND_EQUATION_RGB:
1982             *params = mBlendStateExt.getEquationColorIndexed(0);
1983             break;
1984         case GL_BLEND_EQUATION_ALPHA:
1985             *params = mBlendStateExt.getEquationAlphaIndexed(0);
1986             break;
1987         case GL_STENCIL_WRITEMASK:
1988             *params = CastMaskValue(mDepthStencil.stencilWritemask);
1989             break;
1990         case GL_STENCIL_BACK_WRITEMASK:
1991             *params = CastMaskValue(mDepthStencil.stencilBackWritemask);
1992             break;
1993         case GL_STENCIL_CLEAR_VALUE:
1994             *params = mStencilClearValue;
1995             break;
1996         case GL_VIEWPORT:
1997             params[0] = mViewport.x;
1998             params[1] = mViewport.y;
1999             params[2] = mViewport.width;
2000             params[3] = mViewport.height;
2001             break;
2002         case GL_SCISSOR_BOX:
2003             params[0] = mScissor.x;
2004             params[1] = mScissor.y;
2005             params[2] = mScissor.width;
2006             params[3] = mScissor.height;
2007             break;
2008         case GL_POLYGON_MODE_NV:
2009             *params = ToGLenum(mRasterizer.polygonMode);
2010             break;
2011         case GL_CULL_FACE_MODE:
2012             *params = ToGLenum(mRasterizer.cullMode);
2013             break;
2014         case GL_FRONT_FACE:
2015             *params = mRasterizer.frontFace;
2016             break;
2017 
2018         case GL_MULTISAMPLE_EXT:
2019             *params = static_cast<GLint>(mMultiSampling);
2020             break;
2021         case GL_SAMPLE_ALPHA_TO_ONE_EXT:
2022             *params = static_cast<GLint>(mSampleAlphaToOne);
2023             break;
2024         case GL_COVERAGE_MODULATION_CHROMIUM:
2025             *params = static_cast<GLint>(mCoverageModulation);
2026             break;
2027         case GL_ALPHA_TEST_FUNC:
2028             *params = ToGLenum(mGLES1State.mAlphaTestParameters.func);
2029             break;
2030         case GL_CLIENT_ACTIVE_TEXTURE:
2031             *params = mGLES1State.mClientActiveTexture + GL_TEXTURE0;
2032             break;
2033         case GL_MATRIX_MODE:
2034             *params = ToGLenum(mGLES1State.mMatrixMode);
2035             break;
2036         case GL_SHADE_MODEL:
2037             *params = ToGLenum(mGLES1State.mShadeModel);
2038             break;
2039         case GL_MODELVIEW_STACK_DEPTH:
2040         case GL_PROJECTION_STACK_DEPTH:
2041         case GL_TEXTURE_STACK_DEPTH:
2042             *params = mGLES1State.getCurrentMatrixStackDepth(pname);
2043             break;
2044         case GL_LOGIC_OP_MODE:
2045             *params = ToGLenum(mGLES1State.mLogicOp);
2046             break;
2047         case GL_BLEND_SRC:
2048             // non-indexed get returns the state of draw buffer zero
2049             *params = mBlendStateExt.getSrcColorIndexed(0);
2050             break;
2051         case GL_BLEND_DST:
2052             *params = mBlendStateExt.getDstColorIndexed(0);
2053             break;
2054         case GL_PERSPECTIVE_CORRECTION_HINT:
2055         case GL_POINT_SMOOTH_HINT:
2056         case GL_LINE_SMOOTH_HINT:
2057         case GL_FOG_HINT:
2058             *params = mGLES1State.getHint(pname);
2059             break;
2060 
2061         // GL_ANGLE_provoking_vertex
2062         case GL_PROVOKING_VERTEX_ANGLE:
2063             *params = ToGLenum(mProvokingVertex);
2064             break;
2065 
2066         case GL_PATCH_VERTICES:
2067             *params = mPatchVertices;
2068             break;
2069 
2070         // GL_EXT_clip_control
2071         case GL_CLIP_ORIGIN_EXT:
2072             *params = ToGLenum(mClipOrigin);
2073             break;
2074         case GL_CLIP_DEPTH_MODE_EXT:
2075             *params = ToGLenum(mClipDepthMode);
2076             break;
2077 
2078         // GL_QCOM_shading_rate
2079         case GL_SHADING_RATE_QCOM:
2080             *params = ToGLenum(mShadingRate);
2081             break;
2082 
2083         // GL_ANGLE_shader_pixel_local_storage
2084         case GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE:
2085             *params = mPixelLocalStorageActivePlanes;
2086             break;
2087 
2088         // GL_ARM_shader_framebuffer_fetch
2089         case GL_FETCH_PER_SAMPLE_ARM:
2090             *params = mFetchPerSample ? 1 : 0;
2091             break;
2092 
2093         // GL_ARM_shader_framebuffer_fetch
2094         case GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM:
2095             *params = mCaps.fragmentShaderFramebufferFetchMRT ? 1 : 0;
2096             break;
2097 
2098         default:
2099             UNREACHABLE();
2100             break;
2101     }
2102 }
2103 
getIntegeri_v(GLenum target,GLuint index,GLint * data) const2104 void PrivateState::getIntegeri_v(GLenum target, GLuint index, GLint *data) const
2105 {
2106     switch (target)
2107     {
2108         case GL_BLEND_SRC_RGB:
2109             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2110             *data = mBlendStateExt.getSrcColorIndexed(index);
2111             break;
2112         case GL_BLEND_SRC_ALPHA:
2113             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2114             *data = mBlendStateExt.getSrcAlphaIndexed(index);
2115             break;
2116         case GL_BLEND_DST_RGB:
2117             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2118             *data = mBlendStateExt.getDstColorIndexed(index);
2119             break;
2120         case GL_BLEND_DST_ALPHA:
2121             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2122             *data = mBlendStateExt.getDstAlphaIndexed(index);
2123             break;
2124         case GL_BLEND_EQUATION_RGB:
2125             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2126             *data = mBlendStateExt.getEquationColorIndexed(index);
2127             break;
2128         case GL_BLEND_EQUATION_ALPHA:
2129             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2130             *data = mBlendStateExt.getEquationAlphaIndexed(index);
2131             break;
2132         case GL_SAMPLE_MASK_VALUE:
2133             ASSERT(static_cast<size_t>(index) < mSampleMaskValues.size());
2134             *data = mSampleMaskValues[index];
2135             break;
2136         default:
2137             UNREACHABLE();
2138             break;
2139     }
2140 }
2141 
getBooleani_v(GLenum target,GLuint index,GLboolean * data) const2142 void PrivateState::getBooleani_v(GLenum target, GLuint index, GLboolean *data) const
2143 {
2144     switch (target)
2145     {
2146         case GL_COLOR_WRITEMASK:
2147         {
2148             ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
2149             bool r, g, b, a;
2150             mBlendStateExt.getColorMaskIndexed(index, &r, &g, &b, &a);
2151             data[0] = r;
2152             data[1] = g;
2153             data[2] = b;
2154             data[3] = a;
2155             break;
2156         }
2157         default:
2158             UNREACHABLE();
2159             break;
2160     }
2161 }
2162 
State(const State * shareContextState,egl::ShareGroup * shareGroup,TextureManager * shareTextures,SemaphoreManager * shareSemaphores,egl::ContextMutex * sharedContextMutex,egl::SingleContextMutex * singleContextMutex,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)2163 State::State(const State *shareContextState,
2164              egl::ShareGroup *shareGroup,
2165              TextureManager *shareTextures,
2166              SemaphoreManager *shareSemaphores,
2167              egl::ContextMutex *sharedContextMutex,
2168              egl::SingleContextMutex *singleContextMutex,
2169              const OverlayType *overlay,
2170              const EGLenum clientType,
2171              const Version &clientVersion,
2172              EGLint profileMask,
2173              bool debug,
2174              bool bindGeneratesResourceCHROMIUM,
2175              bool clientArraysEnabled,
2176              bool robustResourceInit,
2177              bool programBinaryCacheEnabled,
2178              EGLenum contextPriority,
2179              bool hasRobustAccess,
2180              bool hasProtectedContent)
2181     : mID({gIDCounter++}),
2182       mContextPriority(contextPriority),
2183       mHasRobustAccess(hasRobustAccess),
2184       mHasProtectedContent(hasProtectedContent),
2185       mIsDebugContext(debug),
2186       mShareGroup(shareGroup),
2187       mSharedContextMutex(sharedContextMutex),
2188       mSingleContextMutex(singleContextMutex),
2189       mContextMutex(singleContextMutex == nullptr ? sharedContextMutex : singleContextMutex),
2190       mIsSharedContextMutexActive(singleContextMutex == nullptr),
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       mExecutable(nullptr),
2213       mVertexArray(nullptr),
2214       mDisplayTextureShareGroup(shareTextures != nullptr),
2215       mMaxShaderCompilerThreads(std::numeric_limits<GLuint>::max()),
2216       mOverlay(overlay),
2217       mPrivateState(clientType,
2218                     clientVersion,
2219                     profileMask,
2220                     debug,
2221                     bindGeneratesResourceCHROMIUM,
2222                     clientArraysEnabled,
2223                     robustResourceInit,
2224                     programBinaryCacheEnabled)
2225 {}
2226 
~State()2227 State::~State() {}
2228 
initialize(Context * context)2229 void State::initialize(Context *context)
2230 {
2231     const Extensions &nativeExtensions = context->getImplementation()->getNativeExtensions();
2232     const Version &clientVersion       = context->getClientVersion();
2233 
2234     mPrivateState.initialize(context);
2235 
2236     mUniformBuffers.resize(getCaps().maxUniformBufferBindings);
2237 
2238     mSamplerTextures[TextureType::_2D].resize(getCaps().maxCombinedTextureImageUnits);
2239     mSamplerTextures[TextureType::CubeMap].resize(getCaps().maxCombinedTextureImageUnits);
2240     if (clientVersion >= Version(3, 0) || nativeExtensions.texture3DOES)
2241     {
2242         mSamplerTextures[TextureType::_3D].resize(getCaps().maxCombinedTextureImageUnits);
2243     }
2244     if (clientVersion >= Version(3, 0))
2245     {
2246         mSamplerTextures[TextureType::_2DArray].resize(getCaps().maxCombinedTextureImageUnits);
2247     }
2248     if (clientVersion >= Version(3, 1) || nativeExtensions.textureMultisampleANGLE)
2249     {
2250         mSamplerTextures[TextureType::_2DMultisample].resize(
2251             getCaps().maxCombinedTextureImageUnits);
2252     }
2253     if (clientVersion >= Version(3, 1))
2254     {
2255         mSamplerTextures[TextureType::_2DMultisampleArray].resize(
2256             getCaps().maxCombinedTextureImageUnits);
2257 
2258         mAtomicCounterBuffers.resize(getCaps().maxAtomicCounterBufferBindings);
2259         mShaderStorageBuffers.resize(getCaps().maxShaderStorageBufferBindings);
2260     }
2261     if (clientVersion >= Version(3, 1) ||
2262         (context->getImplementation()->getNativePixelLocalStorageOptions().type ==
2263          ShPixelLocalStorageType::ImageLoadStore))
2264     {
2265         mImageUnits.resize(getCaps().maxImageUnits);
2266     }
2267     if (clientVersion >= Version(3, 1) || nativeExtensions.textureCubeMapArrayAny())
2268     {
2269         mSamplerTextures[TextureType::CubeMapArray].resize(getCaps().maxCombinedTextureImageUnits);
2270     }
2271     if (clientVersion >= Version(3, 1) || nativeExtensions.textureCubeMapArrayAny())
2272     {
2273         mSamplerTextures[TextureType::Buffer].resize(getCaps().maxCombinedTextureImageUnits);
2274     }
2275     if (nativeExtensions.textureRectangleANGLE)
2276     {
2277         mSamplerTextures[TextureType::Rectangle].resize(getCaps().maxCombinedTextureImageUnits);
2278     }
2279     if (nativeExtensions.EGLImageExternalOES || nativeExtensions.EGLStreamConsumerExternalNV)
2280     {
2281         mSamplerTextures[TextureType::External].resize(getCaps().maxCombinedTextureImageUnits);
2282     }
2283     if (nativeExtensions.videoTextureWEBGL)
2284     {
2285         mSamplerTextures[TextureType::VideoImage].resize(getCaps().maxCombinedTextureImageUnits);
2286     }
2287     mCompleteTextureBindings.reserve(getCaps().maxCombinedTextureImageUnits);
2288     for (int32_t textureIndex = 0; textureIndex < getCaps().maxCombinedTextureImageUnits;
2289          ++textureIndex)
2290     {
2291         mCompleteTextureBindings.emplace_back(context, textureIndex);
2292     }
2293 
2294     mSamplers.resize(getCaps().maxCombinedTextureImageUnits);
2295 
2296     for (QueryType type : angle::AllEnums<QueryType>())
2297     {
2298         mActiveQueries[type].set(context, nullptr);
2299     }
2300 
2301     mProgram    = nullptr;
2302     mExecutable = nullptr;
2303 
2304     mReadFramebuffer = nullptr;
2305     mDrawFramebuffer = nullptr;
2306 
2307     getDebug().setMaxLoggedMessages(getCaps().maxDebugLoggedMessages);
2308 }
2309 
reset(const Context * context)2310 void State::reset(const Context *context)
2311 {
2312     // Force a sync so clear doesn't end up dereferencing stale pointers.
2313     (void)syncActiveTextures(context, Command::Other);
2314     mActiveTexturesCache.clear();
2315 
2316     for (TextureBindingVector &bindingVec : mSamplerTextures)
2317     {
2318         for (BindingPointer<Texture> &texBinding : bindingVec)
2319         {
2320             texBinding.set(context, nullptr);
2321         }
2322     }
2323     for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++)
2324     {
2325         mSamplers[samplerIdx].set(context, nullptr);
2326     }
2327 
2328     for (ImageUnit &imageUnit : mImageUnits)
2329     {
2330         imageUnit.texture.set(context, nullptr);
2331         imageUnit.level   = 0;
2332         imageUnit.layered = false;
2333         imageUnit.layer   = 0;
2334         imageUnit.access  = GL_READ_ONLY;
2335         imageUnit.format  = GL_R32UI;
2336     }
2337 
2338     mRenderbuffer.set(context, nullptr);
2339 
2340     for (BufferBinding type : angle::AllEnums<BufferBinding>())
2341     {
2342         UpdateBufferBinding(context, &mBoundBuffers[type], nullptr, type);
2343     }
2344 
2345     if (mProgram)
2346     {
2347         mProgram->release(context);
2348     }
2349     mProgram = nullptr;
2350     mProgramPipeline.set(context, nullptr);
2351     mExecutable = nullptr;
2352 
2353     if (mTransformFeedback.get())
2354     {
2355         mTransformFeedback->onBindingChanged(context, false);
2356     }
2357     mTransformFeedback.set(context, nullptr);
2358 
2359     for (QueryType type : angle::AllEnums<QueryType>())
2360     {
2361         mActiveQueries[type].set(context, nullptr);
2362     }
2363 
2364     for (OffsetBindingPointer<Buffer> &buf : mUniformBuffers)
2365     {
2366         UpdateIndexedBufferBinding(context, &buf, nullptr, BufferBinding::Uniform, 0, 0);
2367     }
2368     mBoundUniformBuffersMask.reset();
2369 
2370     for (OffsetBindingPointer<Buffer> &buf : mAtomicCounterBuffers)
2371     {
2372         UpdateIndexedBufferBinding(context, &buf, nullptr, BufferBinding::AtomicCounter, 0, 0);
2373     }
2374     mBoundAtomicCounterBuffersMask.reset();
2375 
2376     for (OffsetBindingPointer<Buffer> &buf : mShaderStorageBuffers)
2377     {
2378         UpdateIndexedBufferBinding(context, &buf, nullptr, BufferBinding::ShaderStorage, 0, 0);
2379     }
2380     mBoundShaderStorageBuffersMask.reset();
2381 
2382     mPrivateState.reset();
2383 
2384     setAllDirtyBits();
2385 }
2386 
unsetActiveTextures(const ActiveTextureMask & textureMask)2387 ANGLE_INLINE void State::unsetActiveTextures(const ActiveTextureMask &textureMask)
2388 {
2389     // Unset any relevant bound textures.
2390     for (size_t textureIndex : textureMask)
2391     {
2392         mActiveTexturesCache.reset(textureIndex);
2393         mCompleteTextureBindings[textureIndex].reset();
2394     }
2395 }
2396 
updateActiveTextureStateOnSync(const Context * context,size_t textureIndex,const Sampler * sampler,Texture * texture)2397 ANGLE_INLINE void State::updateActiveTextureStateOnSync(const Context *context,
2398                                                         size_t textureIndex,
2399                                                         const Sampler *sampler,
2400                                                         Texture *texture)
2401 {
2402     if (!texture || !texture->isSamplerComplete(context, sampler))
2403     {
2404         mActiveTexturesCache.reset(textureIndex);
2405     }
2406     else
2407     {
2408         mActiveTexturesCache.set(textureIndex, texture);
2409     }
2410 
2411     mDirtyBits.set(state::DIRTY_BIT_TEXTURE_BINDINGS);
2412 }
2413 
setActiveTextureDirty(size_t textureIndex,Texture * texture)2414 ANGLE_INLINE void State::setActiveTextureDirty(size_t textureIndex, Texture *texture)
2415 {
2416     mDirtyObjects.set(state::DIRTY_OBJECT_ACTIVE_TEXTURES);
2417     mDirtyActiveTextures.set(textureIndex);
2418 
2419     if (!texture)
2420     {
2421         return;
2422     }
2423 
2424     if (texture->hasAnyDirtyBit())
2425     {
2426         setTextureDirty(textureIndex);
2427     }
2428 
2429     if (isRobustResourceInitEnabled() && texture->initState() == InitState::MayNeedInit)
2430     {
2431         mDirtyObjects.set(state::DIRTY_OBJECT_TEXTURES_INIT);
2432     }
2433 
2434     // This cache is updated immediately because we use the cache in the validation layer.
2435     // If we defer the update until syncState it's too late and we've already passed validation.
2436     if (texture && mExecutable)
2437     {
2438         // It is invalid to try to sample a non-yuv texture with a yuv sampler.
2439         mTexturesIncompatibleWithSamplers[textureIndex] =
2440             mExecutable->getActiveYUVSamplers().test(textureIndex) && !texture->isYUV();
2441 
2442         if (isWebGL())
2443         {
2444             const Sampler *sampler = mSamplers[textureIndex].get();
2445             const SamplerState &samplerState =
2446                 sampler ? sampler->getSamplerState() : texture->getSamplerState();
2447             if (!texture->getTextureState().compatibleWithSamplerFormatForWebGL(
2448                     mExecutable->getSamplerFormatForTextureUnitIndex(textureIndex), samplerState))
2449             {
2450                 mTexturesIncompatibleWithSamplers[textureIndex] = true;
2451             }
2452         }
2453     }
2454     else
2455     {
2456         mTexturesIncompatibleWithSamplers[textureIndex] = false;
2457     }
2458 }
2459 
updateTextureBinding(const Context * context,size_t textureIndex,Texture * texture)2460 ANGLE_INLINE void State::updateTextureBinding(const Context *context,
2461                                               size_t textureIndex,
2462                                               Texture *texture)
2463 {
2464     mCompleteTextureBindings[textureIndex].bind(texture);
2465     mActiveTexturesCache.reset(textureIndex);
2466     setActiveTextureDirty(textureIndex, texture);
2467 }
2468 
allActiveDrawBufferChannelsMasked() const2469 bool State::allActiveDrawBufferChannelsMasked() const
2470 {
2471     // Compare current color mask with all-disabled color mask, while ignoring disabled draw
2472     // buffers.
2473     return (getBlendStateExt().compareColorMask(0) & mDrawFramebuffer->getDrawBufferMask()).none();
2474 }
2475 
anyActiveDrawBufferChannelMasked() const2476 bool State::anyActiveDrawBufferChannelMasked() const
2477 {
2478     // Compare current color mask with all-enabled color mask, while ignoring disabled draw
2479     // buffers.
2480     return (getBlendStateExt().compareColorMask(getBlendStateExt().getAllColorMaskBits()) &
2481             mDrawFramebuffer->getDrawBufferMask())
2482         .any();
2483 }
2484 
setSamplerTexture(const Context * context,TextureType type,Texture * texture)2485 void State::setSamplerTexture(const Context *context, TextureType type, Texture *texture)
2486 {
2487     if (mExecutable && mExecutable->getActiveSamplersMask()[getActiveSampler()] &&
2488         IsTextureCompatibleWithSampler(type,
2489                                        mExecutable->getActiveSamplerTypes()[getActiveSampler()]))
2490     {
2491         updateTextureBinding(context, getActiveSampler(), texture);
2492     }
2493 
2494     mSamplerTextures[type][getActiveSampler()].set(context, texture);
2495 
2496     mDirtyBits.set(state::DIRTY_BIT_TEXTURE_BINDINGS);
2497 }
2498 
getTargetTexture(TextureType type) const2499 Texture *State::getTargetTexture(TextureType type) const
2500 {
2501     return getSamplerTexture(getActiveSampler(), type);
2502 }
2503 
getSamplerTextureId(unsigned int sampler,TextureType type) const2504 TextureID State::getSamplerTextureId(unsigned int sampler, TextureType type) const
2505 {
2506     ASSERT(sampler < mSamplerTextures[type].size());
2507     return mSamplerTextures[type][sampler].id();
2508 }
2509 
detachTexture(Context * context,const TextureMap & zeroTextures,TextureID texture)2510 void State::detachTexture(Context *context, const TextureMap &zeroTextures, TextureID texture)
2511 {
2512     // Textures have a detach method on State rather than a simple
2513     // removeBinding, because the zero/null texture objects are managed
2514     // separately, and don't have to go through the Context's maps or
2515     // the ResourceManager.
2516 
2517     // [OpenGL ES 2.0.24] section 3.8 page 84:
2518     // If a texture object is deleted, it is as if all texture units which are bound to that texture
2519     // object are rebound to texture object zero
2520 
2521     for (TextureType type : angle::AllEnums<TextureType>())
2522     {
2523         TextureBindingVector &textureVector = mSamplerTextures[type];
2524 
2525         for (size_t bindingIndex = 0; bindingIndex < textureVector.size(); ++bindingIndex)
2526         {
2527             BindingPointer<Texture> &binding = textureVector[bindingIndex];
2528             if (binding.id() == texture)
2529             {
2530                 // Zero textures are the "default" textures instead of NULL
2531                 Texture *zeroTexture = zeroTextures[type].get();
2532                 ASSERT(zeroTexture != nullptr);
2533                 if (mCompleteTextureBindings[bindingIndex].getSubject() == binding.get())
2534                 {
2535                     updateTextureBinding(context, bindingIndex, zeroTexture);
2536                 }
2537                 binding.set(context, zeroTexture);
2538             }
2539         }
2540     }
2541 
2542     for (auto &bindingImageUnit : mImageUnits)
2543     {
2544         if (bindingImageUnit.texture.id() == texture)
2545         {
2546             bindingImageUnit.texture.set(context, nullptr);
2547             bindingImageUnit.level   = 0;
2548             bindingImageUnit.layered = false;
2549             bindingImageUnit.layer   = 0;
2550             bindingImageUnit.access  = GL_READ_ONLY;
2551             bindingImageUnit.format  = GL_R32UI;
2552         }
2553     }
2554 
2555     // [OpenGL ES 2.0.24] section 4.4 page 112:
2556     // If a texture object is deleted while its image is attached to the currently bound
2557     // framebuffer, then it is as if Texture2DAttachment had been called, with a texture of 0, for
2558     // each attachment point to which this image was attached in the currently bound framebuffer.
2559 
2560     if (mReadFramebuffer && mReadFramebuffer->detachTexture(context, texture))
2561     {
2562         mDirtyObjects.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
2563     }
2564 
2565     if (mDrawFramebuffer && mDrawFramebuffer->detachTexture(context, texture))
2566     {
2567         setDrawFramebufferDirty();
2568     }
2569 }
2570 
initializeZeroTextures(const Context * context,const TextureMap & zeroTextures)2571 void State::initializeZeroTextures(const Context *context, const TextureMap &zeroTextures)
2572 {
2573     for (TextureType type : angle::AllEnums<TextureType>())
2574     {
2575         for (size_t textureUnit = 0; textureUnit < mSamplerTextures[type].size(); ++textureUnit)
2576         {
2577             mSamplerTextures[type][textureUnit].set(context, zeroTextures[type].get());
2578         }
2579     }
2580 }
2581 
invalidateTextureBindings(TextureType type)2582 void State::invalidateTextureBindings(TextureType type)
2583 {
2584     mDirtyBits.set(state::DIRTY_BIT_TEXTURE_BINDINGS);
2585 }
2586 
setSamplerBinding(const Context * context,GLuint textureUnit,Sampler * sampler)2587 void State::setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler)
2588 {
2589     if (mSamplers[textureUnit].get() == sampler)
2590     {
2591         return;
2592     }
2593 
2594     mSamplers[textureUnit].set(context, sampler);
2595     mDirtyBits.set(state::DIRTY_BIT_SAMPLER_BINDINGS);
2596     // This is overly conservative as it assumes the sampler has never been bound.
2597     setSamplerDirty(textureUnit);
2598     onActiveTextureChange(context, textureUnit);
2599 }
2600 
detachSampler(const Context * context,SamplerID sampler)2601 void State::detachSampler(const Context *context, SamplerID sampler)
2602 {
2603     // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124:
2604     // If a sampler object that is currently bound to one or more texture units is
2605     // deleted, it is as though BindSampler is called once for each texture unit to
2606     // which the sampler is bound, with unit set to the texture unit and sampler set to zero.
2607     for (size_t i = 0; i < mSamplers.size(); i++)
2608     {
2609         if (mSamplers[i].id() == sampler)
2610         {
2611             setSamplerBinding(context, static_cast<GLuint>(i), nullptr);
2612         }
2613     }
2614 }
2615 
setRenderbufferBinding(const Context * context,Renderbuffer * renderbuffer)2616 void State::setRenderbufferBinding(const Context *context, Renderbuffer *renderbuffer)
2617 {
2618     mRenderbuffer.set(context, renderbuffer);
2619     mDirtyBits.set(state::DIRTY_BIT_RENDERBUFFER_BINDING);
2620 }
2621 
detachRenderbuffer(Context * context,RenderbufferID renderbuffer)2622 void State::detachRenderbuffer(Context *context, RenderbufferID renderbuffer)
2623 {
2624     // [OpenGL ES 2.0.24] section 4.4 page 109:
2625     // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though
2626     // BindRenderbuffer had been executed with the target RENDERBUFFER and name of zero.
2627 
2628     if (mRenderbuffer.id() == renderbuffer)
2629     {
2630         setRenderbufferBinding(context, nullptr);
2631     }
2632 
2633     // [OpenGL ES 2.0.24] section 4.4 page 111:
2634     // If a renderbuffer object is deleted while its image is attached to the currently bound
2635     // framebuffer, then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of
2636     // 0, for each attachment point to which this image was attached in the currently bound
2637     // framebuffer.
2638 
2639     Framebuffer *readFramebuffer = mReadFramebuffer;
2640     Framebuffer *drawFramebuffer = mDrawFramebuffer;
2641 
2642     if (readFramebuffer && readFramebuffer->detachRenderbuffer(context, renderbuffer))
2643     {
2644         mDirtyObjects.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
2645     }
2646 
2647     if (drawFramebuffer && drawFramebuffer != readFramebuffer)
2648     {
2649         if (drawFramebuffer->detachRenderbuffer(context, renderbuffer))
2650         {
2651             setDrawFramebufferDirty();
2652         }
2653     }
2654 }
2655 
setReadFramebufferBinding(Framebuffer * framebuffer)2656 void State::setReadFramebufferBinding(Framebuffer *framebuffer)
2657 {
2658     if (mReadFramebuffer == framebuffer)
2659         return;
2660 
2661     mReadFramebuffer = framebuffer;
2662     mDirtyBits.set(state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
2663 
2664     if (mReadFramebuffer && mReadFramebuffer->hasAnyDirtyBit())
2665     {
2666         mDirtyObjects.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
2667     }
2668 }
2669 
setDrawFramebufferBinding(Framebuffer * framebuffer)2670 void State::setDrawFramebufferBinding(Framebuffer *framebuffer)
2671 {
2672     if (mDrawFramebuffer == framebuffer)
2673         return;
2674 
2675     mDrawFramebuffer = framebuffer;
2676     mDirtyBits.set(state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
2677 
2678     if (mDrawFramebuffer)
2679     {
2680         mDrawFramebuffer->setWriteControlMode(getFramebufferSRGB() ? SrgbWriteControlMode::Default
2681                                                                    : SrgbWriteControlMode::Linear);
2682 
2683         if (mDrawFramebuffer->hasAnyDirtyBit())
2684         {
2685             mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
2686         }
2687 
2688         if (isRobustResourceInitEnabled() && mDrawFramebuffer->hasResourceThatNeedsInit())
2689         {
2690             mDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS);
2691         }
2692     }
2693 }
2694 
getTargetFramebuffer(GLenum target) const2695 Framebuffer *State::getTargetFramebuffer(GLenum target) const
2696 {
2697     switch (target)
2698     {
2699         case GL_READ_FRAMEBUFFER_ANGLE:
2700             return mReadFramebuffer;
2701         case GL_DRAW_FRAMEBUFFER_ANGLE:
2702         case GL_FRAMEBUFFER:
2703             return mDrawFramebuffer;
2704         default:
2705             UNREACHABLE();
2706             return nullptr;
2707     }
2708 }
2709 
getDefaultFramebuffer() const2710 Framebuffer *State::getDefaultFramebuffer() const
2711 {
2712     return mFramebufferManager->getDefaultFramebuffer();
2713 }
2714 
removeReadFramebufferBinding(FramebufferID framebuffer)2715 bool State::removeReadFramebufferBinding(FramebufferID framebuffer)
2716 {
2717     if (mReadFramebuffer != nullptr && mReadFramebuffer->id() == framebuffer)
2718     {
2719         setReadFramebufferBinding(nullptr);
2720         return true;
2721     }
2722 
2723     return false;
2724 }
2725 
removeDrawFramebufferBinding(FramebufferID framebuffer)2726 bool State::removeDrawFramebufferBinding(FramebufferID framebuffer)
2727 {
2728     if (mReadFramebuffer != nullptr && mDrawFramebuffer->id() == framebuffer)
2729     {
2730         setDrawFramebufferBinding(nullptr);
2731         return true;
2732     }
2733 
2734     return false;
2735 }
2736 
setVertexArrayBinding(const Context * context,VertexArray * vertexArray)2737 void State::setVertexArrayBinding(const Context *context, VertexArray *vertexArray)
2738 {
2739     if (mVertexArray == vertexArray)
2740     {
2741         return;
2742     }
2743 
2744     if (mVertexArray)
2745     {
2746         mVertexArray->onBindingChanged(context, -1);
2747     }
2748     if (vertexArray)
2749     {
2750         vertexArray->onBindingChanged(context, 1);
2751     }
2752 
2753     mVertexArray = vertexArray;
2754     mDirtyBits.set(state::DIRTY_BIT_VERTEX_ARRAY_BINDING);
2755 
2756     if (mVertexArray && mVertexArray->hasAnyDirtyBit())
2757     {
2758         mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
2759     }
2760 }
2761 
removeVertexArrayBinding(const Context * context,VertexArrayID vertexArray)2762 bool State::removeVertexArrayBinding(const Context *context, VertexArrayID vertexArray)
2763 {
2764     if (mVertexArray && mVertexArray->id().value == vertexArray.value)
2765     {
2766         mVertexArray->onBindingChanged(context, -1);
2767         mVertexArray = nullptr;
2768         mDirtyBits.set(state::DIRTY_BIT_VERTEX_ARRAY_BINDING);
2769         mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
2770         return true;
2771     }
2772 
2773     return false;
2774 }
2775 
getVertexArrayId() const2776 VertexArrayID State::getVertexArrayId() const
2777 {
2778     ASSERT(mVertexArray != nullptr);
2779     return mVertexArray->id();
2780 }
2781 
bindVertexBuffer(const Context * context,GLuint bindingIndex,Buffer * boundBuffer,GLintptr offset,GLsizei stride)2782 void State::bindVertexBuffer(const Context *context,
2783                              GLuint bindingIndex,
2784                              Buffer *boundBuffer,
2785                              GLintptr offset,
2786                              GLsizei stride)
2787 {
2788     getVertexArray()->bindVertexBuffer(context, bindingIndex, boundBuffer, offset, stride);
2789     mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
2790 }
2791 
setVertexAttribFormat(GLuint attribIndex,GLint size,VertexAttribType type,bool normalized,bool pureInteger,GLuint relativeOffset)2792 void State::setVertexAttribFormat(GLuint attribIndex,
2793                                   GLint size,
2794                                   VertexAttribType type,
2795                                   bool normalized,
2796                                   bool pureInteger,
2797                                   GLuint relativeOffset)
2798 {
2799     getVertexArray()->setVertexAttribFormat(attribIndex, size, type, normalized, pureInteger,
2800                                             relativeOffset);
2801     mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
2802 }
2803 
setVertexBindingDivisor(const Context * context,GLuint bindingIndex,GLuint divisor)2804 void State::setVertexBindingDivisor(const Context *context, GLuint bindingIndex, GLuint divisor)
2805 {
2806     getVertexArray()->setVertexBindingDivisor(context, bindingIndex, divisor);
2807     mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
2808 }
2809 
setProgram(const Context * context,Program * newProgram)2810 angle::Result State::setProgram(const Context *context, Program *newProgram)
2811 {
2812     if (newProgram && !newProgram->isLinked())
2813     {
2814         // Protect against applications that disable validation and try to use a program that was
2815         // not successfully linked.
2816         WARN() << "Attempted to use a program that was not successfully linked";
2817         return angle::Result::Continue;
2818     }
2819 
2820     if (mProgram != newProgram)
2821     {
2822         if (mProgram)
2823         {
2824             unsetActiveTextures(mExecutable->getActiveSamplersMask());
2825             mProgram->release(context);
2826         }
2827 
2828         mProgram    = newProgram;
2829         mExecutable = nullptr;
2830 
2831         if (mProgram)
2832         {
2833             mExecutable = &mProgram->getExecutable();
2834             newProgram->addRef();
2835             ANGLE_TRY(onProgramExecutableChange(context, newProgram));
2836         }
2837         else if (mProgramPipeline.get())
2838         {
2839             mExecutable = &mProgramPipeline->getExecutable();
2840             ANGLE_TRY(onProgramPipelineExecutableChange(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())
2899         {
2900             mExecutable = &mProgramPipeline->getExecutable();
2901             ANGLE_TRY(onProgramPipelineExecutableChange(context));
2902         }
2903         else
2904         {
2905             mExecutable = nullptr;
2906         }
2907     }
2908 
2909     return angle::Result::Continue;
2910 }
2911 
detachProgramPipeline(const Context * context,ProgramPipelineID pipeline)2912 void State::detachProgramPipeline(const Context *context, ProgramPipelineID pipeline)
2913 {
2914     mProgramPipeline.set(context, nullptr);
2915 
2916     // A bound Program always overrides the ProgramPipeline, so only update the
2917     // current ProgramExecutable if there isn't currently a Program bound.
2918     if (!mProgram)
2919     {
2920         mExecutable = nullptr;
2921     }
2922 }
2923 
isQueryActive(QueryType type) const2924 bool State::isQueryActive(QueryType type) const
2925 {
2926     const Query *query = mActiveQueries[type].get();
2927     if (query != nullptr)
2928     {
2929         return true;
2930     }
2931 
2932     QueryType alternativeType;
2933     if (GetAlternativeQueryType(type, &alternativeType))
2934     {
2935         query = mActiveQueries[alternativeType].get();
2936         return query != nullptr;
2937     }
2938 
2939     return false;
2940 }
2941 
isQueryActive(Query * query) const2942 bool State::isQueryActive(Query *query) const
2943 {
2944     for (auto &queryPointer : mActiveQueries)
2945     {
2946         if (queryPointer.get() == query)
2947         {
2948             return true;
2949         }
2950     }
2951 
2952     return false;
2953 }
2954 
setActiveQuery(const Context * context,QueryType type,Query * query)2955 void State::setActiveQuery(const Context *context, QueryType type, Query *query)
2956 {
2957     mActiveQueries[type].set(context, query);
2958 }
2959 
getActiveQueryId(QueryType type) const2960 QueryID State::getActiveQueryId(QueryType type) const
2961 {
2962     const Query *query = getActiveQuery(type);
2963     if (query)
2964     {
2965         return query->id();
2966     }
2967     return {0};
2968 }
2969 
getActiveQuery(QueryType type) const2970 Query *State::getActiveQuery(QueryType type) const
2971 {
2972     return mActiveQueries[type].get();
2973 }
2974 
setIndexedBufferBinding(const Context * context,BufferBinding target,GLuint index,Buffer * buffer,GLintptr offset,GLsizeiptr size)2975 angle::Result State::setIndexedBufferBinding(const Context *context,
2976                                              BufferBinding target,
2977                                              GLuint index,
2978                                              Buffer *buffer,
2979                                              GLintptr offset,
2980                                              GLsizeiptr size)
2981 {
2982     setBufferBinding(context, target, buffer);
2983 
2984     switch (target)
2985     {
2986         case BufferBinding::TransformFeedback:
2987             ANGLE_TRY(mTransformFeedback->bindIndexedBuffer(context, index, buffer, offset, size));
2988             setBufferBinding(context, target, buffer);
2989             break;
2990         case BufferBinding::Uniform:
2991             mBoundUniformBuffersMask.set(index, buffer != nullptr);
2992             UpdateIndexedBufferBinding(context, &mUniformBuffers[index], buffer, target, offset,
2993                                        size);
2994             onUniformBufferStateChange(index);
2995             break;
2996         case BufferBinding::AtomicCounter:
2997             mBoundAtomicCounterBuffersMask.set(index, buffer != nullptr);
2998             UpdateIndexedBufferBinding(context, &mAtomicCounterBuffers[index], buffer, target,
2999                                        offset, size);
3000             break;
3001         case BufferBinding::ShaderStorage:
3002             mBoundShaderStorageBuffersMask.set(index, buffer != nullptr);
3003             UpdateIndexedBufferBinding(context, &mShaderStorageBuffers[index], buffer, target,
3004                                        offset, size);
3005             break;
3006         default:
3007             UNREACHABLE();
3008             break;
3009     }
3010 
3011     return angle::Result::Continue;
3012 }
3013 
getIndexedUniformBuffer(size_t index) const3014 const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index) const
3015 {
3016     ASSERT(index < mUniformBuffers.size());
3017     return mUniformBuffers[index];
3018 }
3019 
getIndexedAtomicCounterBuffer(size_t index) const3020 const OffsetBindingPointer<Buffer> &State::getIndexedAtomicCounterBuffer(size_t index) const
3021 {
3022     ASSERT(index < mAtomicCounterBuffers.size());
3023     return mAtomicCounterBuffers[index];
3024 }
3025 
getIndexedShaderStorageBuffer(size_t index) const3026 const OffsetBindingPointer<Buffer> &State::getIndexedShaderStorageBuffer(size_t index) const
3027 {
3028     ASSERT(index < mShaderStorageBuffers.size());
3029     return mShaderStorageBuffers[index];
3030 }
3031 
detachBuffer(Context * context,const Buffer * buffer)3032 angle::Result State::detachBuffer(Context *context, const Buffer *buffer)
3033 {
3034     BufferID bufferID = buffer->id();
3035     for (gl::BufferBinding target : angle::AllEnums<BufferBinding>())
3036     {
3037         if (mBoundBuffers[target].id() == bufferID)
3038         {
3039             UpdateBufferBinding(context, &mBoundBuffers[target], nullptr, target);
3040         }
3041     }
3042 
3043     TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
3044     if (curTransformFeedback)
3045     {
3046         ANGLE_TRY(curTransformFeedback->detachBuffer(context, bufferID));
3047         context->getStateCache().onActiveTransformFeedbackChange(context);
3048     }
3049 
3050     if (mVertexArray && mVertexArray->detachBuffer(context, bufferID))
3051     {
3052         mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
3053         context->getStateCache().onVertexArrayStateChange(context);
3054     }
3055 
3056     for (size_t uniformBufferIndex : mBoundUniformBuffersMask)
3057     {
3058         OffsetBindingPointer<Buffer> &binding = mUniformBuffers[uniformBufferIndex];
3059 
3060         if (binding.id() == bufferID)
3061         {
3062             UpdateIndexedBufferBinding(context, &binding, nullptr, BufferBinding::Uniform, 0, 0);
3063             mBoundUniformBuffersMask.reset(uniformBufferIndex);
3064         }
3065     }
3066 
3067     for (size_t atomicCounterBufferIndex : mBoundAtomicCounterBuffersMask)
3068     {
3069         OffsetBindingPointer<Buffer> &binding = mAtomicCounterBuffers[atomicCounterBufferIndex];
3070 
3071         if (binding.id() == bufferID)
3072         {
3073             UpdateIndexedBufferBinding(context, &binding, nullptr, BufferBinding::AtomicCounter, 0,
3074                                        0);
3075             mBoundAtomicCounterBuffersMask.reset(atomicCounterBufferIndex);
3076         }
3077     }
3078 
3079     for (size_t shaderStorageBufferIndex : mBoundShaderStorageBuffersMask)
3080     {
3081         OffsetBindingPointer<Buffer> &binding = mShaderStorageBuffers[shaderStorageBufferIndex];
3082 
3083         if (binding.id() == bufferID)
3084         {
3085             UpdateIndexedBufferBinding(context, &binding, nullptr, BufferBinding::ShaderStorage, 0,
3086                                        0);
3087             mBoundShaderStorageBuffersMask.reset(shaderStorageBufferIndex);
3088         }
3089     }
3090 
3091     return angle::Result::Continue;
3092 }
3093 
setEnableVertexAttribArray(unsigned int attribNum,bool enabled)3094 void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
3095 {
3096     getVertexArray()->enableAttribute(attribNum, enabled);
3097     mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
3098 }
3099 
setVertexAttribDivisor(const Context * context,GLuint index,GLuint divisor)3100 void State::setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor)
3101 {
3102     getVertexArray()->setVertexAttribDivisor(context, index, divisor);
3103     mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
3104 }
3105 
getVertexAttribPointer(unsigned int attribNum) const3106 const void *State::getVertexAttribPointer(unsigned int attribNum) const
3107 {
3108     return getVertexArray()->getVertexAttribute(attribNum).pointer;
3109 }
3110 
getBooleanv(GLenum pname,GLboolean * params) const3111 void State::getBooleanv(GLenum pname, GLboolean *params) const
3112 {
3113     switch (pname)
3114     {
3115         case GL_TRANSFORM_FEEDBACK_ACTIVE:
3116             *params = getCurrentTransformFeedback()->isActive() ? GL_TRUE : GL_FALSE;
3117             break;
3118         case GL_TRANSFORM_FEEDBACK_PAUSED:
3119             *params = getCurrentTransformFeedback()->isPaused() ? GL_TRUE : GL_FALSE;
3120             break;
3121         default:
3122             mPrivateState.getBooleanv(pname, params);
3123     }
3124 }
3125 
getIntegerv(const Context * context,GLenum pname,GLint * params) const3126 angle::Result State::getIntegerv(const Context *context, GLenum pname, GLint *params) const
3127 {
3128     if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
3129     {
3130         size_t drawBuffer = (pname - GL_DRAW_BUFFER0_EXT);
3131         ASSERT(drawBuffer < static_cast<size_t>(getCaps().maxDrawBuffers));
3132         Framebuffer *framebuffer = mDrawFramebuffer;
3133         // The default framebuffer may have fewer draw buffer states than a user-created one. The
3134         // user is always allowed to query up to GL_MAX_DRAWBUFFERS so just return GL_NONE here if
3135         // the draw buffer is out of range for this framebuffer.
3136         *params = drawBuffer < framebuffer->getDrawbufferStateCount()
3137                       ? framebuffer->getDrawBufferState(drawBuffer)
3138                       : GL_NONE;
3139         return angle::Result::Continue;
3140     }
3141 
3142     switch (pname)
3143     {
3144         case GL_ARRAY_BUFFER_BINDING:
3145             *params = mBoundBuffers[BufferBinding::Array].id().value;
3146             break;
3147         case GL_DRAW_INDIRECT_BUFFER_BINDING:
3148             *params = mBoundBuffers[BufferBinding::DrawIndirect].id().value;
3149             break;
3150         case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3151         {
3152             Buffer *elementArrayBuffer = getVertexArray()->getElementArrayBuffer();
3153             *params                    = elementArrayBuffer ? elementArrayBuffer->id().value : 0;
3154             break;
3155         }
3156         case GL_DRAW_FRAMEBUFFER_BINDING:
3157             static_assert(GL_DRAW_FRAMEBUFFER_BINDING == GL_DRAW_FRAMEBUFFER_BINDING_ANGLE,
3158                           "Enum mismatch");
3159             *params = mDrawFramebuffer->id().value;
3160             break;
3161         case GL_READ_FRAMEBUFFER_BINDING:
3162             static_assert(GL_READ_FRAMEBUFFER_BINDING == GL_READ_FRAMEBUFFER_BINDING_ANGLE,
3163                           "Enum mismatch");
3164             *params = mReadFramebuffer->id().value;
3165             break;
3166         case GL_RENDERBUFFER_BINDING:
3167             *params = mRenderbuffer.id().value;
3168             break;
3169         case GL_VERTEX_ARRAY_BINDING:
3170             *params = mVertexArray->id().value;
3171             break;
3172         case GL_CURRENT_PROGRAM:
3173             *params = mProgram ? mProgram->id().value : 0;
3174             break;
3175         case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3176             *params = mReadFramebuffer->getImplementationColorReadType(context);
3177             break;
3178         case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3179             *params = mReadFramebuffer->getImplementationColorReadFormat(context);
3180             break;
3181         case GL_SAMPLE_BUFFERS:
3182         case GL_SAMPLES:
3183         {
3184             Framebuffer *framebuffer = mDrawFramebuffer;
3185             if (framebuffer->isComplete(context))
3186             {
3187                 GLint samples = framebuffer->getSamples(context);
3188                 switch (pname)
3189                 {
3190                     case GL_SAMPLE_BUFFERS:
3191                         if (samples != 0)
3192                         {
3193                             *params = 1;
3194                         }
3195                         else
3196                         {
3197                             *params = 0;
3198                         }
3199                         break;
3200                     case GL_SAMPLES:
3201                         *params = samples;
3202                         break;
3203                 }
3204             }
3205             else
3206             {
3207                 *params = 0;
3208             }
3209         }
3210         break;
3211         case GL_RED_BITS:
3212         case GL_GREEN_BITS:
3213         case GL_BLUE_BITS:
3214         case GL_ALPHA_BITS:
3215         {
3216             Framebuffer *framebuffer                 = getDrawFramebuffer();
3217             const FramebufferAttachment *colorbuffer = framebuffer->getFirstColorAttachment();
3218 
3219             if (colorbuffer)
3220             {
3221                 switch (pname)
3222                 {
3223                     case GL_RED_BITS:
3224                         *params = colorbuffer->getRedSize();
3225                         break;
3226                     case GL_GREEN_BITS:
3227                         *params = colorbuffer->getGreenSize();
3228                         break;
3229                     case GL_BLUE_BITS:
3230                         *params = colorbuffer->getBlueSize();
3231                         break;
3232                     case GL_ALPHA_BITS:
3233                         *params = colorbuffer->getAlphaSize();
3234                         break;
3235                 }
3236             }
3237             else
3238             {
3239                 *params = 0;
3240             }
3241         }
3242         break;
3243         case GL_DEPTH_BITS:
3244         {
3245             const Framebuffer *framebuffer           = getDrawFramebuffer();
3246             const FramebufferAttachment *depthbuffer = framebuffer->getDepthAttachment();
3247 
3248             if (depthbuffer)
3249             {
3250                 *params = depthbuffer->getDepthSize();
3251             }
3252             else
3253             {
3254                 *params = 0;
3255             }
3256         }
3257         break;
3258         case GL_STENCIL_BITS:
3259         {
3260             const Framebuffer *framebuffer             = getDrawFramebuffer();
3261             const FramebufferAttachment *stencilbuffer = framebuffer->getStencilAttachment();
3262 
3263             if (stencilbuffer)
3264             {
3265                 *params = stencilbuffer->getStencilSize();
3266             }
3267             else
3268             {
3269                 *params = 0;
3270             }
3271         }
3272         break;
3273         case GL_TEXTURE_BINDING_2D:
3274             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3275             *params = getSamplerTextureId(getActiveSampler(), TextureType::_2D).value;
3276             break;
3277         case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
3278             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3279             *params = getSamplerTextureId(getActiveSampler(), TextureType::Rectangle).value;
3280             break;
3281         case GL_TEXTURE_BINDING_CUBE_MAP:
3282             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3283             *params = getSamplerTextureId(getActiveSampler(), TextureType::CubeMap).value;
3284             break;
3285         case GL_TEXTURE_BINDING_3D:
3286             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3287             *params = getSamplerTextureId(getActiveSampler(), TextureType::_3D).value;
3288             break;
3289         case GL_TEXTURE_BINDING_2D_ARRAY:
3290             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3291             *params = getSamplerTextureId(getActiveSampler(), TextureType::_2DArray).value;
3292             break;
3293         case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
3294             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3295             *params = getSamplerTextureId(getActiveSampler(), TextureType::_2DMultisample).value;
3296             break;
3297         case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
3298             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3299             *params =
3300                 getSamplerTextureId(getActiveSampler(), TextureType::_2DMultisampleArray).value;
3301             break;
3302         case GL_TEXTURE_BINDING_CUBE_MAP_ARRAY:
3303             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3304             *params = getSamplerTextureId(getActiveSampler(), TextureType::CubeMapArray).value;
3305             break;
3306         case GL_TEXTURE_BINDING_EXTERNAL_OES:
3307             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3308             *params = getSamplerTextureId(getActiveSampler(), TextureType::External).value;
3309             break;
3310 
3311         // GL_OES_texture_buffer
3312         case GL_TEXTURE_BINDING_BUFFER:
3313             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3314             *params = getSamplerTextureId(getActiveSampler(), TextureType::Buffer).value;
3315             break;
3316         case GL_TEXTURE_BUFFER_BINDING:
3317             *params = mBoundBuffers[BufferBinding::Texture].id().value;
3318             break;
3319 
3320         case GL_UNIFORM_BUFFER_BINDING:
3321             *params = mBoundBuffers[BufferBinding::Uniform].id().value;
3322             break;
3323         case GL_TRANSFORM_FEEDBACK_BINDING:
3324             *params = mTransformFeedback.id().value;
3325             break;
3326         case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
3327             *params = mBoundBuffers[BufferBinding::TransformFeedback].id().value;
3328             break;
3329         case GL_COPY_READ_BUFFER_BINDING:
3330             *params = mBoundBuffers[BufferBinding::CopyRead].id().value;
3331             break;
3332         case GL_COPY_WRITE_BUFFER_BINDING:
3333             *params = mBoundBuffers[BufferBinding::CopyWrite].id().value;
3334             break;
3335         case GL_PIXEL_PACK_BUFFER_BINDING:
3336             *params = mBoundBuffers[BufferBinding::PixelPack].id().value;
3337             break;
3338         case GL_PIXEL_UNPACK_BUFFER_BINDING:
3339             *params = mBoundBuffers[BufferBinding::PixelUnpack].id().value;
3340             break;
3341 
3342         case GL_READ_BUFFER:
3343             *params = mReadFramebuffer->getReadBufferState();
3344             break;
3345         case GL_SAMPLER_BINDING:
3346             ASSERT(static_cast<GLint>(getActiveSampler()) < getCaps().maxCombinedTextureImageUnits);
3347             *params = getSamplerId(getActiveSampler()).value;
3348             break;
3349         case GL_DEBUG_LOGGED_MESSAGES:
3350             *params = static_cast<GLint>(getDebug().getMessageCount());
3351             break;
3352         case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
3353             *params = static_cast<GLint>(getDebug().getNextMessageLength());
3354             break;
3355         case GL_DEBUG_GROUP_STACK_DEPTH:
3356             *params = static_cast<GLint>(getDebug().getGroupStackDepth());
3357             break;
3358         case GL_ATOMIC_COUNTER_BUFFER_BINDING:
3359             *params = mBoundBuffers[BufferBinding::AtomicCounter].id().value;
3360             break;
3361         case GL_SHADER_STORAGE_BUFFER_BINDING:
3362             *params = mBoundBuffers[BufferBinding::ShaderStorage].id().value;
3363             break;
3364         case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
3365             *params = mBoundBuffers[BufferBinding::DispatchIndirect].id().value;
3366             break;
3367 
3368         case GL_PROGRAM_PIPELINE_BINDING:
3369         {
3370             ProgramPipeline *pipeline = getProgramPipeline();
3371             if (pipeline)
3372             {
3373                 *params = pipeline->id().value;
3374             }
3375             else
3376             {
3377                 *params = 0;
3378             }
3379             break;
3380         }
3381 
3382         default:
3383             mPrivateState.getIntegerv(pname, params);
3384             break;
3385     }
3386 
3387     return angle::Result::Continue;
3388 }
3389 
getPointerv(const Context * context,GLenum pname,void ** params) const3390 void State::getPointerv(const Context *context, GLenum pname, void **params) const
3391 {
3392     switch (pname)
3393     {
3394         case GL_DEBUG_CALLBACK_FUNCTION:
3395             *params = reinterpret_cast<void *>(getDebug().getCallback());
3396             break;
3397         case GL_DEBUG_CALLBACK_USER_PARAM:
3398             *params = const_cast<void *>(getDebug().getUserParam());
3399             break;
3400         case GL_VERTEX_ARRAY_POINTER:
3401         case GL_NORMAL_ARRAY_POINTER:
3402         case GL_COLOR_ARRAY_POINTER:
3403         case GL_TEXTURE_COORD_ARRAY_POINTER:
3404         case GL_POINT_SIZE_ARRAY_POINTER_OES:
3405             QueryVertexAttribPointerv(getVertexArray()->getVertexAttribute(
3406                                           context->vertexArrayIndex(ParamToVertexArrayType(pname))),
3407                                       GL_VERTEX_ATTRIB_ARRAY_POINTER, params);
3408             return;
3409         default:
3410             UNREACHABLE();
3411             break;
3412     }
3413 }
3414 
getIntegeri_v(const Context * context,GLenum target,GLuint index,GLint * data) const3415 void State::getIntegeri_v(const Context *context, GLenum target, GLuint index, GLint *data) const
3416 {
3417     switch (target)
3418     {
3419         case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
3420             ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
3421             *data = mTransformFeedback->getIndexedBuffer(index).id().value;
3422             break;
3423         case GL_UNIFORM_BUFFER_BINDING:
3424             ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
3425             *data = mUniformBuffers[index].id().value;
3426             break;
3427         case GL_ATOMIC_COUNTER_BUFFER_BINDING:
3428             ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
3429             *data = mAtomicCounterBuffers[index].id().value;
3430             break;
3431         case GL_SHADER_STORAGE_BUFFER_BINDING:
3432             ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
3433             *data = mShaderStorageBuffers[index].id().value;
3434             break;
3435         case GL_VERTEX_BINDING_BUFFER:
3436             ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
3437             *data = mVertexArray->getVertexBinding(index).getBuffer().id().value;
3438             break;
3439         case GL_VERTEX_BINDING_DIVISOR:
3440             ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
3441             *data = mVertexArray->getVertexBinding(index).getDivisor();
3442             break;
3443         case GL_VERTEX_BINDING_OFFSET:
3444             ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
3445             *data = static_cast<GLuint>(mVertexArray->getVertexBinding(index).getOffset());
3446             break;
3447         case GL_VERTEX_BINDING_STRIDE:
3448             ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
3449             *data = mVertexArray->getVertexBinding(index).getStride();
3450             break;
3451         case GL_IMAGE_BINDING_NAME:
3452             ASSERT(static_cast<size_t>(index) < mImageUnits.size());
3453             *data = mImageUnits[index].texture.id().value;
3454             break;
3455         case GL_IMAGE_BINDING_LEVEL:
3456             ASSERT(static_cast<size_t>(index) < mImageUnits.size());
3457             *data = mImageUnits[index].level;
3458             break;
3459         case GL_IMAGE_BINDING_LAYER:
3460             ASSERT(static_cast<size_t>(index) < mImageUnits.size());
3461             *data = mImageUnits[index].layer;
3462             break;
3463         case GL_IMAGE_BINDING_ACCESS:
3464             ASSERT(static_cast<size_t>(index) < mImageUnits.size());
3465             *data = mImageUnits[index].access;
3466             break;
3467         case GL_IMAGE_BINDING_FORMAT:
3468             ASSERT(static_cast<size_t>(index) < mImageUnits.size());
3469             *data = mImageUnits[index].format;
3470             break;
3471         default:
3472             mPrivateState.getIntegeri_v(target, index, data);
3473             break;
3474     }
3475 }
3476 
getInteger64i_v(GLenum target,GLuint index,GLint64 * data) const3477 void State::getInteger64i_v(GLenum target, GLuint index, GLint64 *data) const
3478 {
3479     switch (target)
3480     {
3481         case GL_TRANSFORM_FEEDBACK_BUFFER_START:
3482             ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
3483             *data = mTransformFeedback->getIndexedBuffer(index).getOffset();
3484             break;
3485         case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
3486             ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
3487             *data = mTransformFeedback->getIndexedBuffer(index).getSize();
3488             break;
3489         case GL_UNIFORM_BUFFER_START:
3490             ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
3491             *data = mUniformBuffers[index].getOffset();
3492             break;
3493         case GL_UNIFORM_BUFFER_SIZE:
3494             ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
3495             *data = mUniformBuffers[index].getSize();
3496             break;
3497         case GL_ATOMIC_COUNTER_BUFFER_START:
3498             ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
3499             *data = mAtomicCounterBuffers[index].getOffset();
3500             break;
3501         case GL_ATOMIC_COUNTER_BUFFER_SIZE:
3502             ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
3503             *data = mAtomicCounterBuffers[index].getSize();
3504             break;
3505         case GL_SHADER_STORAGE_BUFFER_START:
3506             ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
3507             *data = mShaderStorageBuffers[index].getOffset();
3508             break;
3509         case GL_SHADER_STORAGE_BUFFER_SIZE:
3510             ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
3511             *data = mShaderStorageBuffers[index].getSize();
3512             break;
3513         default:
3514             UNREACHABLE();
3515             break;
3516     }
3517 }
3518 
getBooleani_v(GLenum target,GLuint index,GLboolean * data) const3519 void State::getBooleani_v(GLenum target, GLuint index, GLboolean *data) const
3520 {
3521     switch (target)
3522     {
3523         case GL_IMAGE_BINDING_LAYERED:
3524             ASSERT(static_cast<size_t>(index) < mImageUnits.size());
3525             *data = mImageUnits[index].layered;
3526             break;
3527         default:
3528             mPrivateState.getBooleani_v(target, index, data);
3529             break;
3530     }
3531 }
3532 
3533 // TODO(http://anglebug.com/3889): Remove this helper function after blink and chromium part
3534 // refactor done.
getTextureForActiveSampler(TextureType type,size_t index)3535 Texture *State::getTextureForActiveSampler(TextureType type, size_t index)
3536 {
3537     if (type != TextureType::VideoImage)
3538     {
3539         return mSamplerTextures[type][index].get();
3540     }
3541 
3542     ASSERT(type == TextureType::VideoImage);
3543 
3544     Texture *candidateTexture = mSamplerTextures[type][index].get();
3545     if (candidateTexture->getWidth(TextureTarget::VideoImage, 0) == 0 ||
3546         candidateTexture->getHeight(TextureTarget::VideoImage, 0) == 0 ||
3547         candidateTexture->getDepth(TextureTarget::VideoImage, 0) == 0)
3548     {
3549         return mSamplerTextures[TextureType::_2D][index].get();
3550     }
3551 
3552     return mSamplerTextures[type][index].get();
3553 }
3554 
syncActiveTextures(const Context * context,Command command)3555 angle::Result State::syncActiveTextures(const Context *context, Command command)
3556 {
3557     if (mDirtyActiveTextures.none())
3558     {
3559         return angle::Result::Continue;
3560     }
3561 
3562     for (size_t textureUnit : mDirtyActiveTextures)
3563     {
3564         if (mExecutable)
3565         {
3566             TextureType type       = mExecutable->getActiveSamplerTypes()[textureUnit];
3567             Texture *activeTexture = (type != TextureType::InvalidEnum)
3568                                          ? getTextureForActiveSampler(type, textureUnit)
3569                                          : nullptr;
3570             const Sampler *sampler = mSamplers[textureUnit].get();
3571 
3572             updateActiveTextureStateOnSync(context, textureUnit, sampler, activeTexture);
3573         }
3574     }
3575 
3576     mDirtyActiveTextures.reset();
3577     return angle::Result::Continue;
3578 }
3579 
syncTexturesInit(const Context * context,Command command)3580 angle::Result State::syncTexturesInit(const Context *context, Command command)
3581 {
3582     ASSERT(isRobustResourceInitEnabled());
3583 
3584     if (!mProgram)
3585         return angle::Result::Continue;
3586 
3587     for (size_t textureUnitIndex : mExecutable->getActiveSamplersMask())
3588     {
3589         Texture *texture = mActiveTexturesCache[textureUnitIndex];
3590         if (texture)
3591         {
3592             ANGLE_TRY(texture->ensureInitialized(context));
3593         }
3594     }
3595     return angle::Result::Continue;
3596 }
3597 
syncImagesInit(const Context * context,Command command)3598 angle::Result State::syncImagesInit(const Context *context, Command command)
3599 {
3600     ASSERT(isRobustResourceInitEnabled());
3601     ASSERT(mExecutable);
3602     for (size_t imageUnitIndex : mExecutable->getActiveImagesMask())
3603     {
3604         Texture *texture = mImageUnits[imageUnitIndex].texture.get();
3605         if (texture)
3606         {
3607             ANGLE_TRY(texture->ensureInitialized(context));
3608         }
3609     }
3610     return angle::Result::Continue;
3611 }
3612 
syncReadAttachments(const Context * context,Command command)3613 angle::Result State::syncReadAttachments(const Context *context, Command command)
3614 {
3615     ASSERT(mReadFramebuffer);
3616     ASSERT(isRobustResourceInitEnabled());
3617     return mReadFramebuffer->ensureReadAttachmentsInitialized(context);
3618 }
3619 
syncDrawAttachments(const Context * context,Command command)3620 angle::Result State::syncDrawAttachments(const Context *context, Command command)
3621 {
3622     ASSERT(mDrawFramebuffer);
3623     ASSERT(isRobustResourceInitEnabled());
3624     return mDrawFramebuffer->ensureDrawAttachmentsInitialized(context);
3625 }
3626 
syncReadFramebuffer(const Context * context,Command command)3627 angle::Result State::syncReadFramebuffer(const Context *context, Command command)
3628 {
3629     ASSERT(mReadFramebuffer);
3630     return mReadFramebuffer->syncState(context, GL_READ_FRAMEBUFFER, command);
3631 }
3632 
syncDrawFramebuffer(const Context * context,Command command)3633 angle::Result State::syncDrawFramebuffer(const Context *context, Command command)
3634 {
3635     ASSERT(mDrawFramebuffer);
3636     mDrawFramebuffer->setWriteControlMode(context->getState().getFramebufferSRGB()
3637                                               ? SrgbWriteControlMode::Default
3638                                               : SrgbWriteControlMode::Linear);
3639     return mDrawFramebuffer->syncState(context, GL_DRAW_FRAMEBUFFER, command);
3640 }
3641 
syncTextures(const Context * context,Command command)3642 angle::Result State::syncTextures(const Context *context, Command command)
3643 {
3644     if (mDirtyTextures.none())
3645         return angle::Result::Continue;
3646 
3647     for (size_t textureIndex : mDirtyTextures)
3648     {
3649         Texture *texture = mActiveTexturesCache[textureIndex];
3650         if (texture && texture->hasAnyDirtyBit())
3651         {
3652             ANGLE_TRY(texture->syncState(context, Command::Other));
3653         }
3654     }
3655 
3656     mDirtyTextures.reset();
3657     return angle::Result::Continue;
3658 }
3659 
syncImages(const Context * context,Command command)3660 angle::Result State::syncImages(const Context *context, Command command)
3661 {
3662     if (mDirtyImages.none())
3663         return angle::Result::Continue;
3664 
3665     for (size_t imageUnitIndex : mDirtyImages)
3666     {
3667         Texture *texture = mImageUnits[imageUnitIndex].texture.get();
3668         if (texture && texture->hasAnyDirtyBit())
3669         {
3670             ANGLE_TRY(texture->syncState(context, Command::Other));
3671         }
3672     }
3673 
3674     mDirtyImages.reset();
3675     return angle::Result::Continue;
3676 }
3677 
syncSamplers(const Context * context,Command command)3678 angle::Result State::syncSamplers(const Context *context, Command command)
3679 {
3680     if (mDirtySamplers.none())
3681         return angle::Result::Continue;
3682 
3683     for (size_t samplerIndex : mDirtySamplers)
3684     {
3685         BindingPointer<Sampler> &sampler = mSamplers[samplerIndex];
3686         if (sampler.get() && sampler->isDirty())
3687         {
3688             ANGLE_TRY(sampler->syncState(context));
3689         }
3690     }
3691 
3692     mDirtySamplers.reset();
3693 
3694     return angle::Result::Continue;
3695 }
3696 
syncVertexArray(const Context * context,Command command)3697 angle::Result State::syncVertexArray(const Context *context, Command command)
3698 {
3699     ASSERT(mVertexArray);
3700     return mVertexArray->syncState(context);
3701 }
3702 
syncProgram(const Context * context,Command command)3703 angle::Result State::syncProgram(const Context *context, Command command)
3704 {
3705     // There may not be a program if the calling application only uses program pipelines.
3706     if (mProgram)
3707     {
3708         return mProgram->syncState(context);
3709     }
3710     else if (mProgramPipeline.get())
3711     {
3712         return mProgramPipeline->syncState(context);
3713     }
3714     return angle::Result::Continue;
3715 }
3716 
syncProgramPipelineObject(const Context * context,Command command)3717 angle::Result State::syncProgramPipelineObject(const Context *context, Command command)
3718 {
3719     // If a ProgramPipeline is bound, ensure it is linked.
3720     if (mProgramPipeline.get())
3721     {
3722         mProgramPipeline->resolveLink(context);
3723     }
3724     return angle::Result::Continue;
3725 }
3726 
syncDirtyObject(const Context * context,GLenum target)3727 angle::Result State::syncDirtyObject(const Context *context, GLenum target)
3728 {
3729     state::DirtyObjects localSet;
3730 
3731     switch (target)
3732     {
3733         case GL_READ_FRAMEBUFFER:
3734             localSet.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
3735             break;
3736         case GL_DRAW_FRAMEBUFFER:
3737             localSet.set(state::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
3738             break;
3739         case GL_FRAMEBUFFER:
3740             localSet.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
3741             localSet.set(state::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
3742             break;
3743         case GL_VERTEX_ARRAY:
3744             localSet.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
3745             break;
3746         case GL_TEXTURE:
3747             localSet.set(state::DIRTY_OBJECT_TEXTURES);
3748             break;
3749         case GL_SAMPLER:
3750             localSet.set(state::DIRTY_OBJECT_SAMPLERS);
3751             break;
3752         case GL_PROGRAM:
3753             localSet.set(state::DIRTY_OBJECT_PROGRAM);
3754             break;
3755     }
3756 
3757     return syncDirtyObjects(context, localSet, Command::Other);
3758 }
3759 
setObjectDirty(GLenum target)3760 void State::setObjectDirty(GLenum target)
3761 {
3762     switch (target)
3763     {
3764         case GL_READ_FRAMEBUFFER:
3765             mDirtyObjects.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
3766             break;
3767         case GL_DRAW_FRAMEBUFFER:
3768             setDrawFramebufferDirty();
3769             break;
3770         case GL_FRAMEBUFFER:
3771             mDirtyObjects.set(state::DIRTY_OBJECT_READ_FRAMEBUFFER);
3772             setDrawFramebufferDirty();
3773             break;
3774         case GL_VERTEX_ARRAY:
3775             mDirtyObjects.set(state::DIRTY_OBJECT_VERTEX_ARRAY);
3776             break;
3777         case GL_PROGRAM:
3778             mDirtyObjects.set(state::DIRTY_OBJECT_PROGRAM);
3779             break;
3780         default:
3781             break;
3782     }
3783 }
3784 
onProgramExecutableChange(const Context * context,Program * program)3785 angle::Result State::onProgramExecutableChange(const Context *context, Program *program)
3786 {
3787     // OpenGL Spec:
3788     // "If LinkProgram or ProgramBinary successfully re-links a program object
3789     //  that was already in use as a result of a previous call to UseProgram, then the
3790     //  generated executable code will be installed as part of the current rendering state."
3791     ASSERT(program->isLinked());
3792 
3793     // If this Program is currently active, we need to update the State's pointer to the current
3794     // ProgramExecutable if we just changed it.
3795     if (mProgram == program)
3796     {
3797         mExecutable = &program->getExecutable();
3798     }
3799 
3800     mDirtyBits.set(state::DIRTY_BIT_PROGRAM_EXECUTABLE);
3801 
3802     if (program->hasAnyDirtyBit())
3803     {
3804         mDirtyObjects.set(state::DIRTY_OBJECT_PROGRAM);
3805     }
3806 
3807     // Set any bound textures.
3808     const ProgramExecutable &executable        = program->getExecutable();
3809     const ActiveTextureTypeArray &textureTypes = executable.getActiveSamplerTypes();
3810     for (size_t textureIndex : executable.getActiveSamplersMask())
3811     {
3812         TextureType type = textureTypes[textureIndex];
3813 
3814         // This can happen if there is a conflicting texture type.
3815         if (type == TextureType::InvalidEnum)
3816             continue;
3817 
3818         Texture *texture = getTextureForActiveSampler(type, textureIndex);
3819         updateTextureBinding(context, textureIndex, texture);
3820     }
3821 
3822     for (size_t imageUnitIndex : executable.getActiveImagesMask())
3823     {
3824         Texture *image = mImageUnits[imageUnitIndex].texture.get();
3825         if (!image)
3826             continue;
3827 
3828         if (image->hasAnyDirtyBit())
3829         {
3830             ANGLE_TRY(image->syncState(context, Command::Other));
3831         }
3832 
3833         if (isRobustResourceInitEnabled() && image->initState() == InitState::MayNeedInit)
3834         {
3835             mDirtyObjects.set(state::DIRTY_OBJECT_IMAGES_INIT);
3836         }
3837     }
3838 
3839     return angle::Result::Continue;
3840 }
3841 
onProgramPipelineExecutableChange(const Context * context)3842 angle::Result State::onProgramPipelineExecutableChange(const Context *context)
3843 {
3844     mDirtyBits.set(state::DIRTY_BIT_PROGRAM_EXECUTABLE);
3845 
3846     if (!mProgramPipeline->isLinked())
3847     {
3848         mDirtyObjects.set(state::DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT);
3849     }
3850 
3851     // Set any bound textures.
3852     const ProgramExecutable &executable        = mProgramPipeline->getExecutable();
3853     const ActiveTextureTypeArray &textureTypes = executable.getActiveSamplerTypes();
3854 
3855     for (size_t textureIndex : executable.getActiveSamplersMask())
3856     {
3857         TextureType type = textureTypes[textureIndex];
3858 
3859         // This can happen if there is a conflicting texture type.
3860         if (type == TextureType::InvalidEnum)
3861             continue;
3862 
3863         Texture *texture = getTextureForActiveSampler(type, textureIndex);
3864         updateTextureBinding(context, textureIndex, texture);
3865     }
3866 
3867     for (size_t imageUnitIndex : executable.getActiveImagesMask())
3868     {
3869         Texture *image = mImageUnits[imageUnitIndex].texture.get();
3870         if (!image)
3871             continue;
3872 
3873         if (image->hasAnyDirtyBit())
3874         {
3875             ANGLE_TRY(image->syncState(context, Command::Other));
3876         }
3877 
3878         if (isRobustResourceInitEnabled() && image->initState() == InitState::MayNeedInit)
3879         {
3880             mDirtyObjects.set(state::DIRTY_OBJECT_IMAGES_INIT);
3881         }
3882     }
3883 
3884     return angle::Result::Continue;
3885 }
3886 
setTextureDirty(size_t textureUnitIndex)3887 void State::setTextureDirty(size_t textureUnitIndex)
3888 {
3889     mDirtyObjects.set(state::DIRTY_OBJECT_TEXTURES);
3890     mDirtyTextures.set(textureUnitIndex);
3891 }
3892 
setSamplerDirty(size_t samplerIndex)3893 void State::setSamplerDirty(size_t samplerIndex)
3894 {
3895     mDirtyObjects.set(state::DIRTY_OBJECT_SAMPLERS);
3896     mDirtySamplers.set(samplerIndex);
3897 }
3898 
setImageUnit(const Context * context,size_t unit,Texture * texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)3899 void State::setImageUnit(const Context *context,
3900                          size_t unit,
3901                          Texture *texture,
3902                          GLint level,
3903                          GLboolean layered,
3904                          GLint layer,
3905                          GLenum access,
3906                          GLenum format)
3907 {
3908     ASSERT(!mImageUnits.empty());
3909 
3910     ImageUnit &imageUnit = mImageUnits[unit];
3911 
3912     if (texture)
3913     {
3914         texture->onBindAsImageTexture();
3915     }
3916     imageUnit.texture.set(context, texture);
3917     imageUnit.level   = level;
3918     imageUnit.layered = layered;
3919     imageUnit.layer   = layer;
3920     imageUnit.access  = access;
3921     imageUnit.format  = format;
3922     mDirtyBits.set(state::DIRTY_BIT_IMAGE_BINDINGS);
3923 
3924     onImageStateChange(context, unit);
3925 }
3926 
setMaxShaderCompilerThreads(GLuint count)3927 void State::setMaxShaderCompilerThreads(GLuint count)
3928 {
3929     mMaxShaderCompilerThreads = count;
3930 }
3931 
3932 // Handle a dirty texture event.
onActiveTextureChange(const Context * context,size_t textureUnit)3933 void State::onActiveTextureChange(const Context *context, size_t textureUnit)
3934 {
3935     if (mExecutable)
3936     {
3937         TextureType type       = mExecutable->getActiveSamplerTypes()[textureUnit];
3938         Texture *activeTexture = (type != TextureType::InvalidEnum)
3939                                      ? getTextureForActiveSampler(type, textureUnit)
3940                                      : nullptr;
3941         updateTextureBinding(context, textureUnit, activeTexture);
3942 
3943         mExecutable->onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
3944     }
3945 }
3946 
onActiveTextureStateChange(const Context * context,size_t textureUnit)3947 void State::onActiveTextureStateChange(const Context *context, size_t textureUnit)
3948 {
3949     if (mExecutable)
3950     {
3951         TextureType type       = mExecutable->getActiveSamplerTypes()[textureUnit];
3952         Texture *activeTexture = (type != TextureType::InvalidEnum)
3953                                      ? getTextureForActiveSampler(type, textureUnit)
3954                                      : nullptr;
3955         setActiveTextureDirty(textureUnit, activeTexture);
3956     }
3957 }
3958 
onImageStateChange(const Context * context,size_t unit)3959 void State::onImageStateChange(const Context *context, size_t unit)
3960 {
3961     if (mExecutable)
3962     {
3963         const ImageUnit &image = mImageUnits[unit];
3964 
3965         // Have nothing to do here if no texture bound
3966         if (!image.texture.get())
3967             return;
3968 
3969         if (image.texture->hasAnyDirtyBit())
3970         {
3971             mDirtyImages.set(unit);
3972             mDirtyObjects.set(state::DIRTY_OBJECT_IMAGES);
3973         }
3974 
3975         if (isRobustResourceInitEnabled() && image.texture->initState() == InitState::MayNeedInit)
3976         {
3977             mDirtyObjects.set(state::DIRTY_OBJECT_IMAGES_INIT);
3978         }
3979 
3980         mExecutable->onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
3981     }
3982 }
3983 
onUniformBufferStateChange(size_t uniformBufferIndex)3984 void State::onUniformBufferStateChange(size_t uniformBufferIndex)
3985 {
3986     if (mProgram)
3987     {
3988         mProgram->onUniformBufferStateChange(uniformBufferIndex);
3989     }
3990     else if (mProgramPipeline.get())
3991     {
3992         mProgramPipeline->onUniformBufferStateChange(uniformBufferIndex);
3993     }
3994     // So that program object syncState will get triggered and process the program's dirty bits
3995     setObjectDirty(GL_PROGRAM);
3996     // This could be represented by a different dirty bit. Using the same one keeps it simple.
3997     mDirtyBits.set(state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
3998 }
3999 
onAtomicCounterBufferStateChange(size_t atomicCounterBufferIndex)4000 void State::onAtomicCounterBufferStateChange(size_t atomicCounterBufferIndex)
4001 {
4002     mDirtyBits.set(state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
4003 }
4004 
onShaderStorageBufferStateChange(size_t shaderStorageBufferIndex)4005 void State::onShaderStorageBufferStateChange(size_t shaderStorageBufferIndex)
4006 {
4007     mDirtyBits.set(state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
4008 }
4009 
initializeForCapture(const Context * context)4010 void State::initializeForCapture(const Context *context)
4011 {
4012     mPrivateState.initializeForCapture(context);
4013 
4014     // This little kludge gets around the frame capture "constness". It should be safe because
4015     // nothing in the context is modified in a non-compatible way during capture.
4016     Context *mutableContext = const_cast<Context *>(context);
4017     initialize(mutableContext);
4018 }
4019 
4020 constexpr State::DirtyObjectHandler State::kDirtyObjectHandlers[state::DIRTY_OBJECT_MAX];
4021 
4022 }  // namespace gl
4023