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