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