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