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