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