1 //
2 // Copyright 2015 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 // StateManagerGL.h: Defines a class for caching applied OpenGL state
8
9 #include "libANGLE/renderer/gl/StateManagerGL.h"
10
11 #include <string.h>
12 #include <algorithm>
13 #include <limits>
14
15 #include "anglebase/numerics/safe_conversions.h"
16 #include "common/bitset_utils.h"
17 #include "common/mathutil.h"
18 #include "common/matrix_utils.h"
19 #include "libANGLE/Context.h"
20 #include "libANGLE/Framebuffer.h"
21 #include "libANGLE/Query.h"
22 #include "libANGLE/TransformFeedback.h"
23 #include "libANGLE/VertexArray.h"
24 #include "libANGLE/renderer/gl/BufferGL.h"
25 #include "libANGLE/renderer/gl/FramebufferGL.h"
26 #include "libANGLE/renderer/gl/FunctionsGL.h"
27 #include "libANGLE/renderer/gl/ProgramGL.h"
28 #include "libANGLE/renderer/gl/QueryGL.h"
29 #include "libANGLE/renderer/gl/SamplerGL.h"
30 #include "libANGLE/renderer/gl/TextureGL.h"
31 #include "libANGLE/renderer/gl/TransformFeedbackGL.h"
32 #include "libANGLE/renderer/gl/VertexArrayGL.h"
33
34 namespace rx
35 {
36
37 namespace
38 {
39
ValidateStateHelper(const FunctionsGL * functions,const GLuint localValue,const GLenum pname,const char * localName,const char * driverName)40 static void ValidateStateHelper(const FunctionsGL *functions,
41 const GLuint localValue,
42 const GLenum pname,
43 const char *localName,
44 const char *driverName)
45 {
46 GLint queryValue;
47 functions->getIntegerv(pname, &queryValue);
48 if (localValue != static_cast<GLuint>(queryValue))
49 {
50 WARN() << localName << " (" << localValue << ") != " << driverName << " (" << queryValue
51 << ")";
52 // Re-add ASSERT: http://anglebug.com/3900
53 // ASSERT(false);
54 }
55 }
56
57 } // anonymous namespace
58
IndexedBufferBinding()59 StateManagerGL::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0) {}
60
StateManagerGL(const FunctionsGL * functions,const gl::Caps & rendererCaps,const gl::Extensions & extensions,const angle::FeaturesGL & features)61 StateManagerGL::StateManagerGL(const FunctionsGL *functions,
62 const gl::Caps &rendererCaps,
63 const gl::Extensions &extensions,
64 const angle::FeaturesGL &features)
65 : mFunctions(functions),
66 mFeatures(features),
67 mProgram(0),
68 mVAO(0),
69 mVertexAttribCurrentValues(rendererCaps.maxVertexAttributes),
70 mBuffers(),
71 mIndexedBuffers(),
72 mTextureUnitIndex(0),
73 mTextures{},
74 mSamplers{},
75 mImages(rendererCaps.maxImageUnits, ImageUnitBinding()),
76 mTransformFeedback(0),
77 mCurrentTransformFeedback(nullptr),
78 mQueries(),
79 mPrevDrawContext(0),
80 mUnpackAlignment(4),
81 mUnpackRowLength(0),
82 mUnpackSkipRows(0),
83 mUnpackSkipPixels(0),
84 mUnpackImageHeight(0),
85 mUnpackSkipImages(0),
86 mPackAlignment(4),
87 mPackRowLength(0),
88 mPackSkipRows(0),
89 mPackSkipPixels(0),
90 mFramebuffers(angle::FramebufferBindingSingletonMax, 0),
91 mRenderbuffer(0),
92 mScissorTestEnabled(false),
93 mScissor(0, 0, 0, 0),
94 mViewport(0, 0, 0, 0),
95 mNear(0.0f),
96 mFar(1.0f),
97 mBlendColor(0, 0, 0, 0),
98 mBlendStateExt(rendererCaps.maxDrawBuffers),
99 mIndependentBlendStates(extensions.drawBuffersIndexedAny()),
100 mSampleAlphaToCoverageEnabled(false),
101 mSampleCoverageEnabled(false),
102 mSampleCoverageValue(1.0f),
103 mSampleCoverageInvert(false),
104 mSampleMaskEnabled(false),
105 mDepthTestEnabled(false),
106 mDepthFunc(GL_LESS),
107 mDepthMask(true),
108 mStencilTestEnabled(false),
109 mStencilFrontFunc(GL_ALWAYS),
110 mStencilFrontRef(0),
111 mStencilFrontValueMask(static_cast<GLuint>(-1)),
112 mStencilFrontStencilFailOp(GL_KEEP),
113 mStencilFrontStencilPassDepthFailOp(GL_KEEP),
114 mStencilFrontStencilPassDepthPassOp(GL_KEEP),
115 mStencilFrontWritemask(static_cast<GLuint>(-1)),
116 mStencilBackFunc(GL_ALWAYS),
117 mStencilBackRef(0),
118 mStencilBackValueMask(static_cast<GLuint>(-1)),
119 mStencilBackStencilFailOp(GL_KEEP),
120 mStencilBackStencilPassDepthFailOp(GL_KEEP),
121 mStencilBackStencilPassDepthPassOp(GL_KEEP),
122 mStencilBackWritemask(static_cast<GLuint>(-1)),
123 mCullFaceEnabled(false),
124 mCullFace(gl::CullFaceMode::Back),
125 mFrontFace(GL_CCW),
126 mPolygonOffsetFillEnabled(false),
127 mPolygonOffsetFactor(0.0f),
128 mPolygonOffsetUnits(0.0f),
129 mRasterizerDiscardEnabled(false),
130 mLineWidth(1.0f),
131 mPrimitiveRestartEnabled(false),
132 mPrimitiveRestartIndex(0),
133 mClearColor(0.0f, 0.0f, 0.0f, 0.0f),
134 mClearDepth(1.0f),
135 mClearStencil(0),
136 mFramebufferSRGBAvailable(extensions.sRGBWriteControl),
137 mFramebufferSRGBEnabled(false),
138 mDitherEnabled(true),
139 mTextureCubemapSeamlessEnabled(false),
140 mMultisamplingEnabled(true),
141 mSampleAlphaToOneEnabled(false),
142 mCoverageModulation(GL_NONE),
143 mIsMultiviewEnabled(extensions.multiview || extensions.multiview2),
144 mProvokingVertex(GL_LAST_VERTEX_CONVENTION),
145 mMaxClipDistances(rendererCaps.maxClipDistances),
146 mLocalDirtyBits()
147 {
148 ASSERT(mFunctions);
149 ASSERT(extensions.maxViews >= 1u);
150
151 mIndexedBuffers[gl::BufferBinding::Uniform].resize(rendererCaps.maxUniformBufferBindings);
152 mIndexedBuffers[gl::BufferBinding::AtomicCounter].resize(
153 rendererCaps.maxAtomicCounterBufferBindings);
154 mIndexedBuffers[gl::BufferBinding::ShaderStorage].resize(
155 rendererCaps.maxShaderStorageBufferBindings);
156
157 mSampleMaskValues.fill(~GLbitfield(0));
158
159 mQueries.fill(nullptr);
160 mTemporaryPausedQueries.fill(nullptr);
161
162 // Initialize point sprite state for desktop GL
163 if (mFunctions->standard == STANDARD_GL_DESKTOP)
164 {
165 mFunctions->enable(GL_PROGRAM_POINT_SIZE);
166
167 // GL_POINT_SPRITE was deprecated in the core profile. Point rasterization is always
168 // performed
169 // as though POINT_SPRITE were enabled.
170 if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) == 0)
171 {
172 mFunctions->enable(GL_POINT_SPRITE);
173 }
174 }
175
176 if (features.emulatePrimitiveRestartFixedIndex.enabled)
177 {
178 // There is no consistent default value for primitive restart index. Set it to UINT -1.
179 constexpr GLuint primitiveRestartIndex = gl::GetPrimitiveRestartIndexFromType<GLuint>();
180 mFunctions->primitiveRestartIndex(primitiveRestartIndex);
181 mPrimitiveRestartIndex = primitiveRestartIndex;
182 }
183 }
184
~StateManagerGL()185 StateManagerGL::~StateManagerGL() {}
186
deleteProgram(GLuint program)187 void StateManagerGL::deleteProgram(GLuint program)
188 {
189 if (program != 0)
190 {
191 if (mProgram == program)
192 {
193 useProgram(0);
194 }
195
196 mFunctions->deleteProgram(program);
197 }
198 }
199
deleteVertexArray(GLuint vao)200 void StateManagerGL::deleteVertexArray(GLuint vao)
201 {
202 if (vao != 0)
203 {
204 if (mVAO == vao)
205 {
206 bindVertexArray(0, 0);
207 }
208
209 mFunctions->deleteVertexArrays(1, &vao);
210 }
211 }
212
deleteTexture(GLuint texture)213 void StateManagerGL::deleteTexture(GLuint texture)
214 {
215 if (texture != 0)
216 {
217 for (gl::TextureType type : angle::AllEnums<gl::TextureType>())
218 {
219 const auto &textureVector = mTextures[type];
220 for (size_t textureUnitIndex = 0; textureUnitIndex < textureVector.size();
221 textureUnitIndex++)
222 {
223 if (textureVector[textureUnitIndex] == texture)
224 {
225 activeTexture(textureUnitIndex);
226 bindTexture(type, 0);
227 }
228 }
229 }
230
231 for (size_t imageUnitIndex = 0; imageUnitIndex < mImages.size(); imageUnitIndex++)
232 {
233 if (mImages[imageUnitIndex].texture == texture)
234 {
235 bindImageTexture(imageUnitIndex, 0, 0, false, 0, GL_READ_ONLY, GL_R32UI);
236 }
237 }
238
239 mFunctions->deleteTextures(1, &texture);
240 }
241 }
242
deleteSampler(GLuint sampler)243 void StateManagerGL::deleteSampler(GLuint sampler)
244 {
245 if (sampler != 0)
246 {
247 for (size_t unit = 0; unit < mSamplers.size(); unit++)
248 {
249 if (mSamplers[unit] == sampler)
250 {
251 bindSampler(unit, 0);
252 }
253 }
254
255 mFunctions->deleteSamplers(1, &sampler);
256 }
257 }
258
deleteBuffer(GLuint buffer)259 void StateManagerGL::deleteBuffer(GLuint buffer)
260 {
261 if (buffer == 0)
262 {
263 return;
264 }
265
266 for (auto target : angle::AllEnums<gl::BufferBinding>())
267 {
268 if (mBuffers[target] == buffer)
269 {
270 bindBuffer(target, 0);
271 }
272
273 auto &indexedTarget = mIndexedBuffers[target];
274 for (size_t bindIndex = 0; bindIndex < indexedTarget.size(); ++bindIndex)
275 {
276 if (indexedTarget[bindIndex].buffer == buffer)
277 {
278 bindBufferBase(target, bindIndex, 0);
279 }
280 }
281 }
282
283 mFunctions->deleteBuffers(1, &buffer);
284 }
285
deleteFramebuffer(GLuint fbo)286 void StateManagerGL::deleteFramebuffer(GLuint fbo)
287 {
288 if (fbo != 0)
289 {
290 for (size_t binding = 0; binding < mFramebuffers.size(); ++binding)
291 {
292 if (mFramebuffers[binding] == fbo)
293 {
294 GLenum enumValue = angle::FramebufferBindingToEnum(
295 static_cast<angle::FramebufferBinding>(binding));
296 bindFramebuffer(enumValue, 0);
297 }
298 }
299 mFunctions->deleteFramebuffers(1, &fbo);
300 }
301 }
302
deleteRenderbuffer(GLuint rbo)303 void StateManagerGL::deleteRenderbuffer(GLuint rbo)
304 {
305 if (rbo != 0)
306 {
307 if (mRenderbuffer == rbo)
308 {
309 bindRenderbuffer(GL_RENDERBUFFER, 0);
310 }
311
312 mFunctions->deleteRenderbuffers(1, &rbo);
313 }
314 }
315
deleteTransformFeedback(GLuint transformFeedback)316 void StateManagerGL::deleteTransformFeedback(GLuint transformFeedback)
317 {
318 if (transformFeedback != 0)
319 {
320 if (mTransformFeedback == transformFeedback)
321 {
322 bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
323 }
324
325 if (mCurrentTransformFeedback != nullptr &&
326 mCurrentTransformFeedback->getTransformFeedbackID() == transformFeedback)
327 {
328 mCurrentTransformFeedback = nullptr;
329 }
330
331 mFunctions->deleteTransformFeedbacks(1, &transformFeedback);
332 }
333 }
334
useProgram(GLuint program)335 void StateManagerGL::useProgram(GLuint program)
336 {
337 if (mProgram != program)
338 {
339 forceUseProgram(program);
340 }
341 }
342
forceUseProgram(GLuint program)343 void StateManagerGL::forceUseProgram(GLuint program)
344 {
345 mProgram = program;
346 mFunctions->useProgram(mProgram);
347 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PROGRAM_BINDING);
348 }
349
bindVertexArray(GLuint vao,GLuint elementArrayBuffer)350 void StateManagerGL::bindVertexArray(GLuint vao, GLuint elementArrayBuffer)
351 {
352 if (mVAO != vao)
353 {
354 mVAO = vao;
355 mBuffers[gl::BufferBinding::ElementArray] = elementArrayBuffer;
356 mFunctions->bindVertexArray(vao);
357
358 mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
359 }
360 }
361
bindBuffer(gl::BufferBinding target,GLuint buffer)362 void StateManagerGL::bindBuffer(gl::BufferBinding target, GLuint buffer)
363 {
364 // GL drivers differ in whether the transform feedback bind point is modified when
365 // glBindTransformFeedback is called. To avoid these behavior differences we shouldn't try to
366 // use it.
367 ASSERT(target != gl::BufferBinding::TransformFeedback);
368 if (mBuffers[target] != buffer)
369 {
370 mBuffers[target] = buffer;
371 mFunctions->bindBuffer(gl::ToGLenum(target), buffer);
372 }
373 }
374
bindBufferBase(gl::BufferBinding target,size_t index,GLuint buffer)375 void StateManagerGL::bindBufferBase(gl::BufferBinding target, size_t index, GLuint buffer)
376 {
377 // Transform feedback buffer bindings are tracked in TransformFeedbackGL
378 ASSERT(target != gl::BufferBinding::TransformFeedback);
379
380 ASSERT(index < mIndexedBuffers[target].size());
381 auto &binding = mIndexedBuffers[target][index];
382 if (binding.buffer != buffer || binding.offset != static_cast<size_t>(-1) ||
383 binding.size != static_cast<size_t>(-1))
384 {
385 binding.buffer = buffer;
386 binding.offset = static_cast<size_t>(-1);
387 binding.size = static_cast<size_t>(-1);
388 mBuffers[target] = buffer;
389 mFunctions->bindBufferBase(gl::ToGLenum(target), static_cast<GLuint>(index), buffer);
390 }
391 }
392
bindBufferRange(gl::BufferBinding target,size_t index,GLuint buffer,size_t offset,size_t size)393 void StateManagerGL::bindBufferRange(gl::BufferBinding target,
394 size_t index,
395 GLuint buffer,
396 size_t offset,
397 size_t size)
398 {
399 // Transform feedback buffer bindings are tracked in TransformFeedbackGL
400 ASSERT(target != gl::BufferBinding::TransformFeedback);
401
402 auto &binding = mIndexedBuffers[target][index];
403 if (binding.buffer != buffer || binding.offset != offset || binding.size != size)
404 {
405 binding.buffer = buffer;
406 binding.offset = offset;
407 binding.size = size;
408 mBuffers[target] = buffer;
409 mFunctions->bindBufferRange(gl::ToGLenum(target), static_cast<GLuint>(index), buffer,
410 offset, size);
411 }
412 }
413
activeTexture(size_t unit)414 void StateManagerGL::activeTexture(size_t unit)
415 {
416 if (mTextureUnitIndex != unit)
417 {
418 mTextureUnitIndex = unit;
419 mFunctions->activeTexture(GL_TEXTURE0 + static_cast<GLenum>(mTextureUnitIndex));
420 }
421 }
422
bindTexture(gl::TextureType type,GLuint texture)423 void StateManagerGL::bindTexture(gl::TextureType type, GLuint texture)
424 {
425 gl::TextureType nativeType = nativegl::GetNativeTextureType(type);
426 if (mTextures[nativeType][mTextureUnitIndex] != texture)
427 {
428 mTextures[nativeType][mTextureUnitIndex] = texture;
429 mFunctions->bindTexture(nativegl::GetTextureBindingTarget(type), texture);
430 mLocalDirtyBits.set(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
431 }
432 }
433
invalidateTexture(gl::TextureType type)434 void StateManagerGL::invalidateTexture(gl::TextureType type)
435 {
436 // Assume the tracked texture binding is incorrect, query the real bound texture from GL.
437 GLint boundTexture = 0;
438 mFunctions->getIntegerv(nativegl::GetTextureBindingQuery(type), &boundTexture);
439 mTextures[type][mTextureUnitIndex] = static_cast<GLuint>(boundTexture);
440 mLocalDirtyBits.set(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
441 }
442
bindSampler(size_t unit,GLuint sampler)443 void StateManagerGL::bindSampler(size_t unit, GLuint sampler)
444 {
445 if (mSamplers[unit] != sampler)
446 {
447 mSamplers[unit] = sampler;
448 mFunctions->bindSampler(static_cast<GLuint>(unit), sampler);
449 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLER_BINDINGS);
450 }
451 }
452
bindImageTexture(size_t unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)453 void StateManagerGL::bindImageTexture(size_t unit,
454 GLuint texture,
455 GLint level,
456 GLboolean layered,
457 GLint layer,
458 GLenum access,
459 GLenum format)
460 {
461 auto &binding = mImages[unit];
462 if (binding.texture != texture || binding.level != level || binding.layered != layered ||
463 binding.layer != layer || binding.access != access || binding.format != format)
464 {
465 binding.texture = texture;
466 binding.level = level;
467 binding.layered = layered;
468 binding.layer = layer;
469 binding.access = access;
470 binding.format = format;
471 mFunctions->bindImageTexture(angle::base::checked_cast<GLuint>(unit), texture, level,
472 layered, layer, access, format);
473 }
474 }
475
setPixelUnpackState(const gl::PixelUnpackState & unpack)476 void StateManagerGL::setPixelUnpackState(const gl::PixelUnpackState &unpack)
477 {
478 if (mUnpackAlignment != unpack.alignment)
479 {
480 mUnpackAlignment = unpack.alignment;
481 mFunctions->pixelStorei(GL_UNPACK_ALIGNMENT, mUnpackAlignment);
482
483 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
484 }
485
486 if (mUnpackRowLength != unpack.rowLength)
487 {
488 mUnpackRowLength = unpack.rowLength;
489 mFunctions->pixelStorei(GL_UNPACK_ROW_LENGTH, mUnpackRowLength);
490
491 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
492 }
493
494 if (mUnpackSkipRows != unpack.skipRows)
495 {
496 mUnpackSkipRows = unpack.skipRows;
497 mFunctions->pixelStorei(GL_UNPACK_SKIP_ROWS, mUnpackSkipRows);
498
499 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
500 }
501
502 if (mUnpackSkipPixels != unpack.skipPixels)
503 {
504 mUnpackSkipPixels = unpack.skipPixels;
505 mFunctions->pixelStorei(GL_UNPACK_SKIP_PIXELS, mUnpackSkipPixels);
506
507 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
508 }
509
510 if (mUnpackImageHeight != unpack.imageHeight)
511 {
512 mUnpackImageHeight = unpack.imageHeight;
513 mFunctions->pixelStorei(GL_UNPACK_IMAGE_HEIGHT, mUnpackImageHeight);
514
515 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
516 }
517
518 if (mUnpackSkipImages != unpack.skipImages)
519 {
520 mUnpackSkipImages = unpack.skipImages;
521 mFunctions->pixelStorei(GL_UNPACK_SKIP_IMAGES, mUnpackSkipImages);
522
523 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
524 }
525 }
526
setPixelUnpackBuffer(const gl::Buffer * pixelBuffer)527 void StateManagerGL::setPixelUnpackBuffer(const gl::Buffer *pixelBuffer)
528 {
529 GLuint bufferID = 0;
530 if (pixelBuffer != nullptr)
531 {
532 bufferID = GetImplAs<BufferGL>(pixelBuffer)->getBufferID();
533 }
534 bindBuffer(gl::BufferBinding::PixelUnpack, bufferID);
535 }
536
setPixelPackState(const gl::PixelPackState & pack)537 void StateManagerGL::setPixelPackState(const gl::PixelPackState &pack)
538 {
539 if (mPackAlignment != pack.alignment)
540 {
541 mPackAlignment = pack.alignment;
542 mFunctions->pixelStorei(GL_PACK_ALIGNMENT, mPackAlignment);
543
544 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
545 }
546
547 if (mPackRowLength != pack.rowLength)
548 {
549 mPackRowLength = pack.rowLength;
550 mFunctions->pixelStorei(GL_PACK_ROW_LENGTH, mPackRowLength);
551
552 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
553 }
554
555 if (mPackSkipRows != pack.skipRows)
556 {
557 mPackSkipRows = pack.skipRows;
558 mFunctions->pixelStorei(GL_PACK_SKIP_ROWS, mPackSkipRows);
559
560 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
561 }
562
563 if (mPackSkipPixels != pack.skipPixels)
564 {
565 mPackSkipPixels = pack.skipPixels;
566 mFunctions->pixelStorei(GL_PACK_SKIP_PIXELS, mPackSkipPixels);
567
568 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
569 }
570 }
571
setPixelPackBuffer(const gl::Buffer * pixelBuffer)572 void StateManagerGL::setPixelPackBuffer(const gl::Buffer *pixelBuffer)
573 {
574 GLuint bufferID = 0;
575 if (pixelBuffer != nullptr)
576 {
577 bufferID = GetImplAs<BufferGL>(pixelBuffer)->getBufferID();
578 }
579 bindBuffer(gl::BufferBinding::PixelPack, bufferID);
580 }
581
bindFramebuffer(GLenum type,GLuint framebuffer)582 void StateManagerGL::bindFramebuffer(GLenum type, GLuint framebuffer)
583 {
584 switch (type)
585 {
586 case GL_FRAMEBUFFER:
587 if (mFramebuffers[angle::FramebufferBindingRead] != framebuffer ||
588 mFramebuffers[angle::FramebufferBindingDraw] != framebuffer)
589 {
590 mFramebuffers[angle::FramebufferBindingRead] = framebuffer;
591 mFramebuffers[angle::FramebufferBindingDraw] = framebuffer;
592 mFunctions->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
593
594 mLocalDirtyBits.set(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
595 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
596 }
597 break;
598
599 case GL_READ_FRAMEBUFFER:
600 if (mFramebuffers[angle::FramebufferBindingRead] != framebuffer)
601 {
602 mFramebuffers[angle::FramebufferBindingRead] = framebuffer;
603 mFunctions->bindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
604
605 mLocalDirtyBits.set(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
606 }
607 break;
608
609 case GL_DRAW_FRAMEBUFFER:
610 if (mFramebuffers[angle::FramebufferBindingDraw] != framebuffer)
611 {
612 mFramebuffers[angle::FramebufferBindingDraw] = framebuffer;
613 mFunctions->bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
614
615 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
616 }
617 break;
618
619 default:
620 UNREACHABLE();
621 break;
622 }
623 }
624
bindRenderbuffer(GLenum type,GLuint renderbuffer)625 void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer)
626 {
627 ASSERT(type == GL_RENDERBUFFER);
628 if (mRenderbuffer != renderbuffer)
629 {
630 mRenderbuffer = renderbuffer;
631 mFunctions->bindRenderbuffer(type, mRenderbuffer);
632 }
633 }
634
bindTransformFeedback(GLenum type,GLuint transformFeedback)635 void StateManagerGL::bindTransformFeedback(GLenum type, GLuint transformFeedback)
636 {
637 ASSERT(type == GL_TRANSFORM_FEEDBACK);
638 if (mTransformFeedback != transformFeedback)
639 {
640 // Pause the current transform feedback if one is active.
641 // To handle virtualized contexts, StateManagerGL needs to be able to bind a new transform
642 // feedback at any time, even if there is one active.
643 if (mCurrentTransformFeedback != nullptr &&
644 mCurrentTransformFeedback->getTransformFeedbackID() != transformFeedback)
645 {
646 mCurrentTransformFeedback->syncPausedState(true);
647 mCurrentTransformFeedback = nullptr;
648 }
649
650 mTransformFeedback = transformFeedback;
651 mFunctions->bindTransformFeedback(type, mTransformFeedback);
652 onTransformFeedbackStateChange();
653 }
654 }
655
onTransformFeedbackStateChange()656 void StateManagerGL::onTransformFeedbackStateChange()
657 {
658 mLocalDirtyBits.set(gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING);
659 }
660
beginQuery(gl::QueryType type,QueryGL * queryObject,GLuint queryId)661 void StateManagerGL::beginQuery(gl::QueryType type, QueryGL *queryObject, GLuint queryId)
662 {
663 // Make sure this is a valid query type and there is no current active query of this type
664 ASSERT(mQueries[type] == nullptr);
665 ASSERT(queryId != 0);
666
667 mQueries[type] = queryObject;
668 mFunctions->beginQuery(ToGLenum(type), queryId);
669 }
670
endQuery(gl::QueryType type,QueryGL * queryObject,GLuint queryId)671 void StateManagerGL::endQuery(gl::QueryType type, QueryGL *queryObject, GLuint queryId)
672 {
673 ASSERT(queryObject != nullptr);
674 ASSERT(mQueries[type] == queryObject);
675 mQueries[type] = nullptr;
676 mFunctions->endQuery(ToGLenum(type));
677 }
678
updateDrawIndirectBufferBinding(const gl::Context * context)679 void StateManagerGL::updateDrawIndirectBufferBinding(const gl::Context *context)
680 {
681 gl::Buffer *drawIndirectBuffer =
682 context->getState().getTargetBuffer(gl::BufferBinding::DrawIndirect);
683 if (drawIndirectBuffer != nullptr)
684 {
685 const BufferGL *bufferGL = GetImplAs<BufferGL>(drawIndirectBuffer);
686 bindBuffer(gl::BufferBinding::DrawIndirect, bufferGL->getBufferID());
687 }
688 }
689
updateDispatchIndirectBufferBinding(const gl::Context * context)690 void StateManagerGL::updateDispatchIndirectBufferBinding(const gl::Context *context)
691 {
692 gl::Buffer *dispatchIndirectBuffer =
693 context->getState().getTargetBuffer(gl::BufferBinding::DispatchIndirect);
694 if (dispatchIndirectBuffer != nullptr)
695 {
696 const BufferGL *bufferGL = GetImplAs<BufferGL>(dispatchIndirectBuffer);
697 bindBuffer(gl::BufferBinding::DispatchIndirect, bufferGL->getBufferID());
698 }
699 }
700
pauseTransformFeedback()701 void StateManagerGL::pauseTransformFeedback()
702 {
703 if (mCurrentTransformFeedback != nullptr)
704 {
705 mCurrentTransformFeedback->syncPausedState(true);
706 onTransformFeedbackStateChange();
707 }
708 }
709
pauseAllQueries(const gl::Context * context)710 angle::Result StateManagerGL::pauseAllQueries(const gl::Context *context)
711 {
712 for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
713 {
714 QueryGL *previousQuery = mQueries[type];
715
716 if (previousQuery != nullptr)
717 {
718 ANGLE_TRY(previousQuery->pause(context));
719 mTemporaryPausedQueries[type] = previousQuery;
720 mQueries[type] = nullptr;
721 }
722 }
723
724 return angle::Result::Continue;
725 }
726
pauseQuery(const gl::Context * context,gl::QueryType type)727 angle::Result StateManagerGL::pauseQuery(const gl::Context *context, gl::QueryType type)
728 {
729 QueryGL *previousQuery = mQueries[type];
730
731 if (previousQuery)
732 {
733 ANGLE_TRY(previousQuery->pause(context));
734 mTemporaryPausedQueries[type] = previousQuery;
735 mQueries[type] = nullptr;
736 }
737
738 return angle::Result::Continue;
739 }
740
resumeAllQueries(const gl::Context * context)741 angle::Result StateManagerGL::resumeAllQueries(const gl::Context *context)
742 {
743 for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
744 {
745 QueryGL *pausedQuery = mTemporaryPausedQueries[type];
746
747 if (pausedQuery != nullptr)
748 {
749 ASSERT(mQueries[type] == nullptr);
750 ANGLE_TRY(pausedQuery->resume(context));
751 mTemporaryPausedQueries[type] = nullptr;
752 }
753 }
754
755 return angle::Result::Continue;
756 }
757
resumeQuery(const gl::Context * context,gl::QueryType type)758 angle::Result StateManagerGL::resumeQuery(const gl::Context *context, gl::QueryType type)
759 {
760 QueryGL *pausedQuery = mTemporaryPausedQueries[type];
761
762 if (pausedQuery != nullptr)
763 {
764 ANGLE_TRY(pausedQuery->resume(context));
765 mTemporaryPausedQueries[type] = nullptr;
766 }
767
768 return angle::Result::Continue;
769 }
770
onMakeCurrent(const gl::Context * context)771 angle::Result StateManagerGL::onMakeCurrent(const gl::Context *context)
772 {
773 const gl::State &glState = context->getState();
774
775 #if defined(ANGLE_ENABLE_ASSERTS)
776 // Temporarily pausing queries during context switch is not supported
777 for (QueryGL *pausedQuery : mTemporaryPausedQueries)
778 {
779 ASSERT(pausedQuery == nullptr);
780 }
781 #endif
782
783 // If the context has changed, pause the previous context's queries
784 auto contextID = context->getState().getContextID();
785 if (contextID != mPrevDrawContext)
786 {
787 for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
788 {
789 QueryGL *currentQuery = mQueries[type];
790 // Pause any old query object
791 if (currentQuery != nullptr)
792 {
793 ANGLE_TRY(currentQuery->pause(context));
794 mQueries[type] = nullptr;
795 }
796
797 // Check if this new context needs to resume a query
798 gl::Query *newQuery = glState.getActiveQuery(type);
799 if (newQuery != nullptr)
800 {
801 QueryGL *queryGL = GetImplAs<QueryGL>(newQuery);
802 ANGLE_TRY(queryGL->resume(context));
803 }
804 }
805 }
806 onTransformFeedbackStateChange();
807 mPrevDrawContext = contextID;
808
809 // Seamless cubemaps are required for ES3 and higher contexts. It should be the cheapest to set
810 // this state here since MakeCurrent is expected to be called less frequently than draw calls.
811 setTextureCubemapSeamlessEnabled(context->getClientMajorVersion() >= 3);
812
813 return angle::Result::Continue;
814 }
815
updateProgramTextureBindings(const gl::Context * context)816 void StateManagerGL::updateProgramTextureBindings(const gl::Context *context)
817 {
818 const gl::State &glState = context->getState();
819 const gl::ProgramExecutable *executable = glState.getProgramExecutable();
820
821 // It is possible there is no active program during a path operation.
822 if (!executable)
823 return;
824
825 const gl::ActiveTexturesCache &textures = glState.getActiveTexturesCache();
826 const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
827 const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
828
829 for (size_t textureUnitIndex : activeTextures)
830 {
831 gl::TextureType textureType = textureTypes[textureUnitIndex];
832 gl::Texture *texture = textures[textureUnitIndex];
833
834 // A nullptr texture indicates incomplete.
835 if (texture != nullptr)
836 {
837 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
838 ASSERT(!texture->hasAnyDirtyBit());
839 ASSERT(!textureGL->hasAnyDirtyBit());
840
841 activeTexture(textureUnitIndex);
842 bindTexture(textureType, textureGL->getTextureID());
843 }
844 else
845 {
846 activeTexture(textureUnitIndex);
847 bindTexture(textureType, 0);
848 }
849 }
850 }
851
updateProgramStorageBufferBindings(const gl::Context * context)852 void StateManagerGL::updateProgramStorageBufferBindings(const gl::Context *context)
853 {
854 const gl::State &glState = context->getState();
855 const gl::Program *program = glState.getProgram();
856
857 for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
858 blockIndex++)
859 {
860 GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
861 const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
862
863 if (shaderStorageBuffer.get() != nullptr)
864 {
865 BufferGL *bufferGL = GetImplAs<BufferGL>(shaderStorageBuffer.get());
866
867 if (shaderStorageBuffer.getSize() == 0)
868 {
869 bindBufferBase(gl::BufferBinding::ShaderStorage, binding, bufferGL->getBufferID());
870 }
871 else
872 {
873 bindBufferRange(gl::BufferBinding::ShaderStorage, binding, bufferGL->getBufferID(),
874 shaderStorageBuffer.getOffset(), shaderStorageBuffer.getSize());
875 }
876 }
877 }
878 }
879
updateProgramUniformBufferBindings(const gl::Context * context)880 void StateManagerGL::updateProgramUniformBufferBindings(const gl::Context *context)
881 {
882 // Sync the current program state
883 const gl::State &glState = context->getState();
884 const gl::Program *program = glState.getProgram();
885
886 for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
887 uniformBlockIndex++)
888 {
889 GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
890 const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding);
891
892 if (uniformBuffer.get() != nullptr)
893 {
894 BufferGL *bufferGL = GetImplAs<BufferGL>(uniformBuffer.get());
895
896 if (uniformBuffer.getSize() == 0)
897 {
898 bindBufferBase(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID());
899 }
900 else
901 {
902 bindBufferRange(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID(),
903 uniformBuffer.getOffset(), uniformBuffer.getSize());
904 }
905 }
906 }
907 }
908
updateProgramAtomicCounterBufferBindings(const gl::Context * context)909 void StateManagerGL::updateProgramAtomicCounterBufferBindings(const gl::Context *context)
910 {
911 const gl::State &glState = context->getState();
912 const gl::Program *program = glState.getProgram();
913
914 for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
915 {
916 GLuint binding = atomicCounterBuffer.binding;
917 const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
918
919 if (buffer.get() != nullptr)
920 {
921 BufferGL *bufferGL = GetImplAs<BufferGL>(buffer.get());
922
923 if (buffer.getSize() == 0)
924 {
925 bindBufferBase(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID());
926 }
927 else
928 {
929 bindBufferRange(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID(),
930 buffer.getOffset(), buffer.getSize());
931 }
932 }
933 }
934 }
935
updateProgramImageBindings(const gl::Context * context)936 void StateManagerGL::updateProgramImageBindings(const gl::Context *context)
937 {
938 const gl::State &glState = context->getState();
939 const gl::ProgramExecutable *executable = glState.getProgramExecutable();
940 const gl::Program *program = glState.getProgram();
941
942 // It is possible there is no active program during a path operation.
943 if (!executable || !program)
944 return;
945
946 ASSERT(context->getClientVersion() >= gl::ES_3_1 || program->getImageBindings().empty());
947 for (size_t imageUnitIndex : executable->getActiveImagesMask())
948 {
949 const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
950 const TextureGL *textureGL = SafeGetImplAs<TextureGL>(imageUnit.texture.get());
951 if (textureGL)
952 {
953 bindImageTexture(imageUnitIndex, textureGL->getTextureID(), imageUnit.level,
954 imageUnit.layered, imageUnit.layer, imageUnit.access,
955 imageUnit.format);
956 }
957 else
958 {
959 bindImageTexture(imageUnitIndex, 0, imageUnit.level, imageUnit.layered, imageUnit.layer,
960 imageUnit.access, imageUnit.format);
961 }
962 }
963 }
964
setAttributeCurrentData(size_t index,const gl::VertexAttribCurrentValueData & data)965 void StateManagerGL::setAttributeCurrentData(size_t index,
966 const gl::VertexAttribCurrentValueData &data)
967 {
968 if (mVertexAttribCurrentValues[index] != data)
969 {
970 mVertexAttribCurrentValues[index] = data;
971 switch (mVertexAttribCurrentValues[index].Type)
972 {
973 case gl::VertexAttribType::Float:
974 mFunctions->vertexAttrib4fv(static_cast<GLuint>(index),
975 mVertexAttribCurrentValues[index].Values.FloatValues);
976 break;
977 case gl::VertexAttribType::Int:
978 mFunctions->vertexAttribI4iv(static_cast<GLuint>(index),
979 mVertexAttribCurrentValues[index].Values.IntValues);
980 break;
981 case gl::VertexAttribType::UnsignedInt:
982 mFunctions->vertexAttribI4uiv(
983 static_cast<GLuint>(index),
984 mVertexAttribCurrentValues[index].Values.UnsignedIntValues);
985 break;
986 default:
987 UNREACHABLE();
988 }
989
990 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CURRENT_VALUES);
991 mLocalDirtyCurrentValues.set(index);
992 }
993 }
994
setScissorTestEnabled(bool enabled)995 void StateManagerGL::setScissorTestEnabled(bool enabled)
996 {
997 if (mScissorTestEnabled != enabled)
998 {
999 mScissorTestEnabled = enabled;
1000 if (mScissorTestEnabled)
1001 {
1002 mFunctions->enable(GL_SCISSOR_TEST);
1003 }
1004 else
1005 {
1006 mFunctions->disable(GL_SCISSOR_TEST);
1007 }
1008
1009 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
1010 }
1011 }
1012
setScissor(const gl::Rectangle & scissor)1013 void StateManagerGL::setScissor(const gl::Rectangle &scissor)
1014 {
1015 if (scissor != mScissor)
1016 {
1017 mScissor = scissor;
1018 mFunctions->scissor(mScissor.x, mScissor.y, mScissor.width, mScissor.height);
1019
1020 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR);
1021 }
1022 }
1023
setViewport(const gl::Rectangle & viewport)1024 void StateManagerGL::setViewport(const gl::Rectangle &viewport)
1025 {
1026 if (viewport != mViewport)
1027 {
1028 mViewport = viewport;
1029 mFunctions->viewport(mViewport.x, mViewport.y, mViewport.width, mViewport.height);
1030
1031 mLocalDirtyBits.set(gl::State::DIRTY_BIT_VIEWPORT);
1032 }
1033 }
1034
setDepthRange(float near,float far)1035 void StateManagerGL::setDepthRange(float near, float far)
1036 {
1037 mNear = near;
1038 mFar = far;
1039
1040 // The glDepthRangef function isn't available until OpenGL 4.1. Prefer it when it is
1041 // available because OpenGL ES only works in floats.
1042 if (mFunctions->depthRangef)
1043 {
1044 mFunctions->depthRangef(mNear, mFar);
1045 }
1046 else
1047 {
1048 ASSERT(mFunctions->depthRange);
1049 mFunctions->depthRange(mNear, mFar);
1050 }
1051
1052 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_RANGE);
1053 }
1054
setBlendEnabled(bool enabled)1055 void StateManagerGL::setBlendEnabled(bool enabled)
1056 {
1057 const gl::DrawBufferMask mask =
1058 enabled ? mBlendStateExt.mMaxEnabledMask : gl::DrawBufferMask::Zero();
1059 if (mBlendStateExt.mEnabledMask == mask)
1060 {
1061 return;
1062 }
1063
1064 if (enabled)
1065 {
1066 mFunctions->enable(GL_BLEND);
1067 }
1068 else
1069 {
1070 mFunctions->disable(GL_BLEND);
1071 }
1072
1073 mBlendStateExt.setEnabled(enabled);
1074 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
1075 }
1076
setBlendEnabledIndexed(const gl::DrawBufferMask enabledMask)1077 void StateManagerGL::setBlendEnabledIndexed(const gl::DrawBufferMask enabledMask)
1078 {
1079 if (mBlendStateExt.mEnabledMask == enabledMask)
1080 {
1081 return;
1082 }
1083
1084 // Get DrawBufferMask of buffers with different blend enable state
1085 gl::DrawBufferMask diffMask = mBlendStateExt.mEnabledMask ^ enabledMask;
1086 const size_t diffCount = diffMask.count();
1087
1088 // Check if enabling or disabling blending for all buffers reduces the number of subsequent
1089 // indexed commands. Implicitly handles the case when the new blend enable state is the same for
1090 // all buffers.
1091 if (diffCount > 1)
1092 {
1093 // The number of indexed blend enable commands in case a mass disable is used.
1094 const size_t enabledCount = enabledMask.count();
1095
1096 // The mask and the number of indexed blend disable commands in case a mass enable is used.
1097 const gl::DrawBufferMask disabledMask = enabledMask ^ mBlendStateExt.mMaxEnabledMask;
1098 const size_t disabledCount = disabledMask.count();
1099
1100 if (enabledCount < diffCount && enabledCount <= disabledCount)
1101 {
1102 diffMask = enabledMask;
1103 mFunctions->disable(GL_BLEND);
1104 }
1105 else if (disabledCount < diffCount && disabledCount <= enabledCount)
1106 {
1107 diffMask = disabledMask;
1108 mFunctions->enable(GL_BLEND);
1109 }
1110 }
1111
1112 for (size_t drawBufferIndex : diffMask)
1113 {
1114 if (enabledMask.test(drawBufferIndex))
1115 {
1116 mFunctions->enablei(GL_BLEND, static_cast<GLuint>(drawBufferIndex));
1117 }
1118 else
1119 {
1120 mFunctions->disablei(GL_BLEND, static_cast<GLuint>(drawBufferIndex));
1121 }
1122 }
1123
1124 mBlendStateExt.mEnabledMask = enabledMask;
1125 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
1126 }
1127
setBlendColor(const gl::ColorF & blendColor)1128 void StateManagerGL::setBlendColor(const gl::ColorF &blendColor)
1129 {
1130 if (mBlendColor != blendColor)
1131 {
1132 mBlendColor = blendColor;
1133 mFunctions->blendColor(mBlendColor.red, mBlendColor.green, mBlendColor.blue,
1134 mBlendColor.alpha);
1135
1136 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_COLOR);
1137 }
1138 }
1139
setBlendFuncs(const gl::BlendStateExt & blendStateExt)1140 void StateManagerGL::setBlendFuncs(const gl::BlendStateExt &blendStateExt)
1141 {
1142 if (mBlendStateExt.mSrcColor == blendStateExt.mSrcColor &&
1143 mBlendStateExt.mDstColor == blendStateExt.mDstColor &&
1144 mBlendStateExt.mSrcAlpha == blendStateExt.mSrcAlpha &&
1145 mBlendStateExt.mDstAlpha == blendStateExt.mDstAlpha)
1146 {
1147 return;
1148 }
1149
1150 if (!mIndependentBlendStates)
1151 {
1152 mFunctions->blendFuncSeparate(
1153 blendStateExt.getSrcColorIndexed(0), blendStateExt.getDstColorIndexed(0),
1154 blendStateExt.getSrcAlphaIndexed(0), blendStateExt.getDstAlphaIndexed(0));
1155 }
1156 else
1157 {
1158 // Get DrawBufferMask of buffers with different blend factors
1159 gl::DrawBufferMask diffMask =
1160 mBlendStateExt.compareFactors(blendStateExt.mSrcColor, blendStateExt.mDstColor,
1161 blendStateExt.mSrcAlpha, blendStateExt.mDstAlpha);
1162 size_t diffCount = diffMask.count();
1163
1164 // Check if setting all buffers to the same value reduces the number of subsequent indexed
1165 // commands. Implicitly handles the case when the new blend function state is the same for
1166 // all buffers.
1167 if (diffCount > 1)
1168 {
1169 bool found = false;
1170 gl::BlendStateExt::FactorStorage::Type commonSrcColor = 0;
1171 gl::BlendStateExt::FactorStorage::Type commonDstColor = 0;
1172 gl::BlendStateExt::FactorStorage::Type commonSrcAlpha = 0;
1173 gl::BlendStateExt::FactorStorage::Type commonDstAlpha = 0;
1174 for (size_t i = 0; i < mBlendStateExt.mMaxDrawBuffers - 1; i++)
1175 {
1176 const gl::BlendStateExt::FactorStorage::Type tempCommonSrcColor =
1177 blendStateExt.expandSrcColorIndexed(i);
1178 const gl::BlendStateExt::FactorStorage::Type tempCommonDstColor =
1179 blendStateExt.expandDstColorIndexed(i);
1180 const gl::BlendStateExt::FactorStorage::Type tempCommonSrcAlpha =
1181 blendStateExt.expandSrcAlphaIndexed(i);
1182 const gl::BlendStateExt::FactorStorage::Type tempCommonDstAlpha =
1183 blendStateExt.expandDstAlphaIndexed(i);
1184
1185 const gl::DrawBufferMask tempDiffMask = blendStateExt.compareFactors(
1186 tempCommonSrcColor, tempCommonDstColor, tempCommonSrcAlpha, tempCommonDstAlpha);
1187
1188 const size_t tempDiffCount = tempDiffMask.count();
1189 if (tempDiffCount < diffCount)
1190 {
1191 found = true;
1192 diffMask = tempDiffMask;
1193 diffCount = tempDiffCount;
1194 commonSrcColor = tempCommonSrcColor;
1195 commonDstColor = tempCommonDstColor;
1196 commonSrcAlpha = tempCommonSrcAlpha;
1197 commonDstAlpha = tempCommonDstAlpha;
1198 if (tempDiffCount == 0)
1199 {
1200 break; // the blend factors are the same for all buffers
1201 }
1202 }
1203 }
1204 if (found)
1205 {
1206 mFunctions->blendFuncSeparate(
1207 ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonSrcColor)),
1208 ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonDstColor)),
1209 ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonSrcAlpha)),
1210 ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonDstAlpha)));
1211 }
1212 }
1213
1214 for (size_t drawBufferIndex : diffMask)
1215 {
1216 mFunctions->blendFuncSeparatei(static_cast<GLuint>(drawBufferIndex),
1217 blendStateExt.getSrcColorIndexed(drawBufferIndex),
1218 blendStateExt.getDstColorIndexed(drawBufferIndex),
1219 blendStateExt.getSrcAlphaIndexed(drawBufferIndex),
1220 blendStateExt.getDstAlphaIndexed(drawBufferIndex));
1221 }
1222 }
1223 mBlendStateExt.mSrcColor = blendStateExt.mSrcColor;
1224 mBlendStateExt.mDstColor = blendStateExt.mDstColor;
1225 mBlendStateExt.mSrcAlpha = blendStateExt.mSrcAlpha;
1226 mBlendStateExt.mDstAlpha = blendStateExt.mDstAlpha;
1227 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);
1228 }
1229
setBlendEquations(const gl::BlendStateExt & blendStateExt)1230 void StateManagerGL::setBlendEquations(const gl::BlendStateExt &blendStateExt)
1231 {
1232 if (mBlendStateExt.mEquationColor == blendStateExt.mEquationColor &&
1233 mBlendStateExt.mEquationAlpha == blendStateExt.mEquationAlpha)
1234 {
1235 return;
1236 }
1237
1238 if (!mIndependentBlendStates)
1239 {
1240 mFunctions->blendEquationSeparate(blendStateExt.getEquationColorIndexed(0),
1241 blendStateExt.getEquationAlphaIndexed(0));
1242 }
1243 else
1244 {
1245 // Get DrawBufferMask of buffers with different blend equations
1246 gl::DrawBufferMask diffMask = mBlendStateExt.compareEquations(blendStateExt.mEquationColor,
1247 blendStateExt.mEquationAlpha);
1248 size_t diffCount = diffMask.count();
1249
1250 // Check if setting all buffers to the same value reduces the number of subsequent indexed
1251 // commands. Implicitly handles the case when the new blend equation state is the same for
1252 // all buffers.
1253 if (diffCount > 1)
1254 {
1255 bool found = false;
1256 gl::BlendStateExt::EquationStorage::Type commonEquationColor = 0;
1257 gl::BlendStateExt::EquationStorage::Type commonEquationAlpha = 0;
1258 for (size_t i = 0; i < mBlendStateExt.mMaxDrawBuffers - 1; i++)
1259 {
1260 const gl::BlendStateExt::EquationStorage::Type tempCommonEquationColor =
1261 blendStateExt.expandEquationColorIndexed(i);
1262 const gl::BlendStateExt::EquationStorage::Type tempCommonEquationAlpha =
1263 blendStateExt.expandEquationAlphaIndexed(i);
1264
1265 const gl::DrawBufferMask tempDiffMask = blendStateExt.compareEquations(
1266 tempCommonEquationColor, tempCommonEquationAlpha);
1267
1268 const size_t tempDiffCount = tempDiffMask.count();
1269 if (tempDiffCount < diffCount)
1270 {
1271 found = true;
1272 diffMask = tempDiffMask;
1273 diffCount = tempDiffCount;
1274 commonEquationColor = tempCommonEquationColor;
1275 commonEquationAlpha = tempCommonEquationAlpha;
1276 if (tempDiffCount == 0)
1277 {
1278 break; // the new blend equations are the same for all buffers
1279 }
1280 }
1281 }
1282 if (found)
1283 {
1284 mFunctions->blendEquationSeparate(
1285 ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
1286 0, commonEquationColor)),
1287 ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
1288 0, commonEquationAlpha)));
1289 }
1290 }
1291
1292 for (size_t drawBufferIndex : diffMask)
1293 {
1294 mFunctions->blendEquationSeparatei(
1295 static_cast<GLuint>(drawBufferIndex),
1296 blendStateExt.getEquationColorIndexed(drawBufferIndex),
1297 blendStateExt.getEquationAlphaIndexed(drawBufferIndex));
1298 }
1299 }
1300 mBlendStateExt.mEquationColor = blendStateExt.mEquationColor;
1301 mBlendStateExt.mEquationAlpha = blendStateExt.mEquationAlpha;
1302 mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
1303 }
1304
setColorMask(bool red,bool green,bool blue,bool alpha)1305 void StateManagerGL::setColorMask(bool red, bool green, bool blue, bool alpha)
1306 {
1307 const gl::BlendStateExt::ColorMaskStorage::Type mask =
1308 mBlendStateExt.expandColorMaskValue(red, green, blue, alpha);
1309 if (mBlendStateExt.mColorMask != mask)
1310 {
1311 mFunctions->colorMask(red, green, blue, alpha);
1312 mBlendStateExt.mColorMask = mask;
1313 mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
1314 }
1315 }
1316
setSampleAlphaToCoverageEnabled(bool enabled)1317 void StateManagerGL::setSampleAlphaToCoverageEnabled(bool enabled)
1318 {
1319 if (mSampleAlphaToCoverageEnabled != enabled)
1320 {
1321 mSampleAlphaToCoverageEnabled = enabled;
1322 if (mSampleAlphaToCoverageEnabled)
1323 {
1324 mFunctions->enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
1325 }
1326 else
1327 {
1328 mFunctions->disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
1329 }
1330
1331 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
1332 }
1333 }
1334
setSampleCoverageEnabled(bool enabled)1335 void StateManagerGL::setSampleCoverageEnabled(bool enabled)
1336 {
1337 if (mSampleCoverageEnabled != enabled)
1338 {
1339 mSampleCoverageEnabled = enabled;
1340 if (mSampleCoverageEnabled)
1341 {
1342 mFunctions->enable(GL_SAMPLE_COVERAGE);
1343 }
1344 else
1345 {
1346 mFunctions->disable(GL_SAMPLE_COVERAGE);
1347 }
1348
1349 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
1350 }
1351 }
1352
setSampleCoverage(float value,bool invert)1353 void StateManagerGL::setSampleCoverage(float value, bool invert)
1354 {
1355 if (mSampleCoverageValue != value || mSampleCoverageInvert != invert)
1356 {
1357 mSampleCoverageValue = value;
1358 mSampleCoverageInvert = invert;
1359 mFunctions->sampleCoverage(mSampleCoverageValue, mSampleCoverageInvert);
1360
1361 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE);
1362 }
1363 }
1364
setSampleMaskEnabled(bool enabled)1365 void StateManagerGL::setSampleMaskEnabled(bool enabled)
1366 {
1367 if (mSampleMaskEnabled != enabled)
1368 {
1369 mSampleMaskEnabled = enabled;
1370 if (mSampleMaskEnabled)
1371 {
1372 mFunctions->enable(GL_SAMPLE_MASK);
1373 }
1374 else
1375 {
1376 mFunctions->disable(GL_SAMPLE_MASK);
1377 }
1378
1379 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_MASK_ENABLED);
1380 }
1381 }
1382
setSampleMaski(GLuint maskNumber,GLbitfield mask)1383 void StateManagerGL::setSampleMaski(GLuint maskNumber, GLbitfield mask)
1384 {
1385 ASSERT(maskNumber < mSampleMaskValues.size());
1386 if (mSampleMaskValues[maskNumber] != mask)
1387 {
1388 mSampleMaskValues[maskNumber] = mask;
1389 mFunctions->sampleMaski(maskNumber, mask);
1390
1391 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_MASK);
1392 }
1393 }
1394
1395 // Depth and stencil redundant state changes are guarded in the
1396 // frontend so for related cases here just set the dirty bit
1397 // and update backend states.
setDepthTestEnabled(bool enabled)1398 void StateManagerGL::setDepthTestEnabled(bool enabled)
1399 {
1400 mDepthTestEnabled = enabled;
1401 if (mDepthTestEnabled)
1402 {
1403 mFunctions->enable(GL_DEPTH_TEST);
1404 }
1405 else
1406 {
1407 mFunctions->disable(GL_DEPTH_TEST);
1408 }
1409
1410 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED);
1411 }
1412
setDepthFunc(GLenum depthFunc)1413 void StateManagerGL::setDepthFunc(GLenum depthFunc)
1414 {
1415 mDepthFunc = depthFunc;
1416 mFunctions->depthFunc(mDepthFunc);
1417
1418 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_FUNC);
1419 }
1420
setDepthMask(bool mask)1421 void StateManagerGL::setDepthMask(bool mask)
1422 {
1423 mDepthMask = mask;
1424 mFunctions->depthMask(mDepthMask);
1425
1426 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_MASK);
1427 }
1428
setStencilTestEnabled(bool enabled)1429 void StateManagerGL::setStencilTestEnabled(bool enabled)
1430 {
1431 mStencilTestEnabled = enabled;
1432 if (mStencilTestEnabled)
1433 {
1434 mFunctions->enable(GL_STENCIL_TEST);
1435 }
1436 else
1437 {
1438 mFunctions->disable(GL_STENCIL_TEST);
1439 }
1440
1441 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED);
1442 }
1443
setStencilFrontWritemask(GLuint mask)1444 void StateManagerGL::setStencilFrontWritemask(GLuint mask)
1445 {
1446 mStencilFrontWritemask = mask;
1447 mFunctions->stencilMaskSeparate(GL_FRONT, mStencilFrontWritemask);
1448
1449 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
1450 }
1451
setStencilBackWritemask(GLuint mask)1452 void StateManagerGL::setStencilBackWritemask(GLuint mask)
1453 {
1454 mStencilBackWritemask = mask;
1455 mFunctions->stencilMaskSeparate(GL_BACK, mStencilBackWritemask);
1456
1457 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
1458 }
1459
setStencilFrontFuncs(GLenum func,GLint ref,GLuint mask)1460 void StateManagerGL::setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask)
1461 {
1462 mStencilFrontFunc = func;
1463 mStencilFrontRef = ref;
1464 mStencilFrontValueMask = mask;
1465 mFunctions->stencilFuncSeparate(GL_FRONT, mStencilFrontFunc, mStencilFrontRef,
1466 mStencilFrontValueMask);
1467
1468 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT);
1469 }
1470
setStencilBackFuncs(GLenum func,GLint ref,GLuint mask)1471 void StateManagerGL::setStencilBackFuncs(GLenum func, GLint ref, GLuint mask)
1472 {
1473 mStencilBackFunc = func;
1474 mStencilBackRef = ref;
1475 mStencilBackValueMask = mask;
1476 mFunctions->stencilFuncSeparate(GL_BACK, mStencilBackFunc, mStencilBackRef,
1477 mStencilBackValueMask);
1478
1479 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK);
1480 }
1481
setStencilFrontOps(GLenum sfail,GLenum dpfail,GLenum dppass)1482 void StateManagerGL::setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass)
1483 {
1484 mStencilFrontStencilFailOp = sfail;
1485 mStencilFrontStencilPassDepthFailOp = dpfail;
1486 mStencilFrontStencilPassDepthPassOp = dppass;
1487 mFunctions->stencilOpSeparate(GL_FRONT, mStencilFrontStencilFailOp,
1488 mStencilFrontStencilPassDepthFailOp,
1489 mStencilFrontStencilPassDepthPassOp);
1490
1491 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_FRONT);
1492 }
1493
setStencilBackOps(GLenum sfail,GLenum dpfail,GLenum dppass)1494 void StateManagerGL::setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass)
1495 {
1496 mStencilBackStencilFailOp = sfail;
1497 mStencilBackStencilPassDepthFailOp = dpfail;
1498 mStencilBackStencilPassDepthPassOp = dppass;
1499 mFunctions->stencilOpSeparate(GL_BACK, mStencilBackStencilFailOp,
1500 mStencilBackStencilPassDepthFailOp,
1501 mStencilBackStencilPassDepthPassOp);
1502
1503 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_BACK);
1504 }
1505
setCullFaceEnabled(bool enabled)1506 void StateManagerGL::setCullFaceEnabled(bool enabled)
1507 {
1508 if (mCullFaceEnabled != enabled)
1509 {
1510 mCullFaceEnabled = enabled;
1511 if (mCullFaceEnabled)
1512 {
1513 mFunctions->enable(GL_CULL_FACE);
1514 }
1515 else
1516 {
1517 mFunctions->disable(GL_CULL_FACE);
1518 }
1519
1520 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE_ENABLED);
1521 }
1522 }
1523
setCullFace(gl::CullFaceMode cullFace)1524 void StateManagerGL::setCullFace(gl::CullFaceMode cullFace)
1525 {
1526 if (mCullFace != cullFace)
1527 {
1528 mCullFace = cullFace;
1529 mFunctions->cullFace(ToGLenum(mCullFace));
1530
1531 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE);
1532 }
1533 }
1534
setFrontFace(GLenum frontFace)1535 void StateManagerGL::setFrontFace(GLenum frontFace)
1536 {
1537 if (mFrontFace != frontFace)
1538 {
1539 mFrontFace = frontFace;
1540 mFunctions->frontFace(mFrontFace);
1541
1542 mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRONT_FACE);
1543 }
1544 }
1545
setPolygonOffsetFillEnabled(bool enabled)1546 void StateManagerGL::setPolygonOffsetFillEnabled(bool enabled)
1547 {
1548 if (mPolygonOffsetFillEnabled != enabled)
1549 {
1550 mPolygonOffsetFillEnabled = enabled;
1551 if (mPolygonOffsetFillEnabled)
1552 {
1553 mFunctions->enable(GL_POLYGON_OFFSET_FILL);
1554 }
1555 else
1556 {
1557 mFunctions->disable(GL_POLYGON_OFFSET_FILL);
1558 }
1559
1560 mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
1561 }
1562 }
1563
setPolygonOffset(float factor,float units)1564 void StateManagerGL::setPolygonOffset(float factor, float units)
1565 {
1566 if (mPolygonOffsetFactor != factor || mPolygonOffsetUnits != units)
1567 {
1568 mPolygonOffsetFactor = factor;
1569 mPolygonOffsetUnits = units;
1570 mFunctions->polygonOffset(mPolygonOffsetFactor, mPolygonOffsetUnits);
1571
1572 mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET);
1573 }
1574 }
1575
setRasterizerDiscardEnabled(bool enabled)1576 void StateManagerGL::setRasterizerDiscardEnabled(bool enabled)
1577 {
1578 if (mRasterizerDiscardEnabled != enabled)
1579 {
1580 mRasterizerDiscardEnabled = enabled;
1581 if (mRasterizerDiscardEnabled)
1582 {
1583 mFunctions->enable(GL_RASTERIZER_DISCARD);
1584 }
1585 else
1586 {
1587 mFunctions->disable(GL_RASTERIZER_DISCARD);
1588 }
1589
1590 mLocalDirtyBits.set(gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
1591 }
1592 }
1593
setLineWidth(float width)1594 void StateManagerGL::setLineWidth(float width)
1595 {
1596 if (mLineWidth != width)
1597 {
1598 mLineWidth = width;
1599 mFunctions->lineWidth(mLineWidth);
1600
1601 mLocalDirtyBits.set(gl::State::DIRTY_BIT_LINE_WIDTH);
1602 }
1603 }
1604
setPrimitiveRestartEnabled(const gl::Context * context,bool enabled)1605 angle::Result StateManagerGL::setPrimitiveRestartEnabled(const gl::Context *context, bool enabled)
1606 {
1607 if (mPrimitiveRestartEnabled != enabled)
1608 {
1609 GLenum cap = mFeatures.emulatePrimitiveRestartFixedIndex.enabled
1610 ? GL_PRIMITIVE_RESTART
1611 : GL_PRIMITIVE_RESTART_FIXED_INDEX;
1612
1613 if (enabled)
1614 {
1615 ANGLE_GL_TRY(context, mFunctions->enable(cap));
1616 }
1617 else
1618 {
1619 ANGLE_GL_TRY(context, mFunctions->disable(cap));
1620 }
1621 mPrimitiveRestartEnabled = enabled;
1622
1623 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
1624 }
1625
1626 return angle::Result::Continue;
1627 }
1628
setPrimitiveRestartIndex(const gl::Context * context,GLuint index)1629 angle::Result StateManagerGL::setPrimitiveRestartIndex(const gl::Context *context, GLuint index)
1630 {
1631 if (mPrimitiveRestartIndex != index)
1632 {
1633 ANGLE_GL_TRY(context, mFunctions->primitiveRestartIndex(index));
1634 mPrimitiveRestartIndex = index;
1635
1636 // No dirty bit for this state, it is not exposed to the frontend.
1637 }
1638
1639 return angle::Result::Continue;
1640 }
1641
setClearDepth(float clearDepth)1642 void StateManagerGL::setClearDepth(float clearDepth)
1643 {
1644 if (mClearDepth != clearDepth)
1645 {
1646 mClearDepth = clearDepth;
1647
1648 // The glClearDepthf function isn't available until OpenGL 4.1. Prefer it when it is
1649 // available because OpenGL ES only works in floats.
1650 if (mFunctions->clearDepthf)
1651 {
1652 mFunctions->clearDepthf(mClearDepth);
1653 }
1654 else
1655 {
1656 ASSERT(mFunctions->clearDepth);
1657 mFunctions->clearDepth(mClearDepth);
1658 }
1659
1660 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_DEPTH);
1661 }
1662 }
1663
setClearColor(const gl::ColorF & clearColor)1664 void StateManagerGL::setClearColor(const gl::ColorF &clearColor)
1665 {
1666 gl::ColorF modifiedClearColor = clearColor;
1667 if (mFeatures.clearToZeroOrOneBroken.enabled &&
1668 (clearColor.red == 1.0f || clearColor.red == 0.0f) &&
1669 (clearColor.green == 1.0f || clearColor.green == 0.0f) &&
1670 (clearColor.blue == 1.0f || clearColor.blue == 0.0f) &&
1671 (clearColor.alpha == 1.0f || clearColor.alpha == 0.0f))
1672 {
1673 if (clearColor.alpha == 1.0f)
1674 {
1675 modifiedClearColor.alpha = 2.0f;
1676 }
1677 else
1678 {
1679 modifiedClearColor.alpha = -1.0f;
1680 }
1681 }
1682
1683 if (mClearColor != modifiedClearColor)
1684 {
1685 mClearColor = modifiedClearColor;
1686 mFunctions->clearColor(mClearColor.red, mClearColor.green, mClearColor.blue,
1687 mClearColor.alpha);
1688
1689 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_COLOR);
1690 }
1691 }
1692
setClearStencil(GLint clearStencil)1693 void StateManagerGL::setClearStencil(GLint clearStencil)
1694 {
1695 if (mClearStencil != clearStencil)
1696 {
1697 mClearStencil = clearStencil;
1698 mFunctions->clearStencil(mClearStencil);
1699
1700 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_STENCIL);
1701 }
1702 }
1703
syncState(const gl::Context * context,const gl::State::DirtyBits & glDirtyBits,const gl::State::DirtyBits & bitMask)1704 angle::Result StateManagerGL::syncState(const gl::Context *context,
1705 const gl::State::DirtyBits &glDirtyBits,
1706 const gl::State::DirtyBits &bitMask)
1707 {
1708 const gl::State &state = context->getState();
1709
1710 const gl::State::DirtyBits glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits) & bitMask;
1711 if (!glAndLocalDirtyBits.any())
1712 {
1713 return angle::Result::Continue;
1714 }
1715
1716 // TODO(jmadill): Investigate only syncing vertex state for active attributes
1717 for (auto iter = glAndLocalDirtyBits.begin(), endIter = glAndLocalDirtyBits.end();
1718 iter != endIter; ++iter)
1719 {
1720 switch (*iter)
1721 {
1722 case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
1723 setScissorTestEnabled(state.isScissorTestEnabled());
1724 break;
1725 case gl::State::DIRTY_BIT_SCISSOR:
1726 {
1727 const gl::Rectangle &scissor = state.getScissor();
1728 setScissor(scissor);
1729 }
1730 break;
1731 case gl::State::DIRTY_BIT_VIEWPORT:
1732 {
1733 const gl::Rectangle &viewport = state.getViewport();
1734 setViewport(viewport);
1735 }
1736 break;
1737 case gl::State::DIRTY_BIT_DEPTH_RANGE:
1738 setDepthRange(state.getNearPlane(), state.getFarPlane());
1739 break;
1740 case gl::State::DIRTY_BIT_BLEND_ENABLED:
1741 if (mIndependentBlendStates)
1742 {
1743 setBlendEnabledIndexed(state.getBlendEnabledDrawBufferMask());
1744 }
1745 else
1746 {
1747 setBlendEnabled(state.isBlendEnabled());
1748 }
1749 break;
1750 case gl::State::DIRTY_BIT_BLEND_COLOR:
1751 setBlendColor(state.getBlendColor());
1752 break;
1753 case gl::State::DIRTY_BIT_BLEND_FUNCS:
1754 {
1755 setBlendFuncs(state.getBlendStateExt());
1756 break;
1757 }
1758 case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
1759 {
1760 setBlendEquations(state.getBlendStateExt());
1761 break;
1762 }
1763 case gl::State::DIRTY_BIT_COLOR_MASK:
1764 {
1765 const gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
1766 const FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
1767 const bool disableAlphaWrite =
1768 framebufferGL->hasEmulatedAlphaChannelTextureAttachment();
1769
1770 setColorMaskForFramebuffer(state.getBlendStateExt(), disableAlphaWrite);
1771 break;
1772 }
1773 case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
1774 setSampleAlphaToCoverageEnabled(state.isSampleAlphaToCoverageEnabled());
1775 break;
1776 case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
1777 setSampleCoverageEnabled(state.isSampleCoverageEnabled());
1778 break;
1779 case gl::State::DIRTY_BIT_SAMPLE_COVERAGE:
1780 setSampleCoverage(state.getSampleCoverageValue(), state.getSampleCoverageInvert());
1781 break;
1782 case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
1783 setDepthTestEnabled(state.isDepthTestEnabled());
1784 break;
1785 case gl::State::DIRTY_BIT_DEPTH_FUNC:
1786 setDepthFunc(state.getDepthStencilState().depthFunc);
1787 break;
1788 case gl::State::DIRTY_BIT_DEPTH_MASK:
1789 setDepthMask(state.getDepthStencilState().depthMask);
1790 break;
1791 case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
1792 setStencilTestEnabled(state.isStencilTestEnabled());
1793 break;
1794 case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
1795 {
1796 const auto &depthStencilState = state.getDepthStencilState();
1797 setStencilFrontFuncs(depthStencilState.stencilFunc, state.getStencilRef(),
1798 depthStencilState.stencilMask);
1799 break;
1800 }
1801 case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
1802 {
1803 const auto &depthStencilState = state.getDepthStencilState();
1804 setStencilBackFuncs(depthStencilState.stencilBackFunc, state.getStencilBackRef(),
1805 depthStencilState.stencilBackMask);
1806 break;
1807 }
1808 case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
1809 {
1810 const auto &depthStencilState = state.getDepthStencilState();
1811 setStencilFrontOps(depthStencilState.stencilFail,
1812 depthStencilState.stencilPassDepthFail,
1813 depthStencilState.stencilPassDepthPass);
1814 break;
1815 }
1816 case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
1817 {
1818 const auto &depthStencilState = state.getDepthStencilState();
1819 setStencilBackOps(depthStencilState.stencilBackFail,
1820 depthStencilState.stencilBackPassDepthFail,
1821 depthStencilState.stencilBackPassDepthPass);
1822 break;
1823 }
1824 case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
1825 setStencilFrontWritemask(state.getDepthStencilState().stencilWritemask);
1826 break;
1827 case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
1828 setStencilBackWritemask(state.getDepthStencilState().stencilBackWritemask);
1829 break;
1830 case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
1831 setCullFaceEnabled(state.isCullFaceEnabled());
1832 break;
1833 case gl::State::DIRTY_BIT_CULL_FACE:
1834 setCullFace(state.getRasterizerState().cullMode);
1835 break;
1836 case gl::State::DIRTY_BIT_FRONT_FACE:
1837 setFrontFace(state.getRasterizerState().frontFace);
1838 break;
1839 case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
1840 setPolygonOffsetFillEnabled(state.isPolygonOffsetFillEnabled());
1841 break;
1842 case gl::State::DIRTY_BIT_POLYGON_OFFSET:
1843 {
1844 const auto &rasterizerState = state.getRasterizerState();
1845 setPolygonOffset(rasterizerState.polygonOffsetFactor,
1846 rasterizerState.polygonOffsetUnits);
1847 break;
1848 }
1849 case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
1850 setRasterizerDiscardEnabled(state.isRasterizerDiscardEnabled());
1851 break;
1852 case gl::State::DIRTY_BIT_LINE_WIDTH:
1853 setLineWidth(state.getLineWidth());
1854 break;
1855 case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
1856 ANGLE_TRY(setPrimitiveRestartEnabled(context, state.isPrimitiveRestartEnabled()));
1857 break;
1858 case gl::State::DIRTY_BIT_CLEAR_COLOR:
1859 setClearColor(state.getColorClearValue());
1860 break;
1861 case gl::State::DIRTY_BIT_CLEAR_DEPTH:
1862 setClearDepth(state.getDepthClearValue());
1863 break;
1864 case gl::State::DIRTY_BIT_CLEAR_STENCIL:
1865 setClearStencil(state.getStencilClearValue());
1866 break;
1867 case gl::State::DIRTY_BIT_UNPACK_STATE:
1868 setPixelUnpackState(state.getUnpackState());
1869 break;
1870 case gl::State::DIRTY_BIT_UNPACK_BUFFER_BINDING:
1871 setPixelUnpackBuffer(state.getTargetBuffer(gl::BufferBinding::PixelUnpack));
1872 break;
1873 case gl::State::DIRTY_BIT_PACK_STATE:
1874 setPixelPackState(state.getPackState());
1875 break;
1876 case gl::State::DIRTY_BIT_PACK_BUFFER_BINDING:
1877 setPixelPackBuffer(state.getTargetBuffer(gl::BufferBinding::PixelPack));
1878 break;
1879 case gl::State::DIRTY_BIT_DITHER_ENABLED:
1880 setDitherEnabled(state.isDitherEnabled());
1881 break;
1882 case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
1883 {
1884 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
1885
1886 // Necessary for an Intel TexImage workaround.
1887 if (!framebuffer)
1888 continue;
1889
1890 FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
1891 bindFramebuffer(GL_READ_FRAMEBUFFER, framebufferGL->getFramebufferID());
1892 break;
1893 }
1894 case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
1895 {
1896 gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
1897
1898 // Necessary for an Intel TexImage workaround.
1899 if (!framebuffer)
1900 continue;
1901
1902 FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
1903 bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferGL->getFramebufferID());
1904
1905 const gl::Program *program = state.getProgram();
1906 if (program)
1907 {
1908 updateMultiviewBaseViewLayerIndexUniform(program, framebufferGL->getState());
1909 }
1910
1911 // Changing the draw framebuffer binding sometimes requires resetting srgb blending.
1912 if (mFunctions->standard == STANDARD_GL_DESKTOP)
1913 {
1914 iter.setLaterBit(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
1915 }
1916
1917 // If the framebuffer is emulating RGB on top of RGBA, the color mask has to be
1918 // updated
1919 iter.setLaterBit(gl::State::DIRTY_BIT_COLOR_MASK);
1920 break;
1921 }
1922 case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
1923 // TODO(jmadill): implement this
1924 break;
1925 case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
1926 {
1927 const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(state.getVertexArray());
1928 bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
1929
1930 propagateProgramToVAO(state.getProgram(),
1931 GetImplAs<VertexArrayGL>(state.getVertexArray()));
1932 break;
1933 }
1934 case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
1935 updateDrawIndirectBufferBinding(context);
1936 break;
1937 case gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
1938 updateDispatchIndirectBufferBinding(context);
1939 break;
1940 case gl::State::DIRTY_BIT_PROGRAM_BINDING:
1941 {
1942 gl::Program *program = state.getProgram();
1943 if (program != nullptr)
1944 {
1945 useProgram(GetImplAs<ProgramGL>(program)->getProgramID());
1946 }
1947 break;
1948 }
1949 case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
1950 {
1951 const gl::Program *program = state.getProgram();
1952 const gl::ProgramExecutable *executable = state.getProgramExecutable();
1953
1954 if (program && executable)
1955 {
1956 iter.setLaterBit(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
1957
1958 if (executable->getActiveImagesMask().any())
1959 {
1960 iter.setLaterBit(gl::State::DIRTY_BIT_IMAGE_BINDINGS);
1961 }
1962
1963 if (program->getActiveShaderStorageBlockCount() > 0)
1964 {
1965 iter.setLaterBit(gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
1966 }
1967
1968 if (program->getActiveUniformBlockCount() > 0)
1969 {
1970 iter.setLaterBit(gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
1971 }
1972
1973 if (program->getActiveAtomicCounterBufferCount() > 0)
1974 {
1975 iter.setLaterBit(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
1976 }
1977
1978 if (mIsMultiviewEnabled && program->usesMultiview())
1979 {
1980 updateMultiviewBaseViewLayerIndexUniform(
1981 program, state.getDrawFramebuffer()->getImplementation()->getState());
1982 }
1983 }
1984
1985 if (!program ||
1986 !program->getExecutable().hasLinkedShaderStage(gl::ShaderType::Compute))
1987 {
1988 propagateProgramToVAO(program,
1989 GetImplAs<VertexArrayGL>(state.getVertexArray()));
1990 }
1991 break;
1992 }
1993 case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
1994 updateProgramTextureBindings(context);
1995 break;
1996 case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
1997 syncSamplersState(context);
1998 break;
1999 case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
2000 updateProgramImageBindings(context);
2001 break;
2002 case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
2003 syncTransformFeedbackState(context);
2004 break;
2005 case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
2006 updateProgramStorageBufferBindings(context);
2007 break;
2008 case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
2009 updateProgramUniformBufferBindings(context);
2010 break;
2011 case gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
2012 updateProgramAtomicCounterBufferBindings(context);
2013 break;
2014 case gl::State::DIRTY_BIT_MULTISAMPLING:
2015 setMultisamplingStateEnabled(state.isMultisamplingEnabled());
2016 break;
2017 case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
2018 setSampleAlphaToOneStateEnabled(state.isSampleAlphaToOneEnabled());
2019 break;
2020 case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
2021 setCoverageModulation(state.getCoverageModulation());
2022 break;
2023 case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB:
2024 setFramebufferSRGBEnabledForFramebuffer(
2025 context, state.getFramebufferSRGB(),
2026 GetImplAs<FramebufferGL>(state.getDrawFramebuffer()));
2027 break;
2028 case gl::State::DIRTY_BIT_SAMPLE_MASK_ENABLED:
2029 setSampleMaskEnabled(state.isSampleMaskEnabled());
2030 break;
2031 case gl::State::DIRTY_BIT_SAMPLE_MASK:
2032 {
2033 for (GLuint maskNumber = 0; maskNumber < state.getMaxSampleMaskWords();
2034 ++maskNumber)
2035 {
2036 setSampleMaski(maskNumber, state.getSampleMaskWord(maskNumber));
2037 }
2038 break;
2039 }
2040 case gl::State::DIRTY_BIT_CURRENT_VALUES:
2041 {
2042 gl::AttributesMask combinedMask =
2043 (state.getAndResetDirtyCurrentValues() | mLocalDirtyCurrentValues);
2044 mLocalDirtyCurrentValues.reset();
2045
2046 for (auto attribIndex : combinedMask)
2047 {
2048 setAttributeCurrentData(attribIndex,
2049 state.getVertexAttribCurrentValue(attribIndex));
2050 }
2051 break;
2052 }
2053 case gl::State::DIRTY_BIT_PROVOKING_VERTEX:
2054 setProvokingVertex(ToGLenum(state.getProvokingVertex()));
2055 break;
2056 case gl::State::DIRTY_BIT_EXTENDED:
2057 // Handling clip distance enabled flags:
2058 setClipDistancesEnable(state.getEnabledClipDistances());
2059 // TODO(jmadill): handle mipmap generation hint
2060 // TODO(jmadill): handle shader derivative hint
2061 break;
2062 default:
2063 UNREACHABLE();
2064 break;
2065 }
2066 }
2067
2068 mLocalDirtyBits &= ~(bitMask);
2069
2070 return angle::Result::Continue;
2071 }
2072
setFramebufferSRGBEnabled(const gl::Context * context,bool enabled)2073 void StateManagerGL::setFramebufferSRGBEnabled(const gl::Context *context, bool enabled)
2074 {
2075 if (!mFramebufferSRGBAvailable)
2076 {
2077 return;
2078 }
2079
2080 if (mFramebufferSRGBEnabled != enabled)
2081 {
2082 mFramebufferSRGBEnabled = enabled;
2083 if (mFramebufferSRGBEnabled)
2084 {
2085 mFunctions->enable(GL_FRAMEBUFFER_SRGB);
2086 }
2087 else
2088 {
2089 mFunctions->disable(GL_FRAMEBUFFER_SRGB);
2090 }
2091 mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
2092 }
2093 }
2094
setFramebufferSRGBEnabledForFramebuffer(const gl::Context * context,bool enabled,const FramebufferGL * framebuffer)2095 void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context,
2096 bool enabled,
2097 const FramebufferGL *framebuffer)
2098 {
2099 if (mFunctions->standard == STANDARD_GL_DESKTOP && framebuffer->isDefault())
2100 {
2101 // Obey the framebuffer sRGB state for blending on all framebuffers except the default
2102 // framebuffer on Desktop OpenGL.
2103 // When SRGB blending is enabled, only SRGB capable formats will use it but the default
2104 // framebuffer will always use it if it is enabled.
2105 // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
2106 setFramebufferSRGBEnabled(context, false);
2107 }
2108 else
2109 {
2110 setFramebufferSRGBEnabled(context, enabled);
2111 }
2112 }
2113
setColorMaskForFramebuffer(const gl::BlendStateExt & blendStateExt,const bool disableAlpha)2114 void StateManagerGL::setColorMaskForFramebuffer(const gl::BlendStateExt &blendStateExt,
2115 const bool disableAlpha)
2116 {
2117 bool r, g, b, a;
2118
2119 // Given that disableAlpha can be true only on macOS backbuffers and color mask is re-synced on
2120 // bound draw framebuffer change, switch all draw buffers color masks to avoid special case
2121 // later.
2122 if (!mIndependentBlendStates || disableAlpha)
2123 {
2124 blendStateExt.getColorMaskIndexed(0, &r, &g, &b, &a);
2125 setColorMask(r, g, b, disableAlpha ? false : a);
2126 return;
2127 }
2128
2129 // Check if the current mask already matches the new state
2130 if (mBlendStateExt.mColorMask == blendStateExt.mColorMask)
2131 {
2132 return;
2133 }
2134
2135 // Get DrawBufferMask of buffers with different color masks
2136 gl::DrawBufferMask diffMask = mBlendStateExt.compareColorMask(blendStateExt.mColorMask);
2137 size_t diffCount = diffMask.count();
2138
2139 // Check if setting all buffers to the same value reduces the number of subsequent indexed
2140 // commands. Implicitly handles the case when the new mask is the same for all buffers.
2141 // For instance, let's say that previously synced mask is ccccff00 and the new state is
2142 // ffeeeeee. Instead of calling colorMaski 8 times, ANGLE can set all buffers to `e` and then
2143 // use colorMaski only twice. On the other hand, if the new state is cceeee00, a non-indexed
2144 // call will increase the total number of GL commands.
2145 if (diffCount > 1)
2146 {
2147 bool found = false;
2148 gl::BlendStateExt::ColorMaskStorage::Type commonColorMask = 0;
2149 for (size_t i = 0; i < mBlendStateExt.mMaxDrawBuffers - 1; i++)
2150 {
2151 const gl::BlendStateExt::ColorMaskStorage::Type tempCommonColorMask =
2152 blendStateExt.expandColorMaskIndexed(i);
2153 const gl::DrawBufferMask tempDiffMask =
2154 blendStateExt.compareColorMask(tempCommonColorMask);
2155 const size_t tempDiffCount = tempDiffMask.count();
2156 if (tempDiffCount < diffCount)
2157 {
2158 found = true;
2159 diffMask = tempDiffMask;
2160 diffCount = tempDiffCount;
2161 commonColorMask = tempCommonColorMask;
2162 if (tempDiffCount == 0)
2163 {
2164 break; // the new mask is the same for all buffers
2165 }
2166 }
2167 }
2168 if (found)
2169 {
2170 gl::BlendStateExt::UnpackColorMask(commonColorMask, &r, &g, &b, &a);
2171 mFunctions->colorMask(r, g, b, a);
2172 }
2173 }
2174
2175 for (size_t drawBufferIndex : diffMask)
2176 {
2177 blendStateExt.getColorMaskIndexed(drawBufferIndex, &r, &g, &b, &a);
2178 mFunctions->colorMaski(static_cast<GLuint>(drawBufferIndex), r, g, b, a);
2179 }
2180
2181 mBlendStateExt.mColorMask = blendStateExt.mColorMask;
2182 mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
2183 }
2184
setDitherEnabled(bool enabled)2185 void StateManagerGL::setDitherEnabled(bool enabled)
2186 {
2187 if (mDitherEnabled != enabled)
2188 {
2189 mDitherEnabled = enabled;
2190 if (mDitherEnabled)
2191 {
2192 mFunctions->enable(GL_DITHER);
2193 }
2194 else
2195 {
2196 mFunctions->disable(GL_DITHER);
2197 }
2198 }
2199 }
2200
setMultisamplingStateEnabled(bool enabled)2201 void StateManagerGL::setMultisamplingStateEnabled(bool enabled)
2202 {
2203 if (mMultisamplingEnabled != enabled)
2204 {
2205 mMultisamplingEnabled = enabled;
2206 if (mMultisamplingEnabled)
2207 {
2208 mFunctions->enable(GL_MULTISAMPLE_EXT);
2209 }
2210 else
2211 {
2212 mFunctions->disable(GL_MULTISAMPLE_EXT);
2213 }
2214 mLocalDirtyBits.set(gl::State::DIRTY_BIT_MULTISAMPLING);
2215 }
2216 }
2217
setSampleAlphaToOneStateEnabled(bool enabled)2218 void StateManagerGL::setSampleAlphaToOneStateEnabled(bool enabled)
2219 {
2220 if (mSampleAlphaToOneEnabled != enabled)
2221 {
2222 mSampleAlphaToOneEnabled = enabled;
2223 if (mSampleAlphaToOneEnabled)
2224 {
2225 mFunctions->enable(GL_SAMPLE_ALPHA_TO_ONE);
2226 }
2227 else
2228 {
2229 mFunctions->disable(GL_SAMPLE_ALPHA_TO_ONE);
2230 }
2231 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
2232 }
2233 }
2234
setCoverageModulation(GLenum components)2235 void StateManagerGL::setCoverageModulation(GLenum components)
2236 {
2237 if (mCoverageModulation != components)
2238 {
2239 mCoverageModulation = components;
2240 mFunctions->coverageModulationNV(components);
2241
2242 mLocalDirtyBits.set(gl::State::DIRTY_BIT_COVERAGE_MODULATION);
2243 }
2244 }
2245
setProvokingVertex(GLenum mode)2246 void StateManagerGL::setProvokingVertex(GLenum mode)
2247 {
2248 if (mode != mProvokingVertex)
2249 {
2250 mFunctions->provokingVertex(mode);
2251 mProvokingVertex = mode;
2252
2253 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PROVOKING_VERTEX);
2254 }
2255 }
2256
setClipDistancesEnable(const gl::State::ClipDistanceEnableBits & enables)2257 void StateManagerGL::setClipDistancesEnable(const gl::State::ClipDistanceEnableBits &enables)
2258 {
2259 if (enables == mEnabledClipDistances)
2260 {
2261 return;
2262 }
2263 ASSERT(mMaxClipDistances <= gl::IMPLEMENTATION_MAX_CLIP_DISTANCES);
2264
2265 gl::State::ClipDistanceEnableBits diff = enables ^ mEnabledClipDistances;
2266 for (size_t i : diff)
2267 {
2268 if (enables.test(i))
2269 {
2270 mFunctions->enable(GL_CLIP_DISTANCE0_EXT + static_cast<uint32_t>(i));
2271 }
2272 else
2273 {
2274 mFunctions->disable(GL_CLIP_DISTANCE0_EXT + static_cast<uint32_t>(i));
2275 }
2276 }
2277
2278 mEnabledClipDistances = enables;
2279 mLocalDirtyBits.set(gl::State::DIRTY_BIT_EXTENDED);
2280 }
2281
setTextureCubemapSeamlessEnabled(bool enabled)2282 void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
2283 {
2284 // TODO(jmadill): Also check for seamless extension.
2285 if (!mFunctions->isAtLeastGL(gl::Version(3, 2)))
2286 {
2287 return;
2288 }
2289
2290 if (mTextureCubemapSeamlessEnabled != enabled)
2291 {
2292 mTextureCubemapSeamlessEnabled = enabled;
2293 if (mTextureCubemapSeamlessEnabled)
2294 {
2295 mFunctions->enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
2296 }
2297 else
2298 {
2299 mFunctions->disable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
2300 }
2301 }
2302 }
2303
propagateProgramToVAO(const gl::Program * program,VertexArrayGL * vao)2304 void StateManagerGL::propagateProgramToVAO(const gl::Program *program, VertexArrayGL *vao)
2305 {
2306 if (vao == nullptr)
2307 {
2308 return;
2309 }
2310
2311 // Number of views:
2312 if (mIsMultiviewEnabled)
2313 {
2314 int programNumViews = 1;
2315 if (program && program->usesMultiview())
2316 {
2317 programNumViews = program->getNumViews();
2318 }
2319 vao->applyNumViewsToDivisor(programNumViews);
2320 }
2321
2322 // Attribute enabled mask:
2323 if (program)
2324 {
2325 vao->applyActiveAttribLocationsMask(
2326 program->getExecutable().getActiveAttribLocationsMask());
2327 }
2328 }
2329
updateMultiviewBaseViewLayerIndexUniformImpl(const gl::Program * program,const gl::FramebufferState & drawFramebufferState) const2330 void StateManagerGL::updateMultiviewBaseViewLayerIndexUniformImpl(
2331 const gl::Program *program,
2332 const gl::FramebufferState &drawFramebufferState) const
2333 {
2334 ASSERT(mIsMultiviewEnabled && program && program->usesMultiview());
2335 const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
2336 if (drawFramebufferState.isMultiview())
2337 {
2338 programGL->enableLayeredRenderingPath(drawFramebufferState.getBaseViewIndex());
2339 }
2340 }
2341
syncSamplersState(const gl::Context * context)2342 void StateManagerGL::syncSamplersState(const gl::Context *context)
2343 {
2344 const gl::SamplerBindingVector &samplers = context->getState().getSamplers();
2345
2346 // This could be optimized by using a separate binding dirty bit per sampler.
2347 for (size_t samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex)
2348 {
2349 const gl::Sampler *sampler = samplers[samplerIndex].get();
2350 if (sampler != nullptr)
2351 {
2352 SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler);
2353 bindSampler(samplerIndex, samplerGL->getSamplerID());
2354 }
2355 else
2356 {
2357 bindSampler(samplerIndex, 0);
2358 }
2359 }
2360 }
2361
syncTransformFeedbackState(const gl::Context * context)2362 void StateManagerGL::syncTransformFeedbackState(const gl::Context *context)
2363 {
2364 // Set the current transform feedback state
2365 gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
2366 if (transformFeedback)
2367 {
2368 TransformFeedbackGL *transformFeedbackGL =
2369 GetImplAs<TransformFeedbackGL>(transformFeedback);
2370 bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID());
2371 transformFeedbackGL->syncActiveState(context, transformFeedback->isActive(),
2372 transformFeedback->getPrimitiveMode());
2373 transformFeedbackGL->syncPausedState(transformFeedback->isPaused());
2374 mCurrentTransformFeedback = transformFeedbackGL;
2375 }
2376 else
2377 {
2378 bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
2379 mCurrentTransformFeedback = nullptr;
2380 }
2381 }
2382
validateState() const2383 void StateManagerGL::validateState() const
2384 {
2385 // Current program
2386 ValidateStateHelper(mFunctions, mProgram, GL_CURRENT_PROGRAM, "mProgram", "GL_CURRENT_PROGRAM");
2387
2388 // Buffers
2389 for (gl::BufferBinding bindingType : angle::AllEnums<gl::BufferBinding>())
2390 {
2391 // These binding types need compute support to be queried
2392 if (bindingType == gl::BufferBinding::AtomicCounter ||
2393 bindingType == gl::BufferBinding::DispatchIndirect ||
2394 bindingType == gl::BufferBinding::ShaderStorage)
2395 {
2396 if (!nativegl::SupportsCompute(mFunctions))
2397 {
2398 continue;
2399 }
2400 }
2401
2402 // Transform feedback buffer bindings are tracked in TransformFeedbackGL
2403 if (bindingType == gl::BufferBinding::TransformFeedback)
2404 {
2405 continue;
2406 }
2407
2408 GLenum bindingTypeGL = nativegl::GetBufferBindingQuery(bindingType);
2409 std::string localName = "mBuffers[" + ToString(bindingType) + "]";
2410 ValidateStateHelper(mFunctions, mBuffers[bindingType], bindingTypeGL, localName.c_str(),
2411 nativegl::GetBufferBindingString(bindingType).c_str());
2412 }
2413
2414 // Vertex array object
2415 ValidateStateHelper(mFunctions, mVAO, GL_VERTEX_ARRAY_BINDING, "mVAO",
2416 "GL_VERTEX_ARRAY_BINDING");
2417 }
2418
2419 } // namespace rx
2420