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
VertexArrayStateGL(size_t maxAttribs,size_t maxBindings)59 VertexArrayStateGL::VertexArrayStateGL(size_t maxAttribs, size_t maxBindings)
60 : attributes(std::min<size_t>(maxAttribs, gl::MAX_VERTEX_ATTRIBS)),
61 bindings(std::min<size_t>(maxBindings, gl::MAX_VERTEX_ATTRIBS))
62 {
63 // Set the cached vertex attribute array and vertex attribute binding array size
64 for (GLuint i = 0; i < attributes.size(); i++)
65 {
66 attributes[i].bindingIndex = i;
67 }
68 }
69
IndexedBufferBinding()70 StateManagerGL::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0) {}
71
StateManagerGL(const FunctionsGL * functions,const gl::Caps & rendererCaps,const gl::Extensions & extensions,const angle::FeaturesGL & features)72 StateManagerGL::StateManagerGL(const FunctionsGL *functions,
73 const gl::Caps &rendererCaps,
74 const gl::Extensions &extensions,
75 const angle::FeaturesGL &features)
76 : mFunctions(functions),
77 mFeatures(features),
78 mProgram(0),
79 mVAO(0),
80 mVertexAttribCurrentValues(rendererCaps.maxVertexAttributes),
81 mDefaultVAOState(rendererCaps.maxVertexAttributes, rendererCaps.maxVertexAttribBindings),
82 mVAOState(&mDefaultVAOState),
83 mBuffers(),
84 mIndexedBuffers(),
85 mTextureUnitIndex(0),
86 mTextures{},
87 mSamplers{},
88 mImages(rendererCaps.maxImageUnits, ImageUnitBinding()),
89 mTransformFeedback(0),
90 mCurrentTransformFeedback(nullptr),
91 mQueries(),
92 mPrevDrawContext({0}),
93 mUnpackAlignment(4),
94 mUnpackRowLength(0),
95 mUnpackSkipRows(0),
96 mUnpackSkipPixels(0),
97 mUnpackImageHeight(0),
98 mUnpackSkipImages(0),
99 mPackAlignment(4),
100 mPackRowLength(0),
101 mPackSkipRows(0),
102 mPackSkipPixels(0),
103 mFramebuffers(angle::FramebufferBindingSingletonMax, 0),
104 mRenderbuffer(0),
105 mScissorTestEnabled(false),
106 mScissor(0, 0, 0, 0),
107 mViewport(0, 0, 0, 0),
108 mNear(0.0f),
109 mFar(1.0f),
110 mBlendColor(0, 0, 0, 0),
111 mBlendStateExt(rendererCaps.maxDrawBuffers),
112 mIndependentBlendStates(extensions.drawBuffersIndexedAny()),
113 mSampleAlphaToCoverageEnabled(false),
114 mSampleCoverageEnabled(false),
115 mSampleCoverageValue(1.0f),
116 mSampleCoverageInvert(false),
117 mSampleMaskEnabled(false),
118 mDepthTestEnabled(false),
119 mDepthFunc(GL_LESS),
120 mDepthMask(true),
121 mStencilTestEnabled(false),
122 mStencilFrontFunc(GL_ALWAYS),
123 mStencilFrontRef(0),
124 mStencilFrontValueMask(static_cast<GLuint>(-1)),
125 mStencilFrontStencilFailOp(GL_KEEP),
126 mStencilFrontStencilPassDepthFailOp(GL_KEEP),
127 mStencilFrontStencilPassDepthPassOp(GL_KEEP),
128 mStencilFrontWritemask(static_cast<GLuint>(-1)),
129 mStencilBackFunc(GL_ALWAYS),
130 mStencilBackRef(0),
131 mStencilBackValueMask(static_cast<GLuint>(-1)),
132 mStencilBackStencilFailOp(GL_KEEP),
133 mStencilBackStencilPassDepthFailOp(GL_KEEP),
134 mStencilBackStencilPassDepthPassOp(GL_KEEP),
135 mStencilBackWritemask(static_cast<GLuint>(-1)),
136 mCullFaceEnabled(false),
137 mCullFace(gl::CullFaceMode::Back),
138 mFrontFace(GL_CCW),
139 mPolygonOffsetFillEnabled(false),
140 mPolygonOffsetFactor(0.0f),
141 mPolygonOffsetUnits(0.0f),
142 mRasterizerDiscardEnabled(false),
143 mLineWidth(1.0f),
144 mPrimitiveRestartEnabled(false),
145 mPrimitiveRestartIndex(0),
146 mClearColor(0.0f, 0.0f, 0.0f, 0.0f),
147 mClearDepth(1.0f),
148 mClearStencil(0),
149 mFramebufferSRGBAvailable(extensions.sRGBWriteControlEXT),
150 mFramebufferSRGBEnabled(false),
151 mHasSeparateFramebufferBindings(mFunctions->isAtLeastGL(gl::Version(3, 0)) ||
152 mFunctions->isAtLeastGLES(gl::Version(3, 0))),
153 mDitherEnabled(true),
154 mTextureCubemapSeamlessEnabled(false),
155 mMultisamplingEnabled(true),
156 mSampleAlphaToOneEnabled(false),
157 mCoverageModulation(GL_NONE),
158 mIsMultiviewEnabled(extensions.multiviewOVR || extensions.multiview2OVR),
159 mProvokingVertex(GL_LAST_VERTEX_CONVENTION),
160 mMaxClipDistances(rendererCaps.maxClipDistances),
161 mLocalDirtyBits()
162 {
163 ASSERT(mFunctions);
164 ASSERT(rendererCaps.maxViews >= 1u);
165
166 mIndexedBuffers[gl::BufferBinding::Uniform].resize(rendererCaps.maxUniformBufferBindings);
167 mIndexedBuffers[gl::BufferBinding::AtomicCounter].resize(
168 rendererCaps.maxAtomicCounterBufferBindings);
169 mIndexedBuffers[gl::BufferBinding::ShaderStorage].resize(
170 rendererCaps.maxShaderStorageBufferBindings);
171
172 mSampleMaskValues.fill(~GLbitfield(0));
173
174 mQueries.fill(nullptr);
175 mTemporaryPausedQueries.fill(nullptr);
176
177 // Initialize point sprite state for desktop GL
178 if (mFunctions->standard == STANDARD_GL_DESKTOP)
179 {
180 mFunctions->enable(GL_PROGRAM_POINT_SIZE);
181
182 // GL_POINT_SPRITE was deprecated in the core profile. Point rasterization is always
183 // performed
184 // as though POINT_SPRITE were enabled.
185 if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) == 0)
186 {
187 mFunctions->enable(GL_POINT_SPRITE);
188 }
189 }
190
191 if (features.emulatePrimitiveRestartFixedIndex.enabled)
192 {
193 // There is no consistent default value for primitive restart index. Set it to UINT -1.
194 constexpr GLuint primitiveRestartIndex = gl::GetPrimitiveRestartIndexFromType<GLuint>();
195 mFunctions->primitiveRestartIndex(primitiveRestartIndex);
196 mPrimitiveRestartIndex = primitiveRestartIndex;
197 }
198
199 // It's possible we've enabled the emulated VAO feature for testing but we're on a core profile.
200 // Use a generated VAO as the default VAO so we can still test.
201 if (features.syncVertexArraysToDefault.enabled &&
202 !nativegl::CanUseDefaultVertexArrayObject(mFunctions))
203 {
204 ASSERT(nativegl::SupportsVertexArrayObjects(mFunctions));
205 mFunctions->genVertexArrays(1, &mDefaultVAO);
206 mFunctions->bindVertexArray(mDefaultVAO);
207 mVAO = mDefaultVAO;
208 }
209 }
210
~StateManagerGL()211 StateManagerGL::~StateManagerGL()
212 {
213 if (mDefaultVAO != 0)
214 {
215 mFunctions->deleteVertexArrays(1, &mDefaultVAO);
216 }
217 }
218
deleteProgram(GLuint program)219 void StateManagerGL::deleteProgram(GLuint program)
220 {
221 if (program != 0)
222 {
223 if (mProgram == program)
224 {
225 useProgram(0);
226 }
227
228 mFunctions->deleteProgram(program);
229 }
230 }
231
deleteVertexArray(GLuint vao)232 void StateManagerGL::deleteVertexArray(GLuint vao)
233 {
234 if (vao != 0)
235 {
236 if (mVAO == vao)
237 {
238 bindVertexArray(0, &mDefaultVAOState);
239 }
240 mFunctions->deleteVertexArrays(1, &vao);
241 }
242 }
243
deleteTexture(GLuint texture)244 void StateManagerGL::deleteTexture(GLuint texture)
245 {
246 if (texture != 0)
247 {
248 for (gl::TextureType type : angle::AllEnums<gl::TextureType>())
249 {
250 const auto &textureVector = mTextures[type];
251 for (size_t textureUnitIndex = 0; textureUnitIndex < textureVector.size();
252 textureUnitIndex++)
253 {
254 if (textureVector[textureUnitIndex] == texture)
255 {
256 activeTexture(textureUnitIndex);
257 bindTexture(type, 0);
258 }
259 }
260 }
261
262 for (size_t imageUnitIndex = 0; imageUnitIndex < mImages.size(); imageUnitIndex++)
263 {
264 if (mImages[imageUnitIndex].texture == texture)
265 {
266 bindImageTexture(imageUnitIndex, 0, 0, false, 0, GL_READ_ONLY, GL_R32UI);
267 }
268 }
269
270 mFunctions->deleteTextures(1, &texture);
271 }
272 }
273
deleteSampler(GLuint sampler)274 void StateManagerGL::deleteSampler(GLuint sampler)
275 {
276 if (sampler != 0)
277 {
278 for (size_t unit = 0; unit < mSamplers.size(); unit++)
279 {
280 if (mSamplers[unit] == sampler)
281 {
282 bindSampler(unit, 0);
283 }
284 }
285
286 mFunctions->deleteSamplers(1, &sampler);
287 }
288 }
289
deleteBuffer(GLuint buffer)290 void StateManagerGL::deleteBuffer(GLuint buffer)
291 {
292 if (buffer == 0)
293 {
294 return;
295 }
296
297 for (auto target : angle::AllEnums<gl::BufferBinding>())
298 {
299 if (mBuffers[target] == buffer)
300 {
301 bindBuffer(target, 0);
302 }
303
304 auto &indexedTarget = mIndexedBuffers[target];
305 for (size_t bindIndex = 0; bindIndex < indexedTarget.size(); ++bindIndex)
306 {
307 if (indexedTarget[bindIndex].buffer == buffer)
308 {
309 bindBufferBase(target, bindIndex, 0);
310 }
311 }
312 }
313
314 if (mVAOState)
315 {
316 if (mVAOState->elementArrayBuffer == buffer)
317 {
318 mVAOState->elementArrayBuffer = 0;
319 }
320
321 for (VertexBindingGL &binding : mVAOState->bindings)
322 {
323 if (binding.buffer == buffer)
324 {
325 binding.buffer = 0;
326 }
327 }
328 }
329
330 mFunctions->deleteBuffers(1, &buffer);
331 }
332
deleteFramebuffer(GLuint fbo)333 void StateManagerGL::deleteFramebuffer(GLuint fbo)
334 {
335 if (fbo != 0)
336 {
337 if (mHasSeparateFramebufferBindings)
338 {
339 for (size_t binding = 0; binding < mFramebuffers.size(); ++binding)
340 {
341 if (mFramebuffers[binding] == fbo)
342 {
343 GLenum enumValue = angle::FramebufferBindingToEnum(
344 static_cast<angle::FramebufferBinding>(binding));
345 bindFramebuffer(enumValue, 0);
346 }
347 }
348 }
349 else
350 {
351 ASSERT(mFramebuffers[angle::FramebufferBindingRead] ==
352 mFramebuffers[angle::FramebufferBindingDraw]);
353 if (mFramebuffers[angle::FramebufferBindingRead] == fbo)
354 {
355 bindFramebuffer(GL_FRAMEBUFFER, 0);
356 }
357 }
358 mFunctions->deleteFramebuffers(1, &fbo);
359 }
360 }
361
deleteRenderbuffer(GLuint rbo)362 void StateManagerGL::deleteRenderbuffer(GLuint rbo)
363 {
364 if (rbo != 0)
365 {
366 if (mRenderbuffer == rbo)
367 {
368 bindRenderbuffer(GL_RENDERBUFFER, 0);
369 }
370
371 mFunctions->deleteRenderbuffers(1, &rbo);
372 }
373 }
374
deleteTransformFeedback(GLuint transformFeedback)375 void StateManagerGL::deleteTransformFeedback(GLuint transformFeedback)
376 {
377 if (transformFeedback != 0)
378 {
379 if (mTransformFeedback == transformFeedback)
380 {
381 bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
382 }
383
384 if (mCurrentTransformFeedback != nullptr &&
385 mCurrentTransformFeedback->getTransformFeedbackID() == transformFeedback)
386 {
387 mCurrentTransformFeedback = nullptr;
388 }
389
390 mFunctions->deleteTransformFeedbacks(1, &transformFeedback);
391 }
392 }
393
useProgram(GLuint program)394 void StateManagerGL::useProgram(GLuint program)
395 {
396 if (mProgram != program)
397 {
398 forceUseProgram(program);
399 }
400 }
401
forceUseProgram(GLuint program)402 void StateManagerGL::forceUseProgram(GLuint program)
403 {
404 mProgram = program;
405 mFunctions->useProgram(mProgram);
406 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PROGRAM_BINDING);
407 }
408
bindVertexArray(GLuint vao,VertexArrayStateGL * vaoState)409 void StateManagerGL::bindVertexArray(GLuint vao, VertexArrayStateGL *vaoState)
410 {
411 ASSERT(vaoState);
412 if (mVAO != vao)
413 {
414 ASSERT(!mFeatures.syncVertexArraysToDefault.enabled);
415
416 mVAO = vao;
417 mVAOState = vaoState;
418 mBuffers[gl::BufferBinding::ElementArray] = vaoState ? vaoState->elementArrayBuffer : 0;
419
420 mFunctions->bindVertexArray(vao);
421
422 mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
423 }
424 }
425
bindBuffer(gl::BufferBinding target,GLuint buffer)426 void StateManagerGL::bindBuffer(gl::BufferBinding target, GLuint buffer)
427 {
428 // GL drivers differ in whether the transform feedback bind point is modified when
429 // glBindTransformFeedback is called. To avoid these behavior differences we shouldn't try to
430 // use it.
431 ASSERT(target != gl::BufferBinding::TransformFeedback);
432 if (mBuffers[target] != buffer)
433 {
434 mBuffers[target] = buffer;
435 mFunctions->bindBuffer(gl::ToGLenum(target), buffer);
436 }
437 }
438
bindBufferBase(gl::BufferBinding target,size_t index,GLuint buffer)439 void StateManagerGL::bindBufferBase(gl::BufferBinding target, size_t index, GLuint buffer)
440 {
441 // Transform feedback buffer bindings are tracked in TransformFeedbackGL
442 ASSERT(target != gl::BufferBinding::TransformFeedback);
443
444 ASSERT(index < mIndexedBuffers[target].size());
445 auto &binding = mIndexedBuffers[target][index];
446 if (binding.buffer != buffer || binding.offset != static_cast<size_t>(-1) ||
447 binding.size != static_cast<size_t>(-1))
448 {
449 binding.buffer = buffer;
450 binding.offset = static_cast<size_t>(-1);
451 binding.size = static_cast<size_t>(-1);
452 mBuffers[target] = buffer;
453 mFunctions->bindBufferBase(gl::ToGLenum(target), static_cast<GLuint>(index), buffer);
454 }
455 }
456
bindBufferRange(gl::BufferBinding target,size_t index,GLuint buffer,size_t offset,size_t size)457 void StateManagerGL::bindBufferRange(gl::BufferBinding target,
458 size_t index,
459 GLuint buffer,
460 size_t offset,
461 size_t size)
462 {
463 // Transform feedback buffer bindings are tracked in TransformFeedbackGL
464 ASSERT(target != gl::BufferBinding::TransformFeedback);
465
466 auto &binding = mIndexedBuffers[target][index];
467 if (binding.buffer != buffer || binding.offset != offset || binding.size != size)
468 {
469 binding.buffer = buffer;
470 binding.offset = offset;
471 binding.size = size;
472 mBuffers[target] = buffer;
473 mFunctions->bindBufferRange(gl::ToGLenum(target), static_cast<GLuint>(index), buffer,
474 offset, size);
475 }
476 }
477
activeTexture(size_t unit)478 void StateManagerGL::activeTexture(size_t unit)
479 {
480 if (mTextureUnitIndex != unit)
481 {
482 mTextureUnitIndex = unit;
483 mFunctions->activeTexture(GL_TEXTURE0 + static_cast<GLenum>(mTextureUnitIndex));
484 }
485 }
486
bindTexture(gl::TextureType type,GLuint texture)487 void StateManagerGL::bindTexture(gl::TextureType type, GLuint texture)
488 {
489 gl::TextureType nativeType = nativegl::GetNativeTextureType(type);
490 if (mTextures[nativeType][mTextureUnitIndex] != texture)
491 {
492 mTextures[nativeType][mTextureUnitIndex] = texture;
493 mFunctions->bindTexture(nativegl::GetTextureBindingTarget(type), texture);
494 mLocalDirtyBits.set(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
495 }
496 }
497
invalidateTexture(gl::TextureType type)498 void StateManagerGL::invalidateTexture(gl::TextureType type)
499 {
500 // Assume the tracked texture binding is incorrect, query the real bound texture from GL.
501 GLint boundTexture = 0;
502 mFunctions->getIntegerv(nativegl::GetTextureBindingQuery(type), &boundTexture);
503 mTextures[type][mTextureUnitIndex] = static_cast<GLuint>(boundTexture);
504 mLocalDirtyBits.set(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
505 }
506
bindSampler(size_t unit,GLuint sampler)507 void StateManagerGL::bindSampler(size_t unit, GLuint sampler)
508 {
509 if (mSamplers[unit] != sampler)
510 {
511 mSamplers[unit] = sampler;
512 mFunctions->bindSampler(static_cast<GLuint>(unit), sampler);
513 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLER_BINDINGS);
514 }
515 }
516
bindImageTexture(size_t unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)517 void StateManagerGL::bindImageTexture(size_t unit,
518 GLuint texture,
519 GLint level,
520 GLboolean layered,
521 GLint layer,
522 GLenum access,
523 GLenum format)
524 {
525 auto &binding = mImages[unit];
526 if (binding.texture != texture || binding.level != level || binding.layered != layered ||
527 binding.layer != layer || binding.access != access || binding.format != format)
528 {
529 binding.texture = texture;
530 binding.level = level;
531 binding.layered = layered;
532 binding.layer = layer;
533 binding.access = access;
534 binding.format = format;
535 mFunctions->bindImageTexture(angle::base::checked_cast<GLuint>(unit), texture, level,
536 layered, layer, access, format);
537 }
538 }
539
setPixelUnpackState(const gl::Context * context,const gl::PixelUnpackState & unpack)540 angle::Result StateManagerGL::setPixelUnpackState(const gl::Context *context,
541 const gl::PixelUnpackState &unpack)
542 {
543 if (mUnpackAlignment != unpack.alignment)
544 {
545 mUnpackAlignment = unpack.alignment;
546 ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_ALIGNMENT, mUnpackAlignment));
547
548 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
549 }
550
551 if (mUnpackRowLength != unpack.rowLength)
552 {
553 mUnpackRowLength = unpack.rowLength;
554 ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_ROW_LENGTH, mUnpackRowLength));
555
556 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
557 }
558
559 if (mUnpackSkipRows != unpack.skipRows)
560 {
561 mUnpackSkipRows = unpack.skipRows;
562 ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_SKIP_ROWS, mUnpackSkipRows));
563
564 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
565 }
566
567 if (mUnpackSkipPixels != unpack.skipPixels)
568 {
569 mUnpackSkipPixels = unpack.skipPixels;
570 ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_SKIP_PIXELS, mUnpackSkipPixels));
571
572 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
573 }
574
575 if (mUnpackImageHeight != unpack.imageHeight)
576 {
577 mUnpackImageHeight = unpack.imageHeight;
578 ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_IMAGE_HEIGHT, mUnpackImageHeight));
579
580 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
581 }
582
583 if (mUnpackSkipImages != unpack.skipImages)
584 {
585 mUnpackSkipImages = unpack.skipImages;
586 ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_SKIP_IMAGES, mUnpackSkipImages));
587
588 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
589 }
590
591 return angle::Result::Continue;
592 }
593
setPixelUnpackBuffer(const gl::Context * context,const gl::Buffer * pixelBuffer)594 angle::Result StateManagerGL::setPixelUnpackBuffer(const gl::Context *context,
595 const gl::Buffer *pixelBuffer)
596 {
597 GLuint bufferID = 0;
598 if (pixelBuffer != nullptr)
599 {
600 bufferID = GetImplAs<BufferGL>(pixelBuffer)->getBufferID();
601 }
602 bindBuffer(gl::BufferBinding::PixelUnpack, bufferID);
603
604 return angle::Result::Continue;
605 }
606
setPixelPackState(const gl::Context * context,const gl::PixelPackState & pack)607 angle::Result StateManagerGL::setPixelPackState(const gl::Context *context,
608 const gl::PixelPackState &pack)
609 {
610 if (mPackAlignment != pack.alignment)
611 {
612 mPackAlignment = pack.alignment;
613 ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_PACK_ALIGNMENT, mPackAlignment));
614
615 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
616 }
617
618 if (mPackRowLength != pack.rowLength)
619 {
620 mPackRowLength = pack.rowLength;
621 ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_PACK_ROW_LENGTH, mPackRowLength));
622
623 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
624 }
625
626 if (mPackSkipRows != pack.skipRows)
627 {
628 mPackSkipRows = pack.skipRows;
629 ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_PACK_SKIP_ROWS, mPackSkipRows));
630
631 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
632 }
633
634 if (mPackSkipPixels != pack.skipPixels)
635 {
636 mPackSkipPixels = pack.skipPixels;
637 ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_PACK_SKIP_PIXELS, mPackSkipPixels));
638
639 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
640 }
641
642 return angle::Result::Continue;
643 }
644
setPixelPackBuffer(const gl::Context * context,const gl::Buffer * pixelBuffer)645 angle::Result StateManagerGL::setPixelPackBuffer(const gl::Context *context,
646 const gl::Buffer *pixelBuffer)
647 {
648 GLuint bufferID = 0;
649 if (pixelBuffer != nullptr)
650 {
651 bufferID = GetImplAs<BufferGL>(pixelBuffer)->getBufferID();
652 }
653 bindBuffer(gl::BufferBinding::PixelPack, bufferID);
654
655 return angle::Result::Continue;
656 }
657
bindFramebuffer(GLenum type,GLuint framebuffer)658 void StateManagerGL::bindFramebuffer(GLenum type, GLuint framebuffer)
659 {
660 bool framebufferChanged = false;
661 switch (type)
662 {
663 case GL_FRAMEBUFFER:
664 if (mFramebuffers[angle::FramebufferBindingRead] != framebuffer ||
665 mFramebuffers[angle::FramebufferBindingDraw] != framebuffer)
666 {
667 mFramebuffers[angle::FramebufferBindingRead] = framebuffer;
668 mFramebuffers[angle::FramebufferBindingDraw] = framebuffer;
669 mFunctions->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
670
671 mLocalDirtyBits.set(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
672 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
673
674 framebufferChanged = true;
675 }
676 break;
677
678 case GL_READ_FRAMEBUFFER:
679 ASSERT(mHasSeparateFramebufferBindings);
680 if (mFramebuffers[angle::FramebufferBindingRead] != framebuffer)
681 {
682 mFramebuffers[angle::FramebufferBindingRead] = framebuffer;
683 mFunctions->bindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
684
685 mLocalDirtyBits.set(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
686
687 framebufferChanged = true;
688 }
689 break;
690
691 case GL_DRAW_FRAMEBUFFER:
692 ASSERT(mHasSeparateFramebufferBindings);
693 if (mFramebuffers[angle::FramebufferBindingDraw] != framebuffer)
694 {
695 mFramebuffers[angle::FramebufferBindingDraw] = framebuffer;
696 mFunctions->bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
697
698 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
699
700 framebufferChanged = true;
701 }
702 break;
703
704 default:
705 UNREACHABLE();
706 break;
707 }
708
709 if (framebufferChanged && mFeatures.flushOnFramebufferChange.enabled)
710 {
711 mFunctions->flush();
712 }
713 }
714
bindRenderbuffer(GLenum type,GLuint renderbuffer)715 void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer)
716 {
717 ASSERT(type == GL_RENDERBUFFER);
718 if (mRenderbuffer != renderbuffer)
719 {
720 mRenderbuffer = renderbuffer;
721 mFunctions->bindRenderbuffer(type, mRenderbuffer);
722 }
723 }
724
bindTransformFeedback(GLenum type,GLuint transformFeedback)725 void StateManagerGL::bindTransformFeedback(GLenum type, GLuint transformFeedback)
726 {
727 ASSERT(type == GL_TRANSFORM_FEEDBACK);
728 if (mTransformFeedback != transformFeedback)
729 {
730 // Pause the current transform feedback if one is active.
731 // To handle virtualized contexts, StateManagerGL needs to be able to bind a new transform
732 // feedback at any time, even if there is one active.
733 if (mCurrentTransformFeedback != nullptr &&
734 mCurrentTransformFeedback->getTransformFeedbackID() != transformFeedback)
735 {
736 mCurrentTransformFeedback->syncPausedState(true);
737 mCurrentTransformFeedback = nullptr;
738 }
739
740 mTransformFeedback = transformFeedback;
741 mFunctions->bindTransformFeedback(type, mTransformFeedback);
742 onTransformFeedbackStateChange();
743 }
744 }
745
onTransformFeedbackStateChange()746 void StateManagerGL::onTransformFeedbackStateChange()
747 {
748 mLocalDirtyBits.set(gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING);
749 }
750
beginQuery(gl::QueryType type,QueryGL * queryObject,GLuint queryId)751 void StateManagerGL::beginQuery(gl::QueryType type, QueryGL *queryObject, GLuint queryId)
752 {
753 // Make sure this is a valid query type and there is no current active query of this type
754 ASSERT(mQueries[type] == nullptr);
755 ASSERT(queryId != 0);
756
757 mQueries[type] = queryObject;
758 mFunctions->beginQuery(ToGLenum(type), queryId);
759 }
760
endQuery(gl::QueryType type,QueryGL * queryObject,GLuint queryId)761 void StateManagerGL::endQuery(gl::QueryType type, QueryGL *queryObject, GLuint queryId)
762 {
763 ASSERT(queryObject != nullptr);
764 ASSERT(mQueries[type] == queryObject);
765 mQueries[type] = nullptr;
766 mFunctions->endQuery(ToGLenum(type));
767 }
768
updateDrawIndirectBufferBinding(const gl::Context * context)769 void StateManagerGL::updateDrawIndirectBufferBinding(const gl::Context *context)
770 {
771 gl::Buffer *drawIndirectBuffer =
772 context->getState().getTargetBuffer(gl::BufferBinding::DrawIndirect);
773 if (drawIndirectBuffer != nullptr)
774 {
775 const BufferGL *bufferGL = GetImplAs<BufferGL>(drawIndirectBuffer);
776 bindBuffer(gl::BufferBinding::DrawIndirect, bufferGL->getBufferID());
777 }
778 }
779
updateDispatchIndirectBufferBinding(const gl::Context * context)780 void StateManagerGL::updateDispatchIndirectBufferBinding(const gl::Context *context)
781 {
782 gl::Buffer *dispatchIndirectBuffer =
783 context->getState().getTargetBuffer(gl::BufferBinding::DispatchIndirect);
784 if (dispatchIndirectBuffer != nullptr)
785 {
786 const BufferGL *bufferGL = GetImplAs<BufferGL>(dispatchIndirectBuffer);
787 bindBuffer(gl::BufferBinding::DispatchIndirect, bufferGL->getBufferID());
788 }
789 }
790
pauseTransformFeedback()791 void StateManagerGL::pauseTransformFeedback()
792 {
793 if (mCurrentTransformFeedback != nullptr)
794 {
795 mCurrentTransformFeedback->syncPausedState(true);
796 onTransformFeedbackStateChange();
797 }
798 }
799
pauseAllQueries(const gl::Context * context)800 angle::Result StateManagerGL::pauseAllQueries(const gl::Context *context)
801 {
802 for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
803 {
804 QueryGL *previousQuery = mQueries[type];
805
806 if (previousQuery != nullptr)
807 {
808 ANGLE_TRY(previousQuery->pause(context));
809 mTemporaryPausedQueries[type] = previousQuery;
810 mQueries[type] = nullptr;
811 }
812 }
813
814 return angle::Result::Continue;
815 }
816
pauseQuery(const gl::Context * context,gl::QueryType type)817 angle::Result StateManagerGL::pauseQuery(const gl::Context *context, gl::QueryType type)
818 {
819 QueryGL *previousQuery = mQueries[type];
820
821 if (previousQuery)
822 {
823 ANGLE_TRY(previousQuery->pause(context));
824 mTemporaryPausedQueries[type] = previousQuery;
825 mQueries[type] = nullptr;
826 }
827
828 return angle::Result::Continue;
829 }
830
resumeAllQueries(const gl::Context * context)831 angle::Result StateManagerGL::resumeAllQueries(const gl::Context *context)
832 {
833 for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
834 {
835 QueryGL *pausedQuery = mTemporaryPausedQueries[type];
836
837 if (pausedQuery != nullptr)
838 {
839 ASSERT(mQueries[type] == nullptr);
840 ANGLE_TRY(pausedQuery->resume(context));
841 mTemporaryPausedQueries[type] = nullptr;
842 }
843 }
844
845 return angle::Result::Continue;
846 }
847
resumeQuery(const gl::Context * context,gl::QueryType type)848 angle::Result StateManagerGL::resumeQuery(const gl::Context *context, gl::QueryType type)
849 {
850 QueryGL *pausedQuery = mTemporaryPausedQueries[type];
851
852 if (pausedQuery != nullptr)
853 {
854 ANGLE_TRY(pausedQuery->resume(context));
855 mTemporaryPausedQueries[type] = nullptr;
856 }
857
858 return angle::Result::Continue;
859 }
860
onMakeCurrent(const gl::Context * context)861 angle::Result StateManagerGL::onMakeCurrent(const gl::Context *context)
862 {
863 const gl::State &glState = context->getState();
864
865 #if defined(ANGLE_ENABLE_ASSERTS)
866 // Temporarily pausing queries during context switch is not supported
867 for (QueryGL *pausedQuery : mTemporaryPausedQueries)
868 {
869 ASSERT(pausedQuery == nullptr);
870 }
871 #endif
872
873 // If the context has changed, pause the previous context's queries
874 auto contextID = context->getState().getContextID();
875 if (contextID != mPrevDrawContext)
876 {
877 for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
878 {
879 QueryGL *currentQuery = mQueries[type];
880 // Pause any old query object
881 if (currentQuery != nullptr)
882 {
883 ANGLE_TRY(currentQuery->pause(context));
884 mQueries[type] = nullptr;
885 }
886
887 // Check if this new context needs to resume a query
888 gl::Query *newQuery = glState.getActiveQuery(type);
889 if (newQuery != nullptr)
890 {
891 QueryGL *queryGL = GetImplAs<QueryGL>(newQuery);
892 ANGLE_TRY(queryGL->resume(context));
893 }
894 }
895 }
896 onTransformFeedbackStateChange();
897 mPrevDrawContext = contextID;
898
899 // Seamless cubemaps are required for ES3 and higher contexts. It should be the cheapest to set
900 // this state here since MakeCurrent is expected to be called less frequently than draw calls.
901 setTextureCubemapSeamlessEnabled(context->getClientMajorVersion() >= 3);
902
903 return angle::Result::Continue;
904 }
905
updateProgramTextureBindings(const gl::Context * context)906 void StateManagerGL::updateProgramTextureBindings(const gl::Context *context)
907 {
908 const gl::State &glState = context->getState();
909 const gl::ProgramExecutable *executable = glState.getProgramExecutable();
910
911 // It is possible there is no active program during a path operation.
912 if (!executable)
913 return;
914
915 const gl::ActiveTexturesCache &textures = glState.getActiveTexturesCache();
916 const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
917 const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
918
919 for (size_t textureUnitIndex : activeTextures)
920 {
921 gl::TextureType textureType = textureTypes[textureUnitIndex];
922 gl::Texture *texture = textures[textureUnitIndex];
923
924 // A nullptr texture indicates incomplete.
925 if (texture != nullptr)
926 {
927 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
928 // The DIRTY_BIT_BOUND_AS_ATTACHMENT may get inserted when texture is attached to
929 // FBO and if texture is already bound, Texture::syncState will not get called and dirty
930 // bit not gets cleared. But this bit is not used by GL backend at all, so it is
931 // harmless even though we expect texture is clean when reaching here. The bit will
932 // still get cleared next time syncState been called.
933 ASSERT(!texture->hasAnyDirtyBitExcludingBoundAsAttachmentBit());
934 ASSERT(!textureGL->hasAnyDirtyBit());
935
936 activeTexture(textureUnitIndex);
937 bindTexture(textureType, textureGL->getTextureID());
938 }
939 else
940 {
941 activeTexture(textureUnitIndex);
942 bindTexture(textureType, 0);
943 }
944 }
945 }
946
updateProgramStorageBufferBindings(const gl::Context * context)947 void StateManagerGL::updateProgramStorageBufferBindings(const gl::Context *context)
948 {
949 const gl::State &glState = context->getState();
950 const gl::Program *program = glState.getProgram();
951
952 for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
953 blockIndex++)
954 {
955 GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
956 const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
957
958 if (shaderStorageBuffer.get() != nullptr)
959 {
960 BufferGL *bufferGL = GetImplAs<BufferGL>(shaderStorageBuffer.get());
961
962 if (shaderStorageBuffer.getSize() == 0)
963 {
964 bindBufferBase(gl::BufferBinding::ShaderStorage, binding, bufferGL->getBufferID());
965 }
966 else
967 {
968 bindBufferRange(gl::BufferBinding::ShaderStorage, binding, bufferGL->getBufferID(),
969 shaderStorageBuffer.getOffset(), shaderStorageBuffer.getSize());
970 }
971 }
972 }
973 }
974
updateProgramUniformBufferBindings(const gl::Context * context)975 void StateManagerGL::updateProgramUniformBufferBindings(const gl::Context *context)
976 {
977 // Sync the current program state
978 const gl::State &glState = context->getState();
979 const gl::Program *program = glState.getProgram();
980
981 for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
982 uniformBlockIndex++)
983 {
984 GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
985 const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding);
986
987 if (uniformBuffer.get() != nullptr)
988 {
989 BufferGL *bufferGL = GetImplAs<BufferGL>(uniformBuffer.get());
990
991 if (uniformBuffer.getSize() == 0)
992 {
993 bindBufferBase(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID());
994 }
995 else
996 {
997 bindBufferRange(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID(),
998 uniformBuffer.getOffset(), uniformBuffer.getSize());
999 }
1000 }
1001 }
1002 }
1003
updateProgramAtomicCounterBufferBindings(const gl::Context * context)1004 void StateManagerGL::updateProgramAtomicCounterBufferBindings(const gl::Context *context)
1005 {
1006 const gl::State &glState = context->getState();
1007 const gl::Program *program = glState.getProgram();
1008
1009 for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
1010 {
1011 GLuint binding = atomicCounterBuffer.binding;
1012 const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
1013
1014 if (buffer.get() != nullptr)
1015 {
1016 BufferGL *bufferGL = GetImplAs<BufferGL>(buffer.get());
1017
1018 if (buffer.getSize() == 0)
1019 {
1020 bindBufferBase(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID());
1021 }
1022 else
1023 {
1024 bindBufferRange(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID(),
1025 buffer.getOffset(), buffer.getSize());
1026 }
1027 }
1028 }
1029 }
1030
updateProgramImageBindings(const gl::Context * context)1031 void StateManagerGL::updateProgramImageBindings(const gl::Context *context)
1032 {
1033 const gl::State &glState = context->getState();
1034 const gl::ProgramExecutable *executable = glState.getProgramExecutable();
1035 const gl::Program *program = glState.getProgram();
1036
1037 // It is possible there is no active program during a path operation.
1038 if (!executable || !program)
1039 return;
1040
1041 ASSERT(context->getClientVersion() >= gl::ES_3_1 || program->getImageBindings().empty());
1042 for (size_t imageUnitIndex : executable->getActiveImagesMask())
1043 {
1044 const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
1045 const TextureGL *textureGL = SafeGetImplAs<TextureGL>(imageUnit.texture.get());
1046 if (textureGL)
1047 {
1048 bindImageTexture(imageUnitIndex, textureGL->getTextureID(), imageUnit.level,
1049 imageUnit.layered, imageUnit.layer, imageUnit.access,
1050 imageUnit.format);
1051 }
1052 else
1053 {
1054 bindImageTexture(imageUnitIndex, 0, imageUnit.level, imageUnit.layered, imageUnit.layer,
1055 imageUnit.access, imageUnit.format);
1056 }
1057 }
1058 }
1059
setAttributeCurrentData(size_t index,const gl::VertexAttribCurrentValueData & data)1060 void StateManagerGL::setAttributeCurrentData(size_t index,
1061 const gl::VertexAttribCurrentValueData &data)
1062 {
1063 if (mVertexAttribCurrentValues[index] != data)
1064 {
1065 mVertexAttribCurrentValues[index] = data;
1066 switch (mVertexAttribCurrentValues[index].Type)
1067 {
1068 case gl::VertexAttribType::Float:
1069 mFunctions->vertexAttrib4fv(static_cast<GLuint>(index),
1070 mVertexAttribCurrentValues[index].Values.FloatValues);
1071 break;
1072 case gl::VertexAttribType::Int:
1073 mFunctions->vertexAttribI4iv(static_cast<GLuint>(index),
1074 mVertexAttribCurrentValues[index].Values.IntValues);
1075 break;
1076 case gl::VertexAttribType::UnsignedInt:
1077 mFunctions->vertexAttribI4uiv(
1078 static_cast<GLuint>(index),
1079 mVertexAttribCurrentValues[index].Values.UnsignedIntValues);
1080 break;
1081 default:
1082 UNREACHABLE();
1083 }
1084
1085 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CURRENT_VALUES);
1086 mLocalDirtyCurrentValues.set(index);
1087 }
1088 }
1089
setScissorTestEnabled(bool enabled)1090 void StateManagerGL::setScissorTestEnabled(bool enabled)
1091 {
1092 if (mScissorTestEnabled != enabled)
1093 {
1094 mScissorTestEnabled = enabled;
1095 if (mScissorTestEnabled)
1096 {
1097 mFunctions->enable(GL_SCISSOR_TEST);
1098 }
1099 else
1100 {
1101 mFunctions->disable(GL_SCISSOR_TEST);
1102 }
1103
1104 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
1105 }
1106 }
1107
setScissor(const gl::Rectangle & scissor)1108 void StateManagerGL::setScissor(const gl::Rectangle &scissor)
1109 {
1110 if (scissor != mScissor)
1111 {
1112 mScissor = scissor;
1113 mFunctions->scissor(mScissor.x, mScissor.y, mScissor.width, mScissor.height);
1114
1115 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR);
1116 }
1117 }
1118
setViewport(const gl::Rectangle & viewport)1119 void StateManagerGL::setViewport(const gl::Rectangle &viewport)
1120 {
1121 if (viewport != mViewport)
1122 {
1123 mViewport = viewport;
1124 mFunctions->viewport(mViewport.x, mViewport.y, mViewport.width, mViewport.height);
1125
1126 mLocalDirtyBits.set(gl::State::DIRTY_BIT_VIEWPORT);
1127 }
1128 }
1129
setDepthRange(float near,float far)1130 void StateManagerGL::setDepthRange(float near, float far)
1131 {
1132 mNear = near;
1133 mFar = far;
1134
1135 // The glDepthRangef function isn't available until OpenGL 4.1. Prefer it when it is
1136 // available because OpenGL ES only works in floats.
1137 if (mFunctions->depthRangef)
1138 {
1139 mFunctions->depthRangef(mNear, mFar);
1140 }
1141 else
1142 {
1143 ASSERT(mFunctions->depthRange);
1144 mFunctions->depthRange(mNear, mFar);
1145 }
1146
1147 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_RANGE);
1148 }
1149
setBlendEnabled(bool enabled)1150 void StateManagerGL::setBlendEnabled(bool enabled)
1151 {
1152 const gl::DrawBufferMask mask =
1153 enabled ? mBlendStateExt.mMaxEnabledMask : gl::DrawBufferMask::Zero();
1154 if (mBlendStateExt.mEnabledMask == mask)
1155 {
1156 return;
1157 }
1158
1159 if (enabled)
1160 {
1161 mFunctions->enable(GL_BLEND);
1162 }
1163 else
1164 {
1165 mFunctions->disable(GL_BLEND);
1166 }
1167
1168 mBlendStateExt.setEnabled(enabled);
1169 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
1170 }
1171
setBlendEnabledIndexed(const gl::DrawBufferMask enabledMask)1172 void StateManagerGL::setBlendEnabledIndexed(const gl::DrawBufferMask enabledMask)
1173 {
1174 if (mBlendStateExt.mEnabledMask == enabledMask)
1175 {
1176 return;
1177 }
1178
1179 // Get DrawBufferMask of buffers with different blend enable state
1180 gl::DrawBufferMask diffMask = mBlendStateExt.mEnabledMask ^ enabledMask;
1181 const size_t diffCount = diffMask.count();
1182
1183 // Check if enabling or disabling blending for all buffers reduces the number of subsequent
1184 // indexed commands. Implicitly handles the case when the new blend enable state is the same for
1185 // all buffers.
1186 if (diffCount > 1)
1187 {
1188 // The number of indexed blend enable commands in case a mass disable is used.
1189 const size_t enabledCount = enabledMask.count();
1190
1191 // The mask and the number of indexed blend disable commands in case a mass enable is used.
1192 const gl::DrawBufferMask disabledMask = enabledMask ^ mBlendStateExt.mMaxEnabledMask;
1193 const size_t disabledCount = disabledMask.count();
1194
1195 if (enabledCount < diffCount && enabledCount <= disabledCount)
1196 {
1197 diffMask = enabledMask;
1198 mFunctions->disable(GL_BLEND);
1199 }
1200 else if (disabledCount < diffCount && disabledCount <= enabledCount)
1201 {
1202 diffMask = disabledMask;
1203 mFunctions->enable(GL_BLEND);
1204 }
1205 }
1206
1207 for (size_t drawBufferIndex : diffMask)
1208 {
1209 if (enabledMask.test(drawBufferIndex))
1210 {
1211 mFunctions->enablei(GL_BLEND, static_cast<GLuint>(drawBufferIndex));
1212 }
1213 else
1214 {
1215 mFunctions->disablei(GL_BLEND, static_cast<GLuint>(drawBufferIndex));
1216 }
1217 }
1218
1219 mBlendStateExt.mEnabledMask = enabledMask;
1220 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
1221 }
1222
setBlendColor(const gl::ColorF & blendColor)1223 void StateManagerGL::setBlendColor(const gl::ColorF &blendColor)
1224 {
1225 if (mBlendColor != blendColor)
1226 {
1227 mBlendColor = blendColor;
1228 mFunctions->blendColor(mBlendColor.red, mBlendColor.green, mBlendColor.blue,
1229 mBlendColor.alpha);
1230
1231 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_COLOR);
1232 }
1233 }
1234
setBlendFuncs(const gl::BlendStateExt & blendStateExt)1235 void StateManagerGL::setBlendFuncs(const gl::BlendStateExt &blendStateExt)
1236 {
1237 if (mBlendStateExt.mSrcColor == blendStateExt.mSrcColor &&
1238 mBlendStateExt.mDstColor == blendStateExt.mDstColor &&
1239 mBlendStateExt.mSrcAlpha == blendStateExt.mSrcAlpha &&
1240 mBlendStateExt.mDstAlpha == blendStateExt.mDstAlpha)
1241 {
1242 return;
1243 }
1244
1245 if (!mIndependentBlendStates)
1246 {
1247 mFunctions->blendFuncSeparate(
1248 blendStateExt.getSrcColorIndexed(0), blendStateExt.getDstColorIndexed(0),
1249 blendStateExt.getSrcAlphaIndexed(0), blendStateExt.getDstAlphaIndexed(0));
1250 }
1251 else
1252 {
1253 // Get DrawBufferMask of buffers with different blend factors
1254 gl::DrawBufferMask diffMask =
1255 mBlendStateExt.compareFactors(blendStateExt.mSrcColor, blendStateExt.mDstColor,
1256 blendStateExt.mSrcAlpha, blendStateExt.mDstAlpha);
1257 size_t diffCount = diffMask.count();
1258
1259 // Check if setting all buffers to the same value reduces the number of subsequent indexed
1260 // commands. Implicitly handles the case when the new blend function state is the same for
1261 // all buffers.
1262 if (diffCount > 1)
1263 {
1264 bool found = false;
1265 gl::BlendStateExt::FactorStorage::Type commonSrcColor = 0;
1266 gl::BlendStateExt::FactorStorage::Type commonDstColor = 0;
1267 gl::BlendStateExt::FactorStorage::Type commonSrcAlpha = 0;
1268 gl::BlendStateExt::FactorStorage::Type commonDstAlpha = 0;
1269 for (size_t i = 0; i < mBlendStateExt.mMaxDrawBuffers - 1; i++)
1270 {
1271 const gl::BlendStateExt::FactorStorage::Type tempCommonSrcColor =
1272 blendStateExt.expandSrcColorIndexed(i);
1273 const gl::BlendStateExt::FactorStorage::Type tempCommonDstColor =
1274 blendStateExt.expandDstColorIndexed(i);
1275 const gl::BlendStateExt::FactorStorage::Type tempCommonSrcAlpha =
1276 blendStateExt.expandSrcAlphaIndexed(i);
1277 const gl::BlendStateExt::FactorStorage::Type tempCommonDstAlpha =
1278 blendStateExt.expandDstAlphaIndexed(i);
1279
1280 const gl::DrawBufferMask tempDiffMask = blendStateExt.compareFactors(
1281 tempCommonSrcColor, tempCommonDstColor, tempCommonSrcAlpha, tempCommonDstAlpha);
1282
1283 const size_t tempDiffCount = tempDiffMask.count();
1284 if (tempDiffCount < diffCount)
1285 {
1286 found = true;
1287 diffMask = tempDiffMask;
1288 diffCount = tempDiffCount;
1289 commonSrcColor = tempCommonSrcColor;
1290 commonDstColor = tempCommonDstColor;
1291 commonSrcAlpha = tempCommonSrcAlpha;
1292 commonDstAlpha = tempCommonDstAlpha;
1293 if (tempDiffCount == 0)
1294 {
1295 break; // the blend factors are the same for all buffers
1296 }
1297 }
1298 }
1299 if (found)
1300 {
1301 mFunctions->blendFuncSeparate(
1302 ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonSrcColor)),
1303 ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonDstColor)),
1304 ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonSrcAlpha)),
1305 ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonDstAlpha)));
1306 }
1307 }
1308
1309 for (size_t drawBufferIndex : diffMask)
1310 {
1311 mFunctions->blendFuncSeparatei(static_cast<GLuint>(drawBufferIndex),
1312 blendStateExt.getSrcColorIndexed(drawBufferIndex),
1313 blendStateExt.getDstColorIndexed(drawBufferIndex),
1314 blendStateExt.getSrcAlphaIndexed(drawBufferIndex),
1315 blendStateExt.getDstAlphaIndexed(drawBufferIndex));
1316 }
1317 }
1318 mBlendStateExt.mSrcColor = blendStateExt.mSrcColor;
1319 mBlendStateExt.mDstColor = blendStateExt.mDstColor;
1320 mBlendStateExt.mSrcAlpha = blendStateExt.mSrcAlpha;
1321 mBlendStateExt.mDstAlpha = blendStateExt.mDstAlpha;
1322 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);
1323 }
1324
setBlendEquations(const gl::BlendStateExt & blendStateExt)1325 void StateManagerGL::setBlendEquations(const gl::BlendStateExt &blendStateExt)
1326 {
1327 if (mBlendStateExt.mEquationColor == blendStateExt.mEquationColor &&
1328 mBlendStateExt.mEquationAlpha == blendStateExt.mEquationAlpha)
1329 {
1330 return;
1331 }
1332
1333 if (!mIndependentBlendStates)
1334 {
1335 mFunctions->blendEquationSeparate(blendStateExt.getEquationColorIndexed(0),
1336 blendStateExt.getEquationAlphaIndexed(0));
1337 }
1338 else
1339 {
1340 // Get DrawBufferMask of buffers with different blend equations
1341 gl::DrawBufferMask diffMask = mBlendStateExt.compareEquations(blendStateExt.mEquationColor,
1342 blendStateExt.mEquationAlpha);
1343 size_t diffCount = diffMask.count();
1344
1345 // Check if setting all buffers to the same value reduces the number of subsequent indexed
1346 // commands. Implicitly handles the case when the new blend equation state is the same for
1347 // all buffers.
1348 if (diffCount > 1)
1349 {
1350 bool found = false;
1351 gl::BlendStateExt::EquationStorage::Type commonEquationColor = 0;
1352 gl::BlendStateExt::EquationStorage::Type commonEquationAlpha = 0;
1353 for (size_t i = 0; i < mBlendStateExt.mMaxDrawBuffers - 1; i++)
1354 {
1355 const gl::BlendStateExt::EquationStorage::Type tempCommonEquationColor =
1356 blendStateExt.expandEquationColorIndexed(i);
1357 const gl::BlendStateExt::EquationStorage::Type tempCommonEquationAlpha =
1358 blendStateExt.expandEquationAlphaIndexed(i);
1359
1360 const gl::DrawBufferMask tempDiffMask = blendStateExt.compareEquations(
1361 tempCommonEquationColor, tempCommonEquationAlpha);
1362
1363 const size_t tempDiffCount = tempDiffMask.count();
1364 if (tempDiffCount < diffCount)
1365 {
1366 found = true;
1367 diffMask = tempDiffMask;
1368 diffCount = tempDiffCount;
1369 commonEquationColor = tempCommonEquationColor;
1370 commonEquationAlpha = tempCommonEquationAlpha;
1371 if (tempDiffCount == 0)
1372 {
1373 break; // the new blend equations are the same for all buffers
1374 }
1375 }
1376 }
1377 if (found)
1378 {
1379 mFunctions->blendEquationSeparate(
1380 ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
1381 0, commonEquationColor)),
1382 ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
1383 0, commonEquationAlpha)));
1384 }
1385 }
1386
1387 for (size_t drawBufferIndex : diffMask)
1388 {
1389 mFunctions->blendEquationSeparatei(
1390 static_cast<GLuint>(drawBufferIndex),
1391 blendStateExt.getEquationColorIndexed(drawBufferIndex),
1392 blendStateExt.getEquationAlphaIndexed(drawBufferIndex));
1393 }
1394 }
1395 mBlendStateExt.mEquationColor = blendStateExt.mEquationColor;
1396 mBlendStateExt.mEquationAlpha = blendStateExt.mEquationAlpha;
1397 mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
1398 }
1399
setColorMask(bool red,bool green,bool blue,bool alpha)1400 void StateManagerGL::setColorMask(bool red, bool green, bool blue, bool alpha)
1401 {
1402 const gl::BlendStateExt::ColorMaskStorage::Type mask =
1403 mBlendStateExt.expandColorMaskValue(red, green, blue, alpha);
1404 if (mBlendStateExt.mColorMask != mask)
1405 {
1406 mFunctions->colorMask(red, green, blue, alpha);
1407 mBlendStateExt.mColorMask = mask;
1408 mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
1409 }
1410 }
1411
setSampleAlphaToCoverageEnabled(bool enabled)1412 void StateManagerGL::setSampleAlphaToCoverageEnabled(bool enabled)
1413 {
1414 if (mSampleAlphaToCoverageEnabled != enabled)
1415 {
1416 mSampleAlphaToCoverageEnabled = enabled;
1417 if (mSampleAlphaToCoverageEnabled)
1418 {
1419 mFunctions->enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
1420 }
1421 else
1422 {
1423 mFunctions->disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
1424 }
1425
1426 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
1427 }
1428 }
1429
setSampleCoverageEnabled(bool enabled)1430 void StateManagerGL::setSampleCoverageEnabled(bool enabled)
1431 {
1432 if (mSampleCoverageEnabled != enabled)
1433 {
1434 mSampleCoverageEnabled = enabled;
1435 if (mSampleCoverageEnabled)
1436 {
1437 mFunctions->enable(GL_SAMPLE_COVERAGE);
1438 }
1439 else
1440 {
1441 mFunctions->disable(GL_SAMPLE_COVERAGE);
1442 }
1443
1444 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
1445 }
1446 }
1447
setSampleCoverage(float value,bool invert)1448 void StateManagerGL::setSampleCoverage(float value, bool invert)
1449 {
1450 if (mSampleCoverageValue != value || mSampleCoverageInvert != invert)
1451 {
1452 mSampleCoverageValue = value;
1453 mSampleCoverageInvert = invert;
1454 mFunctions->sampleCoverage(mSampleCoverageValue, mSampleCoverageInvert);
1455
1456 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE);
1457 }
1458 }
1459
setSampleMaskEnabled(bool enabled)1460 void StateManagerGL::setSampleMaskEnabled(bool enabled)
1461 {
1462 if (mSampleMaskEnabled != enabled)
1463 {
1464 mSampleMaskEnabled = enabled;
1465 if (mSampleMaskEnabled)
1466 {
1467 mFunctions->enable(GL_SAMPLE_MASK);
1468 }
1469 else
1470 {
1471 mFunctions->disable(GL_SAMPLE_MASK);
1472 }
1473
1474 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_MASK_ENABLED);
1475 }
1476 }
1477
setSampleMaski(GLuint maskNumber,GLbitfield mask)1478 void StateManagerGL::setSampleMaski(GLuint maskNumber, GLbitfield mask)
1479 {
1480 ASSERT(maskNumber < mSampleMaskValues.size());
1481 if (mSampleMaskValues[maskNumber] != mask)
1482 {
1483 mSampleMaskValues[maskNumber] = mask;
1484 mFunctions->sampleMaski(maskNumber, mask);
1485
1486 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_MASK);
1487 }
1488 }
1489
1490 // Depth and stencil redundant state changes are guarded in the
1491 // frontend so for related cases here just set the dirty bit
1492 // and update backend states.
setDepthTestEnabled(bool enabled)1493 void StateManagerGL::setDepthTestEnabled(bool enabled)
1494 {
1495 mDepthTestEnabled = enabled;
1496 if (mDepthTestEnabled)
1497 {
1498 mFunctions->enable(GL_DEPTH_TEST);
1499 }
1500 else
1501 {
1502 mFunctions->disable(GL_DEPTH_TEST);
1503 }
1504
1505 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED);
1506 }
1507
setDepthFunc(GLenum depthFunc)1508 void StateManagerGL::setDepthFunc(GLenum depthFunc)
1509 {
1510 mDepthFunc = depthFunc;
1511 mFunctions->depthFunc(mDepthFunc);
1512
1513 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_FUNC);
1514 }
1515
setDepthMask(bool mask)1516 void StateManagerGL::setDepthMask(bool mask)
1517 {
1518 mDepthMask = mask;
1519 mFunctions->depthMask(mDepthMask);
1520
1521 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_MASK);
1522 }
1523
setStencilTestEnabled(bool enabled)1524 void StateManagerGL::setStencilTestEnabled(bool enabled)
1525 {
1526 mStencilTestEnabled = enabled;
1527 if (mStencilTestEnabled)
1528 {
1529 mFunctions->enable(GL_STENCIL_TEST);
1530 }
1531 else
1532 {
1533 mFunctions->disable(GL_STENCIL_TEST);
1534 }
1535
1536 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED);
1537 }
1538
setStencilFrontWritemask(GLuint mask)1539 void StateManagerGL::setStencilFrontWritemask(GLuint mask)
1540 {
1541 mStencilFrontWritemask = mask;
1542 mFunctions->stencilMaskSeparate(GL_FRONT, mStencilFrontWritemask);
1543
1544 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
1545 }
1546
setStencilBackWritemask(GLuint mask)1547 void StateManagerGL::setStencilBackWritemask(GLuint mask)
1548 {
1549 mStencilBackWritemask = mask;
1550 mFunctions->stencilMaskSeparate(GL_BACK, mStencilBackWritemask);
1551
1552 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
1553 }
1554
setStencilFrontFuncs(GLenum func,GLint ref,GLuint mask)1555 void StateManagerGL::setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask)
1556 {
1557 mStencilFrontFunc = func;
1558 mStencilFrontRef = ref;
1559 mStencilFrontValueMask = mask;
1560 mFunctions->stencilFuncSeparate(GL_FRONT, mStencilFrontFunc, mStencilFrontRef,
1561 mStencilFrontValueMask);
1562
1563 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT);
1564 }
1565
setStencilBackFuncs(GLenum func,GLint ref,GLuint mask)1566 void StateManagerGL::setStencilBackFuncs(GLenum func, GLint ref, GLuint mask)
1567 {
1568 mStencilBackFunc = func;
1569 mStencilBackRef = ref;
1570 mStencilBackValueMask = mask;
1571 mFunctions->stencilFuncSeparate(GL_BACK, mStencilBackFunc, mStencilBackRef,
1572 mStencilBackValueMask);
1573
1574 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK);
1575 }
1576
setStencilFrontOps(GLenum sfail,GLenum dpfail,GLenum dppass)1577 void StateManagerGL::setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass)
1578 {
1579 mStencilFrontStencilFailOp = sfail;
1580 mStencilFrontStencilPassDepthFailOp = dpfail;
1581 mStencilFrontStencilPassDepthPassOp = dppass;
1582 mFunctions->stencilOpSeparate(GL_FRONT, mStencilFrontStencilFailOp,
1583 mStencilFrontStencilPassDepthFailOp,
1584 mStencilFrontStencilPassDepthPassOp);
1585
1586 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_FRONT);
1587 }
1588
setStencilBackOps(GLenum sfail,GLenum dpfail,GLenum dppass)1589 void StateManagerGL::setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass)
1590 {
1591 mStencilBackStencilFailOp = sfail;
1592 mStencilBackStencilPassDepthFailOp = dpfail;
1593 mStencilBackStencilPassDepthPassOp = dppass;
1594 mFunctions->stencilOpSeparate(GL_BACK, mStencilBackStencilFailOp,
1595 mStencilBackStencilPassDepthFailOp,
1596 mStencilBackStencilPassDepthPassOp);
1597
1598 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_BACK);
1599 }
1600
setCullFaceEnabled(bool enabled)1601 void StateManagerGL::setCullFaceEnabled(bool enabled)
1602 {
1603 if (mCullFaceEnabled != enabled)
1604 {
1605 mCullFaceEnabled = enabled;
1606 if (mCullFaceEnabled)
1607 {
1608 mFunctions->enable(GL_CULL_FACE);
1609 }
1610 else
1611 {
1612 mFunctions->disable(GL_CULL_FACE);
1613 }
1614
1615 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE_ENABLED);
1616 }
1617 }
1618
setCullFace(gl::CullFaceMode cullFace)1619 void StateManagerGL::setCullFace(gl::CullFaceMode cullFace)
1620 {
1621 if (mCullFace != cullFace)
1622 {
1623 mCullFace = cullFace;
1624 mFunctions->cullFace(ToGLenum(mCullFace));
1625
1626 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE);
1627 }
1628 }
1629
setFrontFace(GLenum frontFace)1630 void StateManagerGL::setFrontFace(GLenum frontFace)
1631 {
1632 if (mFrontFace != frontFace)
1633 {
1634 mFrontFace = frontFace;
1635 mFunctions->frontFace(mFrontFace);
1636
1637 mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRONT_FACE);
1638 }
1639 }
1640
setPolygonOffsetFillEnabled(bool enabled)1641 void StateManagerGL::setPolygonOffsetFillEnabled(bool enabled)
1642 {
1643 if (mPolygonOffsetFillEnabled != enabled)
1644 {
1645 mPolygonOffsetFillEnabled = enabled;
1646 if (mPolygonOffsetFillEnabled)
1647 {
1648 mFunctions->enable(GL_POLYGON_OFFSET_FILL);
1649 }
1650 else
1651 {
1652 mFunctions->disable(GL_POLYGON_OFFSET_FILL);
1653 }
1654
1655 mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
1656 }
1657 }
1658
setPolygonOffset(float factor,float units)1659 void StateManagerGL::setPolygonOffset(float factor, float units)
1660 {
1661 if (mPolygonOffsetFactor != factor || mPolygonOffsetUnits != units)
1662 {
1663 mPolygonOffsetFactor = factor;
1664 mPolygonOffsetUnits = units;
1665 mFunctions->polygonOffset(mPolygonOffsetFactor, mPolygonOffsetUnits);
1666
1667 mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET);
1668 }
1669 }
1670
setRasterizerDiscardEnabled(bool enabled)1671 void StateManagerGL::setRasterizerDiscardEnabled(bool enabled)
1672 {
1673 if (mRasterizerDiscardEnabled != enabled)
1674 {
1675 mRasterizerDiscardEnabled = enabled;
1676 if (mRasterizerDiscardEnabled)
1677 {
1678 mFunctions->enable(GL_RASTERIZER_DISCARD);
1679 }
1680 else
1681 {
1682 mFunctions->disable(GL_RASTERIZER_DISCARD);
1683 }
1684
1685 mLocalDirtyBits.set(gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
1686 }
1687 }
1688
setLineWidth(float width)1689 void StateManagerGL::setLineWidth(float width)
1690 {
1691 if (mLineWidth != width)
1692 {
1693 mLineWidth = width;
1694 mFunctions->lineWidth(mLineWidth);
1695
1696 mLocalDirtyBits.set(gl::State::DIRTY_BIT_LINE_WIDTH);
1697 }
1698 }
1699
setPrimitiveRestartEnabled(const gl::Context * context,bool enabled)1700 angle::Result StateManagerGL::setPrimitiveRestartEnabled(const gl::Context *context, bool enabled)
1701 {
1702 if (mPrimitiveRestartEnabled != enabled)
1703 {
1704 GLenum cap = mFeatures.emulatePrimitiveRestartFixedIndex.enabled
1705 ? GL_PRIMITIVE_RESTART
1706 : GL_PRIMITIVE_RESTART_FIXED_INDEX;
1707
1708 if (enabled)
1709 {
1710 ANGLE_GL_TRY(context, mFunctions->enable(cap));
1711 }
1712 else
1713 {
1714 ANGLE_GL_TRY(context, mFunctions->disable(cap));
1715 }
1716 mPrimitiveRestartEnabled = enabled;
1717
1718 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
1719 }
1720
1721 return angle::Result::Continue;
1722 }
1723
setPrimitiveRestartIndex(const gl::Context * context,GLuint index)1724 angle::Result StateManagerGL::setPrimitiveRestartIndex(const gl::Context *context, GLuint index)
1725 {
1726 if (mPrimitiveRestartIndex != index)
1727 {
1728 ANGLE_GL_TRY(context, mFunctions->primitiveRestartIndex(index));
1729 mPrimitiveRestartIndex = index;
1730
1731 // No dirty bit for this state, it is not exposed to the frontend.
1732 }
1733
1734 return angle::Result::Continue;
1735 }
1736
setClearDepth(float clearDepth)1737 void StateManagerGL::setClearDepth(float clearDepth)
1738 {
1739 if (mClearDepth != clearDepth)
1740 {
1741 mClearDepth = clearDepth;
1742
1743 // The glClearDepthf function isn't available until OpenGL 4.1. Prefer it when it is
1744 // available because OpenGL ES only works in floats.
1745 if (mFunctions->clearDepthf)
1746 {
1747 mFunctions->clearDepthf(mClearDepth);
1748 }
1749 else
1750 {
1751 ASSERT(mFunctions->clearDepth);
1752 mFunctions->clearDepth(mClearDepth);
1753 }
1754
1755 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_DEPTH);
1756 }
1757 }
1758
setClearColor(const gl::ColorF & clearColor)1759 void StateManagerGL::setClearColor(const gl::ColorF &clearColor)
1760 {
1761 gl::ColorF modifiedClearColor = clearColor;
1762 if (mFeatures.clearToZeroOrOneBroken.enabled &&
1763 (clearColor.red == 1.0f || clearColor.red == 0.0f) &&
1764 (clearColor.green == 1.0f || clearColor.green == 0.0f) &&
1765 (clearColor.blue == 1.0f || clearColor.blue == 0.0f) &&
1766 (clearColor.alpha == 1.0f || clearColor.alpha == 0.0f))
1767 {
1768 if (clearColor.alpha == 1.0f)
1769 {
1770 modifiedClearColor.alpha = 2.0f;
1771 }
1772 else
1773 {
1774 modifiedClearColor.alpha = -1.0f;
1775 }
1776 }
1777
1778 if (mClearColor != modifiedClearColor)
1779 {
1780 mClearColor = modifiedClearColor;
1781 mFunctions->clearColor(mClearColor.red, mClearColor.green, mClearColor.blue,
1782 mClearColor.alpha);
1783
1784 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_COLOR);
1785 }
1786 }
1787
setClearStencil(GLint clearStencil)1788 void StateManagerGL::setClearStencil(GLint clearStencil)
1789 {
1790 if (mClearStencil != clearStencil)
1791 {
1792 mClearStencil = clearStencil;
1793 mFunctions->clearStencil(mClearStencil);
1794
1795 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_STENCIL);
1796 }
1797 }
1798
syncState(const gl::Context * context,const gl::State::DirtyBits & glDirtyBits,const gl::State::DirtyBits & bitMask)1799 angle::Result StateManagerGL::syncState(const gl::Context *context,
1800 const gl::State::DirtyBits &glDirtyBits,
1801 const gl::State::DirtyBits &bitMask)
1802 {
1803 const gl::State &state = context->getState();
1804
1805 const gl::State::DirtyBits glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits) & bitMask;
1806 if (!glAndLocalDirtyBits.any())
1807 {
1808 return angle::Result::Continue;
1809 }
1810
1811 // TODO(jmadill): Investigate only syncing vertex state for active attributes
1812 for (auto iter = glAndLocalDirtyBits.begin(), endIter = glAndLocalDirtyBits.end();
1813 iter != endIter; ++iter)
1814 {
1815 switch (*iter)
1816 {
1817 case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
1818 setScissorTestEnabled(state.isScissorTestEnabled());
1819 break;
1820 case gl::State::DIRTY_BIT_SCISSOR:
1821 {
1822 const gl::Rectangle &scissor = state.getScissor();
1823 setScissor(scissor);
1824 }
1825 break;
1826 case gl::State::DIRTY_BIT_VIEWPORT:
1827 {
1828 const gl::Rectangle &viewport = state.getViewport();
1829 setViewport(viewport);
1830 }
1831 break;
1832 case gl::State::DIRTY_BIT_DEPTH_RANGE:
1833 setDepthRange(state.getNearPlane(), state.getFarPlane());
1834 break;
1835 case gl::State::DIRTY_BIT_BLEND_ENABLED:
1836 if (mIndependentBlendStates)
1837 {
1838 setBlendEnabledIndexed(state.getBlendEnabledDrawBufferMask());
1839 }
1840 else
1841 {
1842 setBlendEnabled(state.isBlendEnabled());
1843 }
1844 break;
1845 case gl::State::DIRTY_BIT_BLEND_COLOR:
1846 setBlendColor(state.getBlendColor());
1847 break;
1848 case gl::State::DIRTY_BIT_BLEND_FUNCS:
1849 {
1850 setBlendFuncs(state.getBlendStateExt());
1851 break;
1852 }
1853 case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
1854 {
1855 setBlendEquations(state.getBlendStateExt());
1856 break;
1857 }
1858 case gl::State::DIRTY_BIT_COLOR_MASK:
1859 {
1860 const gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
1861 const FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
1862 const bool disableAlphaWrite =
1863 framebufferGL->hasEmulatedAlphaChannelTextureAttachment();
1864
1865 setColorMaskForFramebuffer(state.getBlendStateExt(), disableAlphaWrite);
1866 break;
1867 }
1868 case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
1869 setSampleAlphaToCoverageEnabled(state.isSampleAlphaToCoverageEnabled());
1870 break;
1871 case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
1872 setSampleCoverageEnabled(state.isSampleCoverageEnabled());
1873 break;
1874 case gl::State::DIRTY_BIT_SAMPLE_COVERAGE:
1875 setSampleCoverage(state.getSampleCoverageValue(), state.getSampleCoverageInvert());
1876 break;
1877 case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
1878 setDepthTestEnabled(state.isDepthTestEnabled());
1879 break;
1880 case gl::State::DIRTY_BIT_DEPTH_FUNC:
1881 setDepthFunc(state.getDepthStencilState().depthFunc);
1882 break;
1883 case gl::State::DIRTY_BIT_DEPTH_MASK:
1884 setDepthMask(state.getDepthStencilState().depthMask);
1885 break;
1886 case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
1887 setStencilTestEnabled(state.isStencilTestEnabled());
1888 break;
1889 case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
1890 {
1891 const auto &depthStencilState = state.getDepthStencilState();
1892 setStencilFrontFuncs(depthStencilState.stencilFunc, state.getStencilRef(),
1893 depthStencilState.stencilMask);
1894 break;
1895 }
1896 case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
1897 {
1898 const auto &depthStencilState = state.getDepthStencilState();
1899 setStencilBackFuncs(depthStencilState.stencilBackFunc, state.getStencilBackRef(),
1900 depthStencilState.stencilBackMask);
1901 break;
1902 }
1903 case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
1904 {
1905 const auto &depthStencilState = state.getDepthStencilState();
1906 setStencilFrontOps(depthStencilState.stencilFail,
1907 depthStencilState.stencilPassDepthFail,
1908 depthStencilState.stencilPassDepthPass);
1909 break;
1910 }
1911 case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
1912 {
1913 const auto &depthStencilState = state.getDepthStencilState();
1914 setStencilBackOps(depthStencilState.stencilBackFail,
1915 depthStencilState.stencilBackPassDepthFail,
1916 depthStencilState.stencilBackPassDepthPass);
1917 break;
1918 }
1919 case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
1920 setStencilFrontWritemask(state.getDepthStencilState().stencilWritemask);
1921 break;
1922 case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
1923 setStencilBackWritemask(state.getDepthStencilState().stencilBackWritemask);
1924 break;
1925 case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
1926 setCullFaceEnabled(state.isCullFaceEnabled());
1927 break;
1928 case gl::State::DIRTY_BIT_CULL_FACE:
1929 setCullFace(state.getRasterizerState().cullMode);
1930 break;
1931 case gl::State::DIRTY_BIT_FRONT_FACE:
1932 setFrontFace(state.getRasterizerState().frontFace);
1933 break;
1934 case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
1935 setPolygonOffsetFillEnabled(state.isPolygonOffsetFillEnabled());
1936 break;
1937 case gl::State::DIRTY_BIT_POLYGON_OFFSET:
1938 {
1939 const auto &rasterizerState = state.getRasterizerState();
1940 setPolygonOffset(rasterizerState.polygonOffsetFactor,
1941 rasterizerState.polygonOffsetUnits);
1942 break;
1943 }
1944 case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
1945 setRasterizerDiscardEnabled(state.isRasterizerDiscardEnabled());
1946 break;
1947 case gl::State::DIRTY_BIT_LINE_WIDTH:
1948 setLineWidth(state.getLineWidth());
1949 break;
1950 case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
1951 ANGLE_TRY(setPrimitiveRestartEnabled(context, state.isPrimitiveRestartEnabled()));
1952 break;
1953 case gl::State::DIRTY_BIT_CLEAR_COLOR:
1954 setClearColor(state.getColorClearValue());
1955 break;
1956 case gl::State::DIRTY_BIT_CLEAR_DEPTH:
1957 setClearDepth(state.getDepthClearValue());
1958 break;
1959 case gl::State::DIRTY_BIT_CLEAR_STENCIL:
1960 setClearStencil(state.getStencilClearValue());
1961 break;
1962 case gl::State::DIRTY_BIT_UNPACK_STATE:
1963 ANGLE_TRY(setPixelUnpackState(context, state.getUnpackState()));
1964 break;
1965 case gl::State::DIRTY_BIT_UNPACK_BUFFER_BINDING:
1966 ANGLE_TRY(setPixelUnpackBuffer(
1967 context, state.getTargetBuffer(gl::BufferBinding::PixelUnpack)));
1968 break;
1969 case gl::State::DIRTY_BIT_PACK_STATE:
1970 ANGLE_TRY(setPixelPackState(context, state.getPackState()));
1971 break;
1972 case gl::State::DIRTY_BIT_PACK_BUFFER_BINDING:
1973 ANGLE_TRY(setPixelPackBuffer(context,
1974 state.getTargetBuffer(gl::BufferBinding::PixelPack)));
1975 break;
1976 case gl::State::DIRTY_BIT_DITHER_ENABLED:
1977 setDitherEnabled(state.isDitherEnabled());
1978 break;
1979 case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
1980 {
1981 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
1982
1983 // Necessary for an Intel TexImage workaround.
1984 if (!framebuffer)
1985 continue;
1986
1987 FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
1988 bindFramebuffer(
1989 mHasSeparateFramebufferBindings ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER,
1990 framebufferGL->getFramebufferID());
1991 break;
1992 }
1993 case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
1994 {
1995 gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
1996
1997 // Necessary for an Intel TexImage workaround.
1998 if (!framebuffer)
1999 continue;
2000
2001 FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
2002 bindFramebuffer(
2003 mHasSeparateFramebufferBindings ? GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER,
2004 framebufferGL->getFramebufferID());
2005
2006 const gl::Program *program = state.getProgram();
2007 if (program)
2008 {
2009 updateMultiviewBaseViewLayerIndexUniform(program, framebufferGL->getState());
2010 }
2011
2012 // Changing the draw framebuffer binding sometimes requires resetting srgb blending.
2013 iter.setLaterBit(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE);
2014
2015 // If the framebuffer is emulating RGB on top of RGBA, the color mask has to be
2016 // updated
2017 iter.setLaterBit(gl::State::DIRTY_BIT_COLOR_MASK);
2018 break;
2019 }
2020 case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
2021 // TODO(jmadill): implement this
2022 break;
2023 case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
2024 {
2025 VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(state.getVertexArray());
2026 bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getNativeState());
2027
2028 ANGLE_TRY(propagateProgramToVAO(context, state.getProgram(),
2029 GetImplAs<VertexArrayGL>(state.getVertexArray())));
2030
2031 if (mFeatures.syncVertexArraysToDefault.enabled)
2032 {
2033 // Re-sync the vertex array because all frontend VAOs share the same backend
2034 // state. Only sync bits that can be set in ES2.0 or 3.0
2035 gl::VertexArray::DirtyBits dirtyBits;
2036 gl::VertexArray::DirtyAttribBitsArray dirtyAttribBits;
2037 gl::VertexArray::DirtyBindingBitsArray dirtBindingBits;
2038
2039 dirtyBits.set(gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
2040 for (size_t attrib = 0; attrib < mDefaultVAOState.attributes.size(); attrib++)
2041 {
2042 dirtyBits.set(gl::VertexArray::DIRTY_BIT_ATTRIB_0 + attrib);
2043 dirtyAttribBits[attrib].set(gl::VertexArray::DIRTY_ATTRIB_ENABLED);
2044 dirtyAttribBits[attrib].set(gl::VertexArray::DIRTY_ATTRIB_POINTER);
2045 dirtyAttribBits[attrib].set(gl::VertexArray::DIRTY_ATTRIB_POINTER_BUFFER);
2046 }
2047 for (size_t binding = 0; binding < mDefaultVAOState.bindings.size(); binding++)
2048 {
2049 dirtyBits.set(gl::VertexArray::DIRTY_BIT_BINDING_0 + binding);
2050 dirtBindingBits[binding].set(gl::VertexArray::DIRTY_BINDING_DIVISOR);
2051 }
2052
2053 ANGLE_TRY(
2054 vaoGL->syncState(context, dirtyBits, &dirtyAttribBits, &dirtBindingBits));
2055 }
2056 break;
2057 }
2058 case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
2059 updateDrawIndirectBufferBinding(context);
2060 break;
2061 case gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
2062 updateDispatchIndirectBufferBinding(context);
2063 break;
2064 case gl::State::DIRTY_BIT_PROGRAM_BINDING:
2065 {
2066 gl::Program *program = state.getProgram();
2067 if (program != nullptr)
2068 {
2069 useProgram(GetImplAs<ProgramGL>(program)->getProgramID());
2070 }
2071 break;
2072 }
2073 case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
2074 {
2075 const gl::Program *program = state.getProgram();
2076 const gl::ProgramExecutable *executable = state.getProgramExecutable();
2077
2078 if (program && executable)
2079 {
2080 iter.setLaterBit(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
2081
2082 if (executable->getActiveImagesMask().any())
2083 {
2084 iter.setLaterBit(gl::State::DIRTY_BIT_IMAGE_BINDINGS);
2085 }
2086
2087 if (program->getActiveShaderStorageBlockCount() > 0)
2088 {
2089 iter.setLaterBit(gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
2090 }
2091
2092 if (program->getActiveUniformBlockCount() > 0)
2093 {
2094 iter.setLaterBit(gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
2095 }
2096
2097 if (program->getActiveAtomicCounterBufferCount() > 0)
2098 {
2099 iter.setLaterBit(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
2100 }
2101
2102 if (mIsMultiviewEnabled && program->usesMultiview())
2103 {
2104 updateMultiviewBaseViewLayerIndexUniform(
2105 program, state.getDrawFramebuffer()->getImplementation()->getState());
2106 }
2107 }
2108
2109 if (!program ||
2110 !program->getExecutable().hasLinkedShaderStage(gl::ShaderType::Compute))
2111 {
2112 ANGLE_TRY(propagateProgramToVAO(
2113 context, program, GetImplAs<VertexArrayGL>(state.getVertexArray())));
2114 }
2115 break;
2116 }
2117 case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
2118 updateProgramTextureBindings(context);
2119 break;
2120 case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
2121 syncSamplersState(context);
2122 break;
2123 case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
2124 updateProgramImageBindings(context);
2125 break;
2126 case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
2127 syncTransformFeedbackState(context);
2128 break;
2129 case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
2130 updateProgramStorageBufferBindings(context);
2131 break;
2132 case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
2133 updateProgramUniformBufferBindings(context);
2134 break;
2135 case gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
2136 updateProgramAtomicCounterBufferBindings(context);
2137 break;
2138 case gl::State::DIRTY_BIT_MULTISAMPLING:
2139 setMultisamplingStateEnabled(state.isMultisamplingEnabled());
2140 break;
2141 case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
2142 setSampleAlphaToOneStateEnabled(state.isSampleAlphaToOneEnabled());
2143 break;
2144 case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
2145 setCoverageModulation(state.getCoverageModulation());
2146 break;
2147 case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE:
2148 setFramebufferSRGBEnabledForFramebuffer(
2149 context, state.getFramebufferSRGB(),
2150 GetImplAs<FramebufferGL>(state.getDrawFramebuffer()));
2151 break;
2152 case gl::State::DIRTY_BIT_SAMPLE_MASK_ENABLED:
2153 setSampleMaskEnabled(state.isSampleMaskEnabled());
2154 break;
2155 case gl::State::DIRTY_BIT_SAMPLE_MASK:
2156 {
2157 for (GLuint maskNumber = 0; maskNumber < state.getMaxSampleMaskWords();
2158 ++maskNumber)
2159 {
2160 setSampleMaski(maskNumber, state.getSampleMaskWord(maskNumber));
2161 }
2162 break;
2163 }
2164 case gl::State::DIRTY_BIT_CURRENT_VALUES:
2165 {
2166 gl::AttributesMask combinedMask =
2167 (state.getAndResetDirtyCurrentValues() | mLocalDirtyCurrentValues);
2168 mLocalDirtyCurrentValues.reset();
2169
2170 for (auto attribIndex : combinedMask)
2171 {
2172 setAttributeCurrentData(attribIndex,
2173 state.getVertexAttribCurrentValue(attribIndex));
2174 }
2175 break;
2176 }
2177 case gl::State::DIRTY_BIT_PROVOKING_VERTEX:
2178 setProvokingVertex(ToGLenum(state.getProvokingVertex()));
2179 break;
2180 case gl::State::DIRTY_BIT_EXTENDED:
2181 // Handling clip distance enabled flags:
2182 setClipDistancesEnable(state.getEnabledClipDistances());
2183 // TODO(jmadill): handle mipmap generation hint
2184 // TODO(jmadill): handle shader derivative hint
2185 // Nothing to do until EXT_clip_contorl is implemented.
2186 break;
2187 case gl::State::DIRTY_BIT_SAMPLE_SHADING:
2188 // Nothing to do until OES_sample_shading is implemented.
2189 break;
2190 case gl::State::DIRTY_BIT_PATCH_VERTICES:
2191 // Nothing to do until EXT_tessellation_shader is implemented.
2192 break;
2193 default:
2194 UNREACHABLE();
2195 break;
2196 }
2197 }
2198
2199 mLocalDirtyBits &= ~(bitMask);
2200
2201 return angle::Result::Continue;
2202 }
2203
setFramebufferSRGBEnabled(const gl::Context * context,bool enabled)2204 void StateManagerGL::setFramebufferSRGBEnabled(const gl::Context *context, bool enabled)
2205 {
2206 if (!mFramebufferSRGBAvailable)
2207 {
2208 return;
2209 }
2210
2211 if (mFramebufferSRGBEnabled != enabled)
2212 {
2213 mFramebufferSRGBEnabled = enabled;
2214 if (mFramebufferSRGBEnabled)
2215 {
2216 mFunctions->enable(GL_FRAMEBUFFER_SRGB);
2217 }
2218 else
2219 {
2220 mFunctions->disable(GL_FRAMEBUFFER_SRGB);
2221 }
2222 mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE);
2223 }
2224 }
2225
setFramebufferSRGBEnabledForFramebuffer(const gl::Context * context,bool enabled,const FramebufferGL * framebuffer)2226 void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context,
2227 bool enabled,
2228 const FramebufferGL *framebuffer)
2229 {
2230 if (framebuffer->isDefault())
2231 {
2232 // Obey the framebuffer sRGB state for blending on all framebuffers except the default
2233 // framebuffer.
2234 // When SRGB blending is enabled, only SRGB capable formats will use it but the default
2235 // framebuffer will always use it if it is enabled.
2236 // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
2237 setFramebufferSRGBEnabled(context, false);
2238 }
2239 else
2240 {
2241 setFramebufferSRGBEnabled(context, enabled);
2242 }
2243 }
2244
setColorMaskForFramebuffer(const gl::BlendStateExt & blendStateExt,const bool disableAlpha)2245 void StateManagerGL::setColorMaskForFramebuffer(const gl::BlendStateExt &blendStateExt,
2246 const bool disableAlpha)
2247 {
2248 bool r, g, b, a;
2249
2250 // Given that disableAlpha can be true only on macOS backbuffers and color mask is re-synced on
2251 // bound draw framebuffer change, switch all draw buffers color masks to avoid special case
2252 // later.
2253 if (!mIndependentBlendStates || disableAlpha)
2254 {
2255 blendStateExt.getColorMaskIndexed(0, &r, &g, &b, &a);
2256 setColorMask(r, g, b, disableAlpha ? false : a);
2257 return;
2258 }
2259
2260 // Check if the current mask already matches the new state
2261 if (mBlendStateExt.mColorMask == blendStateExt.mColorMask)
2262 {
2263 return;
2264 }
2265
2266 // Get DrawBufferMask of buffers with different color masks
2267 gl::DrawBufferMask diffMask = mBlendStateExt.compareColorMask(blendStateExt.mColorMask);
2268 size_t diffCount = diffMask.count();
2269
2270 // Check if setting all buffers to the same value reduces the number of subsequent indexed
2271 // commands. Implicitly handles the case when the new mask is the same for all buffers.
2272 // For instance, let's say that previously synced mask is ccccff00 and the new state is
2273 // ffeeeeee. Instead of calling colorMaski 8 times, ANGLE can set all buffers to `e` and then
2274 // use colorMaski only twice. On the other hand, if the new state is cceeee00, a non-indexed
2275 // call will increase the total number of GL commands.
2276 if (diffCount > 1)
2277 {
2278 bool found = false;
2279 gl::BlendStateExt::ColorMaskStorage::Type commonColorMask = 0;
2280 for (size_t i = 0; i < mBlendStateExt.mMaxDrawBuffers - 1; i++)
2281 {
2282 const gl::BlendStateExt::ColorMaskStorage::Type tempCommonColorMask =
2283 blendStateExt.expandColorMaskIndexed(i);
2284 const gl::DrawBufferMask tempDiffMask =
2285 blendStateExt.compareColorMask(tempCommonColorMask);
2286 const size_t tempDiffCount = tempDiffMask.count();
2287 if (tempDiffCount < diffCount)
2288 {
2289 found = true;
2290 diffMask = tempDiffMask;
2291 diffCount = tempDiffCount;
2292 commonColorMask = tempCommonColorMask;
2293 if (tempDiffCount == 0)
2294 {
2295 break; // the new mask is the same for all buffers
2296 }
2297 }
2298 }
2299 if (found)
2300 {
2301 gl::BlendStateExt::UnpackColorMask(commonColorMask, &r, &g, &b, &a);
2302 mFunctions->colorMask(r, g, b, a);
2303 }
2304 }
2305
2306 for (size_t drawBufferIndex : diffMask)
2307 {
2308 blendStateExt.getColorMaskIndexed(drawBufferIndex, &r, &g, &b, &a);
2309 mFunctions->colorMaski(static_cast<GLuint>(drawBufferIndex), r, g, b, a);
2310 }
2311
2312 mBlendStateExt.mColorMask = blendStateExt.mColorMask;
2313 mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
2314 }
2315
setDitherEnabled(bool enabled)2316 void StateManagerGL::setDitherEnabled(bool enabled)
2317 {
2318 if (mDitherEnabled != enabled)
2319 {
2320 mDitherEnabled = enabled;
2321 if (mDitherEnabled)
2322 {
2323 mFunctions->enable(GL_DITHER);
2324 }
2325 else
2326 {
2327 mFunctions->disable(GL_DITHER);
2328 }
2329 }
2330 }
2331
setMultisamplingStateEnabled(bool enabled)2332 void StateManagerGL::setMultisamplingStateEnabled(bool enabled)
2333 {
2334 if (mMultisamplingEnabled != enabled)
2335 {
2336 mMultisamplingEnabled = enabled;
2337 if (mMultisamplingEnabled)
2338 {
2339 mFunctions->enable(GL_MULTISAMPLE_EXT);
2340 }
2341 else
2342 {
2343 mFunctions->disable(GL_MULTISAMPLE_EXT);
2344 }
2345 mLocalDirtyBits.set(gl::State::DIRTY_BIT_MULTISAMPLING);
2346 }
2347 }
2348
setSampleAlphaToOneStateEnabled(bool enabled)2349 void StateManagerGL::setSampleAlphaToOneStateEnabled(bool enabled)
2350 {
2351 if (mSampleAlphaToOneEnabled != enabled)
2352 {
2353 mSampleAlphaToOneEnabled = enabled;
2354 if (mSampleAlphaToOneEnabled)
2355 {
2356 mFunctions->enable(GL_SAMPLE_ALPHA_TO_ONE);
2357 }
2358 else
2359 {
2360 mFunctions->disable(GL_SAMPLE_ALPHA_TO_ONE);
2361 }
2362 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
2363 }
2364 }
2365
setCoverageModulation(GLenum components)2366 void StateManagerGL::setCoverageModulation(GLenum components)
2367 {
2368 if (mCoverageModulation != components)
2369 {
2370 mCoverageModulation = components;
2371 mFunctions->coverageModulationNV(components);
2372
2373 mLocalDirtyBits.set(gl::State::DIRTY_BIT_COVERAGE_MODULATION);
2374 }
2375 }
2376
setProvokingVertex(GLenum mode)2377 void StateManagerGL::setProvokingVertex(GLenum mode)
2378 {
2379 if (mode != mProvokingVertex)
2380 {
2381 mFunctions->provokingVertex(mode);
2382 mProvokingVertex = mode;
2383
2384 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PROVOKING_VERTEX);
2385 }
2386 }
2387
setClipDistancesEnable(const gl::State::ClipDistanceEnableBits & enables)2388 void StateManagerGL::setClipDistancesEnable(const gl::State::ClipDistanceEnableBits &enables)
2389 {
2390 if (enables == mEnabledClipDistances)
2391 {
2392 return;
2393 }
2394 ASSERT(mMaxClipDistances <= gl::IMPLEMENTATION_MAX_CLIP_DISTANCES);
2395
2396 gl::State::ClipDistanceEnableBits diff = enables ^ mEnabledClipDistances;
2397 for (size_t i : diff)
2398 {
2399 if (enables.test(i))
2400 {
2401 mFunctions->enable(GL_CLIP_DISTANCE0_EXT + static_cast<uint32_t>(i));
2402 }
2403 else
2404 {
2405 mFunctions->disable(GL_CLIP_DISTANCE0_EXT + static_cast<uint32_t>(i));
2406 }
2407 }
2408
2409 mEnabledClipDistances = enables;
2410 mLocalDirtyBits.set(gl::State::DIRTY_BIT_EXTENDED);
2411 }
2412
setTextureCubemapSeamlessEnabled(bool enabled)2413 void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
2414 {
2415 // TODO(jmadill): Also check for seamless extension.
2416 if (!mFunctions->isAtLeastGL(gl::Version(3, 2)))
2417 {
2418 return;
2419 }
2420
2421 if (mTextureCubemapSeamlessEnabled != enabled)
2422 {
2423 mTextureCubemapSeamlessEnabled = enabled;
2424 if (mTextureCubemapSeamlessEnabled)
2425 {
2426 mFunctions->enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
2427 }
2428 else
2429 {
2430 mFunctions->disable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
2431 }
2432 }
2433 }
2434
propagateProgramToVAO(const gl::Context * context,const gl::Program * program,VertexArrayGL * vao)2435 angle::Result StateManagerGL::propagateProgramToVAO(const gl::Context *context,
2436 const gl::Program *program,
2437 VertexArrayGL *vao)
2438 {
2439 if (vao == nullptr)
2440 {
2441 return angle::Result::Continue;
2442 }
2443
2444 // Number of views:
2445 if (mIsMultiviewEnabled)
2446 {
2447 int programNumViews = 1;
2448 if (program && program->usesMultiview())
2449 {
2450 programNumViews = program->getNumViews();
2451 }
2452 ANGLE_TRY(vao->applyNumViewsToDivisor(context, programNumViews));
2453 }
2454
2455 // Attribute enabled mask:
2456 if (program)
2457 {
2458 ANGLE_TRY(vao->applyActiveAttribLocationsMask(
2459 context, program->getExecutable().getActiveAttribLocationsMask()));
2460 }
2461
2462 return angle::Result::Continue;
2463 }
2464
updateMultiviewBaseViewLayerIndexUniformImpl(const gl::Program * program,const gl::FramebufferState & drawFramebufferState) const2465 void StateManagerGL::updateMultiviewBaseViewLayerIndexUniformImpl(
2466 const gl::Program *program,
2467 const gl::FramebufferState &drawFramebufferState) const
2468 {
2469 ASSERT(mIsMultiviewEnabled && program && program->usesMultiview());
2470 const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
2471 if (drawFramebufferState.isMultiview())
2472 {
2473 programGL->enableLayeredRenderingPath(drawFramebufferState.getBaseViewIndex());
2474 }
2475 }
2476
syncSamplersState(const gl::Context * context)2477 void StateManagerGL::syncSamplersState(const gl::Context *context)
2478 {
2479 const gl::SamplerBindingVector &samplers = context->getState().getSamplers();
2480
2481 // This could be optimized by using a separate binding dirty bit per sampler.
2482 for (size_t samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex)
2483 {
2484 const gl::Sampler *sampler = samplers[samplerIndex].get();
2485 if (sampler != nullptr)
2486 {
2487 SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler);
2488 bindSampler(samplerIndex, samplerGL->getSamplerID());
2489 }
2490 else
2491 {
2492 bindSampler(samplerIndex, 0);
2493 }
2494 }
2495 }
2496
syncTransformFeedbackState(const gl::Context * context)2497 void StateManagerGL::syncTransformFeedbackState(const gl::Context *context)
2498 {
2499 // Set the current transform feedback state
2500 gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
2501 if (transformFeedback)
2502 {
2503 TransformFeedbackGL *transformFeedbackGL =
2504 GetImplAs<TransformFeedbackGL>(transformFeedback);
2505 bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID());
2506 transformFeedbackGL->syncActiveState(context, transformFeedback->isActive(),
2507 transformFeedback->getPrimitiveMode());
2508 transformFeedbackGL->syncPausedState(transformFeedback->isPaused());
2509 mCurrentTransformFeedback = transformFeedbackGL;
2510 }
2511 else
2512 {
2513 bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
2514 mCurrentTransformFeedback = nullptr;
2515 }
2516 }
2517
getDefaultVAO() const2518 GLuint StateManagerGL::getDefaultVAO() const
2519 {
2520 return mDefaultVAO;
2521 }
2522
getDefaultVAOState()2523 VertexArrayStateGL *StateManagerGL::getDefaultVAOState()
2524 {
2525 return &mDefaultVAOState;
2526 }
2527
validateState() const2528 void StateManagerGL::validateState() const
2529 {
2530 // Current program
2531 ValidateStateHelper(mFunctions, mProgram, GL_CURRENT_PROGRAM, "mProgram", "GL_CURRENT_PROGRAM");
2532
2533 // Buffers
2534 for (gl::BufferBinding bindingType : angle::AllEnums<gl::BufferBinding>())
2535 {
2536 // These binding types need compute support to be queried
2537 if (bindingType == gl::BufferBinding::AtomicCounter ||
2538 bindingType == gl::BufferBinding::DispatchIndirect ||
2539 bindingType == gl::BufferBinding::ShaderStorage)
2540 {
2541 if (!nativegl::SupportsCompute(mFunctions))
2542 {
2543 continue;
2544 }
2545 }
2546
2547 // Transform feedback buffer bindings are tracked in TransformFeedbackGL
2548 if (bindingType == gl::BufferBinding::TransformFeedback)
2549 {
2550 continue;
2551 }
2552
2553 GLenum bindingTypeGL = nativegl::GetBufferBindingQuery(bindingType);
2554 std::string localName = "mBuffers[" + ToString(bindingType) + "]";
2555 ValidateStateHelper(mFunctions, mBuffers[bindingType], bindingTypeGL, localName.c_str(),
2556 nativegl::GetBufferBindingString(bindingType).c_str());
2557 }
2558
2559 // Vertex array object
2560 ValidateStateHelper(mFunctions, mVAO, GL_VERTEX_ARRAY_BINDING, "mVAO",
2561 "GL_VERTEX_ARRAY_BINDING");
2562 }
2563
2564 template <>
get(GLenum name,GLboolean * value)2565 void StateManagerGL::get(GLenum name, GLboolean *value)
2566 {
2567 mFunctions->getBooleanv(name, value);
2568 }
2569
2570 template <>
get(GLenum name,bool * value)2571 void StateManagerGL::get(GLenum name, bool *value)
2572 {
2573 GLboolean v;
2574 get(name, &v);
2575 *value = (v == GL_TRUE);
2576 }
2577
2578 template <>
get(GLenum name,std::array<bool,4> * values)2579 void StateManagerGL::get(GLenum name, std::array<bool, 4> *values)
2580 {
2581 GLboolean v[4];
2582 get(name, v);
2583 for (size_t i = 0; i < 4; i++)
2584 {
2585 (*values)[i] = (v[i] == GL_TRUE);
2586 }
2587 }
2588
2589 template <>
get(GLenum name,GLint * value)2590 void StateManagerGL::get(GLenum name, GLint *value)
2591 {
2592 mFunctions->getIntegerv(name, value);
2593 }
2594
2595 template <>
get(GLenum name,GLenum * value)2596 void StateManagerGL::get(GLenum name, GLenum *value)
2597 {
2598 GLint v;
2599 get(name, &v);
2600 *value = static_cast<GLenum>(v);
2601 }
2602
2603 template <>
get(GLenum name,gl::Rectangle * rect)2604 void StateManagerGL::get(GLenum name, gl::Rectangle *rect)
2605 {
2606 GLint v[4];
2607 get(name, v);
2608 *rect = gl::Rectangle(v[0], v[1], v[2], v[3]);
2609 }
2610
2611 template <>
get(GLenum name,GLfloat * value)2612 void StateManagerGL::get(GLenum name, GLfloat *value)
2613 {
2614 mFunctions->getFloatv(name, value);
2615 }
2616
2617 template <>
get(GLenum name,gl::ColorF * color)2618 void StateManagerGL::get(GLenum name, gl::ColorF *color)
2619 {
2620 GLfloat v[4];
2621 get(name, v);
2622 *color = gl::ColorF(v[0], v[1], v[2], v[3]);
2623 }
2624
syncFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)2625 void StateManagerGL::syncFromNativeContext(const gl::Extensions &extensions,
2626 ExternalContextState *state)
2627 {
2628 ASSERT(mFunctions->getError() == GL_NO_ERROR);
2629
2630 get(GL_VIEWPORT, &state->viewport);
2631 if (mViewport != state->viewport)
2632 {
2633 mViewport = state->viewport;
2634 mLocalDirtyBits.set(gl::State::DIRTY_BIT_VIEWPORT);
2635 }
2636
2637 get(GL_SCISSOR_TEST, &state->scissorTest);
2638 if (mScissorTestEnabled != static_cast<bool>(state->scissorTest))
2639 {
2640 mScissorTestEnabled = state->scissorTest;
2641 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
2642 }
2643
2644 get(GL_SCISSOR_BOX, &state->scissorBox);
2645 if (mScissor != state->scissorBox)
2646 {
2647 mScissor = state->scissorBox;
2648 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR);
2649 }
2650
2651 get(GL_DEPTH_TEST, &state->depthTest);
2652 if (mDepthTestEnabled != state->depthTest)
2653 {
2654 mDepthTestEnabled = state->depthTest;
2655 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED);
2656 }
2657
2658 get(GL_CULL_FACE, &state->cullFace);
2659 if (mCullFaceEnabled != state->cullFace)
2660 {
2661 mCullFaceEnabled = state->cullFace;
2662 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE_ENABLED);
2663 }
2664
2665 get(GL_CULL_FACE_MODE, &state->cullFaceMode);
2666 if (mCullFace != gl::FromGLenum<gl::CullFaceMode>(state->cullFaceMode))
2667 {
2668 mCullFace = gl::FromGLenum<gl::CullFaceMode>(state->cullFaceMode);
2669 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE);
2670 }
2671
2672 get(GL_COLOR_WRITEMASK, &state->colorMask);
2673 auto colorMask = mBlendStateExt.expandColorMaskValue(state->colorMask[0], state->colorMask[1],
2674 state->colorMask[2], state->colorMask[3]);
2675 if (mBlendStateExt.mColorMask != colorMask)
2676 {
2677 mBlendStateExt.mColorMask = colorMask;
2678 mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
2679 }
2680
2681 get(GL_CURRENT_PROGRAM, &state->currentProgram);
2682 if (mProgram != static_cast<GLuint>(state->currentProgram))
2683 {
2684 mProgram = state->currentProgram;
2685 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PROGRAM_BINDING);
2686 }
2687
2688 get(GL_COLOR_CLEAR_VALUE, &state->colorClear);
2689 if (mClearColor != state->colorClear)
2690 {
2691 mClearColor = state->colorClear;
2692 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_COLOR);
2693 }
2694
2695 get(GL_DEPTH_CLEAR_VALUE, &state->depthClear);
2696 if (mClearDepth != state->depthClear)
2697 {
2698 mClearDepth = state->depthClear;
2699 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_DEPTH);
2700 }
2701
2702 get(GL_DEPTH_FUNC, &state->depthFunc);
2703 if (mDepthFunc != static_cast<GLenum>(state->depthFunc))
2704 {
2705 mDepthFunc = state->depthFunc;
2706 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_FUNC);
2707 }
2708
2709 get(GL_DEPTH_WRITEMASK, &state->depthMask);
2710 if (mDepthMask != state->depthMask)
2711 {
2712 mDepthMask = state->depthMask;
2713 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_MASK);
2714 }
2715
2716 get(GL_DEPTH_RANGE, state->depthRage);
2717 if (mNear != state->depthRage[0] || mFar != state->depthRage[1])
2718 {
2719 mNear = state->depthRage[0];
2720 mFar = state->depthRage[1];
2721 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_RANGE);
2722 }
2723
2724 get(GL_FRONT_FACE, &state->frontFace);
2725 if (mFrontFace != static_cast<GLenum>(state->frontFace))
2726 {
2727 mFrontFace = state->frontFace;
2728 mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRONT_FACE);
2729 }
2730
2731 get(GL_LINE_WIDTH, &state->lineWidth);
2732 if (mLineWidth != state->lineWidth)
2733 {
2734 mLineWidth = state->lineWidth;
2735 mLocalDirtyBits.set(gl::State::DIRTY_BIT_LINE_WIDTH);
2736 }
2737
2738 get(GL_POLYGON_OFFSET_FACTOR, &state->polygonOffsetFactor);
2739 get(GL_POLYGON_OFFSET_UNITS, &state->polygonOffsetUnits);
2740 if (mPolygonOffsetFactor != state->polygonOffsetFactor ||
2741 mPolygonOffsetUnits != state->polygonOffsetUnits)
2742 {
2743 mPolygonOffsetFactor = state->polygonOffsetFactor;
2744 mPolygonOffsetUnits = state->polygonOffsetUnits;
2745 mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET);
2746 }
2747
2748 get(GL_SAMPLE_COVERAGE_VALUE, &state->sampleCoverageValue);
2749 get(GL_SAMPLE_COVERAGE_INVERT, &state->sampleCoverageInvert);
2750 if (mSampleCoverageValue != state->sampleCoverageValue ||
2751 mSampleCoverageInvert != state->sampleCoverageInvert)
2752 {
2753 mSampleCoverageValue = state->sampleCoverageValue;
2754 mSampleCoverageInvert = state->sampleCoverageInvert;
2755 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE);
2756 }
2757
2758 get(GL_DITHER, &state->enableDither);
2759 if (mDitherEnabled != state->enableDither)
2760 {
2761 mDitherEnabled = state->enableDither;
2762 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DITHER_ENABLED);
2763 }
2764
2765 get(GL_POLYGON_OFFSET_FILL, &state->enablePolygonOffsetFill);
2766 if (mPolygonOffsetFillEnabled != state->enablePolygonOffsetFill)
2767 {
2768 mPolygonOffsetFillEnabled = state->enablePolygonOffsetFill;
2769 mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
2770 }
2771
2772 get(GL_SAMPLE_ALPHA_TO_COVERAGE, &state->enableSampleAlphaToCoverage);
2773 if (mSampleAlphaToOneEnabled != state->enableSampleAlphaToCoverage)
2774 {
2775 mSampleAlphaToOneEnabled = state->enableSampleAlphaToCoverage;
2776 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
2777 }
2778
2779 get(GL_SAMPLE_COVERAGE, &state->enableSampleCoverage);
2780 if (mSampleCoverageEnabled != state->enableSampleCoverage)
2781 {
2782 mSampleCoverageEnabled = state->enableSampleCoverage;
2783 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
2784 }
2785
2786 if (extensions.multisampleCompatibilityEXT)
2787 {
2788 get(GL_MULTISAMPLE, &state->multisampleEnabled);
2789 if (mMultisamplingEnabled != state->multisampleEnabled)
2790 {
2791 mMultisamplingEnabled = state->multisampleEnabled;
2792 mLocalDirtyBits.set(gl::State::DIRTY_BIT_MULTISAMPLING);
2793 }
2794 }
2795
2796 syncBlendFromNativeContext(extensions, state);
2797 syncFramebufferFromNativeContext(extensions, state);
2798 syncPixelPackUnpackFromNativeContext(extensions, state);
2799 syncStencilFromNativeContext(extensions, state);
2800 syncVertexArraysFromNativeContext(extensions, state);
2801 syncBufferBindingsFromNativeContext(extensions, state);
2802 syncTextureUnitsFromNativeContext(extensions, state);
2803
2804 ASSERT(mFunctions->getError() == GL_NO_ERROR);
2805 }
2806
restoreNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)2807 void StateManagerGL::restoreNativeContext(const gl::Extensions &extensions,
2808 const ExternalContextState *state)
2809 {
2810 ASSERT(mFunctions->getError() == GL_NO_ERROR);
2811
2812 setViewport(state->viewport);
2813
2814 setScissorTestEnabled(state->scissorTest);
2815 setScissor(state->scissorBox);
2816
2817 setDepthTestEnabled(state->depthTest);
2818
2819 setCullFaceEnabled(state->cullFace);
2820 setCullFace(gl::FromGLenum<gl::CullFaceMode>(state->cullFaceMode));
2821
2822 setColorMask(state->colorMask[0], state->colorMask[1], state->colorMask[2],
2823 state->colorMask[3]);
2824
2825 forceUseProgram(state->currentProgram);
2826
2827 setClearColor(state->colorClear);
2828
2829 setClearDepth(state->depthClear);
2830 setDepthFunc(state->depthFunc);
2831 setDepthMask(state->depthMask);
2832 setDepthRange(state->depthRage[0], state->depthRage[1]);
2833
2834 setFrontFace(state->frontFace);
2835
2836 setLineWidth(state->lineWidth);
2837
2838 setPolygonOffset(state->polygonOffsetFactor, state->polygonOffsetUnits);
2839
2840 setSampleCoverage(state->sampleCoverageValue, state->sampleCoverageInvert);
2841
2842 setDitherEnabled(state->enableDither);
2843
2844 setPolygonOffsetFillEnabled(state->enablePolygonOffsetFill);
2845
2846 setSampleAlphaToOneStateEnabled(state->enableSampleAlphaToCoverage);
2847
2848 setSampleCoverageEnabled(state->enableSampleCoverage);
2849
2850 if (extensions.multisampleCompatibilityEXT)
2851 setMultisamplingStateEnabled(state->multisampleEnabled);
2852
2853 restoreBlendNativeContext(extensions, state);
2854 restoreFramebufferNativeContext(extensions, state);
2855 restorePixelPackUnpackNativeContext(extensions, state);
2856 restoreStencilNativeContext(extensions, state);
2857 restoreVertexArraysNativeContext(extensions, state);
2858 restoreBufferBindingsNativeContext(extensions, state);
2859 restoreTextureUnitsNativeContext(extensions, state);
2860
2861 // if (mFunctions->coverageModulationNV) ?
2862 setCoverageModulation(GL_NONE);
2863
2864 ASSERT(mFunctions->getError() == GL_NO_ERROR);
2865 }
2866
syncBlendFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)2867 void StateManagerGL::syncBlendFromNativeContext(const gl::Extensions &extensions,
2868 ExternalContextState *state)
2869 {
2870 get(GL_BLEND, &state->blendEnabled);
2871 if (mBlendStateExt.mEnabledMask !=
2872 (state->blendEnabled ? mBlendStateExt.mMaxEnabledMask : gl::DrawBufferMask::Zero()))
2873 {
2874 mBlendStateExt.setEnabled(state->blendEnabled);
2875 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
2876 }
2877
2878 get(GL_BLEND_SRC_RGB, &state->blendSrcRgb);
2879 get(GL_BLEND_DST_RGB, &state->blendDestRgb);
2880 get(GL_BLEND_SRC_ALPHA, &state->blendSrcAlpha);
2881 get(GL_BLEND_DST_ALPHA, &state->blendDestAlpha);
2882 if (mBlendStateExt.mSrcColor != static_cast<uint64_t>(state->blendSrcRgb) ||
2883 mBlendStateExt.mDstColor != static_cast<uint64_t>(state->blendDestRgb) ||
2884 mBlendStateExt.mSrcAlpha != static_cast<uint64_t>(state->blendSrcAlpha) ||
2885 mBlendStateExt.mDstAlpha != static_cast<uint64_t>(state->blendDestAlpha))
2886 {
2887 mBlendStateExt.mSrcColor = state->blendSrcRgb;
2888 mBlendStateExt.mDstColor = state->blendDestRgb;
2889 mBlendStateExt.mSrcAlpha = state->blendSrcAlpha;
2890 mBlendStateExt.mDstAlpha = state->blendDestAlpha;
2891 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);
2892 }
2893
2894 get(GL_BLEND_COLOR, &state->blendColor);
2895 if (mBlendColor != state->blendColor)
2896 {
2897 mBlendColor = state->blendColor;
2898 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_COLOR);
2899 }
2900
2901 get(GL_BLEND_EQUATION_RGB, &state->blendEquationRgb);
2902 get(GL_BLEND_EQUATION_ALPHA, &state->blendEquationAlpha);
2903 }
2904
restoreBlendNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)2905 void StateManagerGL::restoreBlendNativeContext(const gl::Extensions &extensions,
2906 const ExternalContextState *state)
2907 {
2908 setBlendEnabled(state->blendEnabled);
2909 // TODO: use setBlendFuncs()
2910 mFunctions->blendFuncSeparate(state->blendSrcRgb, state->blendDestRgb, state->blendSrcAlpha,
2911 state->blendDestAlpha);
2912 mBlendStateExt.mSrcColor = state->blendSrcRgb;
2913 mBlendStateExt.mDstColor = state->blendDestRgb;
2914 mBlendStateExt.mSrcAlpha = state->blendSrcAlpha;
2915 mBlendStateExt.mDstAlpha = state->blendDestAlpha;
2916 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);
2917
2918 setBlendColor(state->blendColor);
2919
2920 // TODO: use setBlendEquations()
2921 mFunctions->blendEquationSeparate(state->blendEquationRgb, state->blendEquationAlpha);
2922 mBlendStateExt.mEquationColor = state->blendEquationRgb;
2923 mBlendStateExt.mEquationAlpha = state->blendEquationAlpha;
2924 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_EQUATIONS);
2925 }
2926
syncFramebufferFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)2927 void StateManagerGL::syncFramebufferFromNativeContext(const gl::Extensions &extensions,
2928 ExternalContextState *state)
2929 {
2930 // TODO: wrap fbo into an EGLSurface
2931 get(GL_FRAMEBUFFER_BINDING, &state->framebufferBinding);
2932 if (mFramebuffers[angle::FramebufferBindingDraw] !=
2933 static_cast<GLenum>(state->framebufferBinding))
2934 {
2935 mFramebuffers[angle::FramebufferBindingDraw] =
2936 static_cast<GLenum>(state->framebufferBinding);
2937 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
2938 }
2939 if (mFramebuffers[angle::FramebufferBindingRead] !=
2940 static_cast<GLenum>(state->framebufferBinding))
2941 {
2942 mFramebuffers[angle::FramebufferBindingRead] =
2943 static_cast<GLenum>(state->framebufferBinding);
2944 mLocalDirtyBits.set(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
2945 }
2946 }
2947
restoreFramebufferNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)2948 void StateManagerGL::restoreFramebufferNativeContext(const gl::Extensions &extensions,
2949 const ExternalContextState *state)
2950 {
2951 bindFramebuffer(GL_FRAMEBUFFER, state->framebufferBinding);
2952 }
2953
syncPixelPackUnpackFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)2954 void StateManagerGL::syncPixelPackUnpackFromNativeContext(const gl::Extensions &extensions,
2955 ExternalContextState *state)
2956 {
2957 get(GL_PACK_ALIGNMENT, &state->packAlignment);
2958 if (mPackAlignment != state->packAlignment)
2959 {
2960 mPackAlignment = state->packAlignment;
2961 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
2962 }
2963
2964 get(GL_UNPACK_ALIGNMENT, &state->unpackAlignment);
2965 if (mUnpackAlignment != state->unpackAlignment)
2966 {
2967 mUnpackAlignment = state->unpackAlignment;
2968 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
2969 }
2970 }
2971
restorePixelPackUnpackNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)2972 void StateManagerGL::restorePixelPackUnpackNativeContext(const gl::Extensions &extensions,
2973 const ExternalContextState *state)
2974 {
2975 if (mPackAlignment != state->packAlignment)
2976 {
2977 mFunctions->pixelStorei(GL_PACK_ALIGNMENT, state->packAlignment);
2978 mPackAlignment = state->packAlignment;
2979 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
2980 }
2981
2982 if (mUnpackAlignment != state->unpackAlignment)
2983 {
2984 mFunctions->pixelStorei(GL_UNPACK_ALIGNMENT, state->unpackAlignment);
2985 mUnpackAlignment = state->unpackAlignment;
2986 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
2987 }
2988 }
2989
syncStencilFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)2990 void StateManagerGL::syncStencilFromNativeContext(const gl::Extensions &extensions,
2991 ExternalContextState *state)
2992 {
2993 get(GL_STENCIL_TEST, &state->stencilState.stencilTestEnabled);
2994 if (state->stencilState.stencilTestEnabled != mStencilTestEnabled)
2995 {
2996 mStencilTestEnabled = state->stencilState.stencilTestEnabled;
2997 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED);
2998 }
2999
3000 get(GL_STENCIL_FUNC, &state->stencilState.stencilFrontFunc);
3001 get(GL_STENCIL_VALUE_MASK, &state->stencilState.stencilFrontMask);
3002 get(GL_STENCIL_REF, &state->stencilState.stencilFrontRef);
3003 if (state->stencilState.stencilFrontFunc != mStencilFrontFunc ||
3004 state->stencilState.stencilFrontMask != mStencilFrontValueMask ||
3005 state->stencilState.stencilFrontRef != mStencilFrontRef)
3006 {
3007 mStencilFrontFunc = state->stencilState.stencilFrontFunc;
3008 mStencilFrontValueMask = state->stencilState.stencilFrontMask;
3009 mStencilFrontRef = state->stencilState.stencilFrontRef;
3010 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT);
3011 }
3012
3013 get(GL_STENCIL_BACK_FUNC, &state->stencilState.stencilBackFunc);
3014 get(GL_STENCIL_BACK_VALUE_MASK, &state->stencilState.stencilBackMask);
3015 get(GL_STENCIL_BACK_REF, &state->stencilState.stencilBackRef);
3016 if (state->stencilState.stencilBackFunc != mStencilBackFunc ||
3017 state->stencilState.stencilBackMask != mStencilBackValueMask ||
3018 state->stencilState.stencilBackRef != mStencilBackRef)
3019 {
3020 mStencilBackFunc = state->stencilState.stencilBackFunc;
3021 mStencilBackValueMask = state->stencilState.stencilBackMask;
3022 mStencilBackRef = state->stencilState.stencilBackRef;
3023 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK);
3024 }
3025
3026 get(GL_STENCIL_CLEAR_VALUE, &state->stencilState.stencilClear);
3027 if (mClearStencil != state->stencilState.stencilClear)
3028 {
3029 mClearStencil = state->stencilState.stencilClear;
3030 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_STENCIL);
3031 }
3032
3033 get(GL_STENCIL_WRITEMASK, &state->stencilState.stencilFrontWritemask);
3034 if (mStencilFrontWritemask != static_cast<GLenum>(state->stencilState.stencilFrontWritemask))
3035 {
3036 mStencilFrontWritemask = state->stencilState.stencilFrontWritemask;
3037 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
3038 }
3039
3040 get(GL_STENCIL_BACK_WRITEMASK, &state->stencilState.stencilBackWritemask);
3041 if (mStencilBackWritemask != static_cast<GLenum>(state->stencilState.stencilBackWritemask))
3042 {
3043 mStencilBackWritemask = state->stencilState.stencilBackWritemask;
3044 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
3045 }
3046
3047 get(GL_STENCIL_FAIL, &state->stencilState.stencilFrontFailOp);
3048 get(GL_STENCIL_PASS_DEPTH_FAIL, &state->stencilState.stencilFrontZFailOp);
3049 get(GL_STENCIL_PASS_DEPTH_PASS, &state->stencilState.stencilFrontZPassOp);
3050 if (mStencilFrontStencilFailOp != static_cast<GLenum>(state->stencilState.stencilFrontFailOp) ||
3051 mStencilFrontStencilPassDepthFailOp !=
3052 static_cast<GLenum>(state->stencilState.stencilFrontZFailOp) ||
3053 mStencilFrontStencilPassDepthPassOp !=
3054 static_cast<GLenum>(state->stencilState.stencilFrontZPassOp))
3055 {
3056 mStencilFrontStencilFailOp = static_cast<GLenum>(state->stencilState.stencilFrontFailOp);
3057 mStencilFrontStencilPassDepthFailOp =
3058 static_cast<GLenum>(state->stencilState.stencilFrontZFailOp);
3059 mStencilFrontStencilPassDepthPassOp =
3060 static_cast<GLenum>(state->stencilState.stencilFrontZPassOp);
3061 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_FRONT);
3062 }
3063
3064 get(GL_STENCIL_BACK_FAIL, &state->stencilState.stencilBackFailOp);
3065 get(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &state->stencilState.stencilBackZFailOp);
3066 get(GL_STENCIL_BACK_PASS_DEPTH_PASS, &state->stencilState.stencilBackZPassOp);
3067 if (mStencilBackStencilFailOp != static_cast<GLenum>(state->stencilState.stencilBackFailOp) ||
3068 mStencilBackStencilPassDepthFailOp !=
3069 static_cast<GLenum>(state->stencilState.stencilBackZFailOp) ||
3070 mStencilBackStencilPassDepthPassOp !=
3071 static_cast<GLenum>(state->stencilState.stencilBackZPassOp))
3072 {
3073 mStencilBackStencilFailOp = static_cast<GLenum>(state->stencilState.stencilBackFailOp);
3074 mStencilBackStencilPassDepthFailOp =
3075 static_cast<GLenum>(state->stencilState.stencilBackZFailOp);
3076 mStencilBackStencilPassDepthPassOp =
3077 static_cast<GLenum>(state->stencilState.stencilBackZPassOp);
3078 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_BACK);
3079 }
3080 }
3081
restoreStencilNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)3082 void StateManagerGL::restoreStencilNativeContext(const gl::Extensions &extensions,
3083 const ExternalContextState *state)
3084 {
3085 setStencilTestEnabled(state->stencilState.stencilTestEnabled);
3086 setStencilFrontFuncs(state->stencilState.stencilFrontFunc, state->stencilState.stencilFrontMask,
3087 state->stencilState.stencilFrontRef);
3088 setStencilBackFuncs(state->stencilState.stencilBackFunc, state->stencilState.stencilBackMask,
3089 state->stencilState.stencilBackRef);
3090 setClearStencil(state->stencilState.stencilClear);
3091 setStencilFrontWritemask(state->stencilState.stencilFrontWritemask);
3092 setStencilBackWritemask(state->stencilState.stencilBackWritemask);
3093 setStencilFrontOps(state->stencilState.stencilFrontFailOp,
3094 state->stencilState.stencilFrontZFailOp,
3095 state->stencilState.stencilFrontZPassOp);
3096 setStencilBackOps(state->stencilState.stencilBackFailOp, state->stencilState.stencilBackZFailOp,
3097 state->stencilState.stencilBackZPassOp);
3098 }
3099
syncBufferBindingsFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)3100 void StateManagerGL::syncBufferBindingsFromNativeContext(const gl::Extensions &extensions,
3101 ExternalContextState *state)
3102 {
3103 get(GL_ARRAY_BUFFER_BINDING, &state->vertexArrayBufferBinding);
3104 mBuffers[gl::BufferBinding::Array] = state->vertexArrayBufferBinding;
3105
3106 get(GL_ELEMENT_ARRAY_BUFFER_BINDING, &state->elementArrayBufferBinding);
3107 mBuffers[gl::BufferBinding::ElementArray] = state->elementArrayBufferBinding;
3108 }
3109
restoreBufferBindingsNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)3110 void StateManagerGL::restoreBufferBindingsNativeContext(const gl::Extensions &extensions,
3111 const ExternalContextState *state)
3112 {
3113 bindBuffer(gl::BufferBinding::Array, state->vertexArrayBufferBinding);
3114 bindBuffer(gl::BufferBinding::ElementArray, state->elementArrayBufferBinding);
3115 }
3116
syncTextureUnitsFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)3117 void StateManagerGL::syncTextureUnitsFromNativeContext(const gl::Extensions &extensions,
3118 ExternalContextState *state)
3119 {
3120 get(GL_ACTIVE_TEXTURE, &state->activeTexture);
3121
3122 for (size_t i = 0; i < state->textureBindings.size(); ++i)
3123 {
3124 auto &bindings = state->textureBindings[i];
3125 activeTexture(i);
3126 get(GL_TEXTURE_BINDING_2D, &bindings.texture2d);
3127 get(GL_TEXTURE_BINDING_CUBE_MAP, &bindings.textureCubeMap);
3128 get(GL_TEXTURE_BINDING_EXTERNAL_OES, &bindings.textureExternalOES);
3129 if (mTextures[gl::TextureType::_2D][i] != static_cast<GLuint>(bindings.texture2d) ||
3130 mTextures[gl::TextureType::CubeMap][i] !=
3131 static_cast<GLuint>(bindings.textureCubeMap) ||
3132 mTextures[gl::TextureType::External][i] !=
3133 static_cast<GLuint>(bindings.textureExternalOES))
3134 {
3135 mTextures[gl::TextureType::_2D][i] = bindings.texture2d;
3136 mTextures[gl::TextureType::CubeMap][i] = bindings.textureCubeMap;
3137 mTextures[gl::TextureType::External][i] = bindings.textureExternalOES;
3138 mLocalDirtyBits.set(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
3139 }
3140 }
3141 }
3142
restoreTextureUnitsNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)3143 void StateManagerGL::restoreTextureUnitsNativeContext(const gl::Extensions &extensions,
3144 const ExternalContextState *state)
3145 {
3146 for (size_t i = 0; i < state->textureBindings.size(); ++i)
3147 {
3148 const auto &bindings = state->textureBindings[i];
3149 activeTexture(i);
3150 bindTexture(gl::TextureType::_2D, bindings.texture2d);
3151 bindTexture(gl::TextureType::CubeMap, bindings.textureCubeMap);
3152 bindTexture(gl::TextureType::External, bindings.textureExternalOES);
3153 bindSampler(i, 0);
3154 }
3155 activeTexture(state->activeTexture - GL_TEXTURE0);
3156 }
3157
syncVertexArraysFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)3158 void StateManagerGL::syncVertexArraysFromNativeContext(const gl::Extensions &extensions,
3159 ExternalContextState *state)
3160 {
3161 get(GL_VERTEX_ARRAY_BINDING, &state->vertexArrayBinding);
3162 if (mVAO != static_cast<GLuint>(state->vertexArrayBinding))
3163 {
3164 mVAO = state->vertexArrayBinding;
3165 mBuffers[gl::BufferBinding::ElementArray] = 0;
3166 mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
3167 }
3168 }
3169
restoreVertexArraysNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)3170 void StateManagerGL::restoreVertexArraysNativeContext(const gl::Extensions &extensions,
3171 const ExternalContextState *state)
3172 {
3173 bindVertexArray(state->vertexArrayBinding, 0);
3174 }
3175
setDefaultVAOStateDirty()3176 void StateManagerGL::setDefaultVAOStateDirty()
3177 {
3178 mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
3179 }
3180
3181 } // namespace rx
3182