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