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::Program *program = glState.getProgram();
1011
1012 for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
1013 blockIndex++)
1014 {
1015 GLuint binding = program->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 state
1038 const gl::State &glState = context->getState();
1039 const gl::Program *program = glState.getProgram();
1040
1041 for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
1042 uniformBlockIndex++)
1043 {
1044 GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
1045 const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding);
1046
1047 if (uniformBuffer.get() != nullptr)
1048 {
1049 BufferGL *bufferGL = GetImplAs<BufferGL>(uniformBuffer.get());
1050
1051 if (uniformBuffer.getSize() == 0)
1052 {
1053 bindBufferBase(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID());
1054 }
1055 else
1056 {
1057 bindBufferRange(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID(),
1058 uniformBuffer.getOffset(), uniformBuffer.getSize());
1059 }
1060 }
1061 }
1062 }
1063
updateProgramAtomicCounterBufferBindings(const gl::Context * context)1064 void StateManagerGL::updateProgramAtomicCounterBufferBindings(const gl::Context *context)
1065 {
1066 const gl::State &glState = context->getState();
1067 const gl::Program *program = glState.getProgram();
1068
1069 for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
1070 {
1071 GLuint binding = atomicCounterBuffer.binding;
1072 const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
1073
1074 if (buffer.get() != nullptr)
1075 {
1076 BufferGL *bufferGL = GetImplAs<BufferGL>(buffer.get());
1077
1078 if (buffer.getSize() == 0)
1079 {
1080 bindBufferBase(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID());
1081 }
1082 else
1083 {
1084 bindBufferRange(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID(),
1085 buffer.getOffset(), buffer.getSize());
1086 }
1087 }
1088 }
1089 }
1090
updateProgramImageBindings(const gl::Context * context)1091 void StateManagerGL::updateProgramImageBindings(const gl::Context *context)
1092 {
1093 const gl::State &glState = context->getState();
1094 const gl::ProgramExecutable *executable = glState.getProgramExecutable();
1095 const gl::Program *program = glState.getProgram();
1096
1097 // It is possible there is no active program during a path operation.
1098 if (!executable || !program)
1099 return;
1100
1101 ASSERT(context->getClientVersion() >= gl::ES_3_1 ||
1102 context->getExtensions().shaderPixelLocalStorageANGLE ||
1103 program->getImageBindings().empty());
1104 for (size_t imageUnitIndex : executable->getActiveImagesMask())
1105 {
1106 const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
1107 const TextureGL *textureGL = SafeGetImplAs<TextureGL>(imageUnit.texture.get());
1108 if (textureGL)
1109 {
1110 bindImageTexture(imageUnitIndex, textureGL->getTextureID(), imageUnit.level,
1111 imageUnit.layered, imageUnit.layer, imageUnit.access,
1112 imageUnit.format);
1113 }
1114 else
1115 {
1116 bindImageTexture(imageUnitIndex, 0, imageUnit.level, imageUnit.layered, imageUnit.layer,
1117 imageUnit.access, imageUnit.format);
1118 }
1119 }
1120 }
1121
setAttributeCurrentData(size_t index,const gl::VertexAttribCurrentValueData & data)1122 void StateManagerGL::setAttributeCurrentData(size_t index,
1123 const gl::VertexAttribCurrentValueData &data)
1124 {
1125 if (mVertexAttribCurrentValues[index] != data)
1126 {
1127 mVertexAttribCurrentValues[index] = data;
1128 switch (mVertexAttribCurrentValues[index].Type)
1129 {
1130 case gl::VertexAttribType::Float:
1131 mFunctions->vertexAttrib4fv(static_cast<GLuint>(index),
1132 mVertexAttribCurrentValues[index].Values.FloatValues);
1133 break;
1134 case gl::VertexAttribType::Int:
1135 mFunctions->vertexAttribI4iv(static_cast<GLuint>(index),
1136 mVertexAttribCurrentValues[index].Values.IntValues);
1137 break;
1138 case gl::VertexAttribType::UnsignedInt:
1139 mFunctions->vertexAttribI4uiv(
1140 static_cast<GLuint>(index),
1141 mVertexAttribCurrentValues[index].Values.UnsignedIntValues);
1142 break;
1143 default:
1144 UNREACHABLE();
1145 }
1146
1147 mLocalDirtyBits.set(gl::state::DIRTY_BIT_CURRENT_VALUES);
1148 mLocalDirtyCurrentValues.set(index);
1149 }
1150 }
1151
setScissorTestEnabled(bool enabled)1152 void StateManagerGL::setScissorTestEnabled(bool enabled)
1153 {
1154 if (mScissorTestEnabled != enabled)
1155 {
1156 mScissorTestEnabled = enabled;
1157 if (mScissorTestEnabled)
1158 {
1159 mFunctions->enable(GL_SCISSOR_TEST);
1160 }
1161 else
1162 {
1163 mFunctions->disable(GL_SCISSOR_TEST);
1164 }
1165
1166 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SCISSOR_TEST_ENABLED);
1167 }
1168 }
1169
setScissor(const gl::Rectangle & scissor)1170 void StateManagerGL::setScissor(const gl::Rectangle &scissor)
1171 {
1172 if (scissor != mScissor)
1173 {
1174 mScissor = scissor;
1175 mFunctions->scissor(mScissor.x, mScissor.y, mScissor.width, mScissor.height);
1176
1177 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SCISSOR);
1178 }
1179 }
1180
setViewport(const gl::Rectangle & viewport)1181 void StateManagerGL::setViewport(const gl::Rectangle &viewport)
1182 {
1183 if (viewport != mViewport)
1184 {
1185 mViewport = viewport;
1186 mFunctions->viewport(mViewport.x, mViewport.y, mViewport.width, mViewport.height);
1187
1188 mLocalDirtyBits.set(gl::state::DIRTY_BIT_VIEWPORT);
1189 }
1190 }
1191
setDepthRange(float near,float far)1192 void StateManagerGL::setDepthRange(float near, float far)
1193 {
1194 mNear = near;
1195 mFar = far;
1196
1197 // The glDepthRangef function isn't available until OpenGL 4.1. Prefer it when it is
1198 // available because OpenGL ES only works in floats.
1199 if (mFunctions->depthRangef)
1200 {
1201 mFunctions->depthRangef(mNear, mFar);
1202 }
1203 else
1204 {
1205 ASSERT(mFunctions->depthRange);
1206 mFunctions->depthRange(mNear, mFar);
1207 }
1208
1209 mLocalDirtyBits.set(gl::state::DIRTY_BIT_DEPTH_RANGE);
1210 }
1211
setClipControl(gl::ClipOrigin origin,gl::ClipDepthMode depth)1212 void StateManagerGL::setClipControl(gl::ClipOrigin origin, gl::ClipDepthMode depth)
1213 {
1214 if (mClipOrigin == origin && mClipDepthMode == depth)
1215 {
1216 return;
1217 }
1218
1219 mClipOrigin = origin;
1220 mClipDepthMode = depth;
1221
1222 ASSERT(mFunctions->clipControl);
1223 mFunctions->clipControl(ToGLenum(mClipOrigin), ToGLenum(mClipDepthMode));
1224
1225 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
1226 mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_CLIP_CONTROL);
1227 }
1228
setBlendEnabled(bool enabled)1229 void StateManagerGL::setBlendEnabled(bool enabled)
1230 {
1231 const gl::DrawBufferMask mask =
1232 enabled ? mBlendStateExt.getAllEnabledMask() : gl::DrawBufferMask::Zero();
1233 if (mBlendStateExt.getEnabledMask() == mask)
1234 {
1235 return;
1236 }
1237
1238 if (enabled)
1239 {
1240 mFunctions->enable(GL_BLEND);
1241 }
1242 else
1243 {
1244 mFunctions->disable(GL_BLEND);
1245 }
1246
1247 mBlendStateExt.setEnabled(enabled);
1248 mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_ENABLED);
1249 }
1250
setBlendEnabledIndexed(const gl::DrawBufferMask enabledMask)1251 void StateManagerGL::setBlendEnabledIndexed(const gl::DrawBufferMask enabledMask)
1252 {
1253 if (mBlendStateExt.getEnabledMask() == enabledMask)
1254 {
1255 return;
1256 }
1257
1258 // Get DrawBufferMask of buffers with different blend enable state
1259 gl::DrawBufferMask diffMask = mBlendStateExt.getEnabledMask() ^ enabledMask;
1260 const size_t diffCount = diffMask.count();
1261
1262 // Check if enabling or disabling blending for all buffers reduces the number of subsequent
1263 // indexed commands. Implicitly handles the case when the new blend enable state is the same for
1264 // all buffers.
1265 if (diffCount > 1)
1266 {
1267 // The number of indexed blend enable commands in case a mass disable is used.
1268 const size_t enabledCount = enabledMask.count();
1269
1270 // The mask and the number of indexed blend disable commands in case a mass enable is used.
1271 const gl::DrawBufferMask disabledMask = enabledMask ^ mBlendStateExt.getAllEnabledMask();
1272 const size_t disabledCount = disabledMask.count();
1273
1274 if (enabledCount < diffCount && enabledCount <= disabledCount)
1275 {
1276 diffMask = enabledMask;
1277 mFunctions->disable(GL_BLEND);
1278 }
1279 else if (disabledCount < diffCount && disabledCount <= enabledCount)
1280 {
1281 diffMask = disabledMask;
1282 mFunctions->enable(GL_BLEND);
1283 }
1284 }
1285
1286 for (size_t drawBufferIndex : diffMask)
1287 {
1288 if (enabledMask.test(drawBufferIndex))
1289 {
1290 mFunctions->enablei(GL_BLEND, static_cast<GLuint>(drawBufferIndex));
1291 }
1292 else
1293 {
1294 mFunctions->disablei(GL_BLEND, static_cast<GLuint>(drawBufferIndex));
1295 }
1296 }
1297
1298 mBlendStateExt.setEnabledMask(enabledMask);
1299 mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_ENABLED);
1300 }
1301
setBlendColor(const gl::ColorF & blendColor)1302 void StateManagerGL::setBlendColor(const gl::ColorF &blendColor)
1303 {
1304 if (mBlendColor != blendColor)
1305 {
1306 mBlendColor = blendColor;
1307 mFunctions->blendColor(mBlendColor.red, mBlendColor.green, mBlendColor.blue,
1308 mBlendColor.alpha);
1309
1310 mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_COLOR);
1311 }
1312 }
1313
setBlendFuncs(const gl::BlendStateExt & blendStateExt)1314 void StateManagerGL::setBlendFuncs(const gl::BlendStateExt &blendStateExt)
1315 {
1316 if (mBlendStateExt.getSrcColorBits() == blendStateExt.getSrcColorBits() &&
1317 mBlendStateExt.getDstColorBits() == blendStateExt.getDstColorBits() &&
1318 mBlendStateExt.getSrcAlphaBits() == blendStateExt.getSrcAlphaBits() &&
1319 mBlendStateExt.getDstAlphaBits() == blendStateExt.getDstAlphaBits())
1320 {
1321 return;
1322 }
1323
1324 if (!mIndependentBlendStates)
1325 {
1326 mFunctions->blendFuncSeparate(
1327 blendStateExt.getSrcColorIndexed(0), blendStateExt.getDstColorIndexed(0),
1328 blendStateExt.getSrcAlphaIndexed(0), blendStateExt.getDstAlphaIndexed(0));
1329 }
1330 else
1331 {
1332 // Get DrawBufferMask of buffers with different blend factors
1333 gl::DrawBufferMask diffMask = mBlendStateExt.compareFactors(blendStateExt);
1334 size_t diffCount = diffMask.count();
1335
1336 // Check if setting all buffers to the same value reduces the number of subsequent indexed
1337 // commands. Implicitly handles the case when the new blend function state is the same for
1338 // all buffers.
1339 if (diffCount > 1)
1340 {
1341 bool found = false;
1342 gl::BlendStateExt::FactorStorage::Type commonSrcColor = 0;
1343 gl::BlendStateExt::FactorStorage::Type commonDstColor = 0;
1344 gl::BlendStateExt::FactorStorage::Type commonSrcAlpha = 0;
1345 gl::BlendStateExt::FactorStorage::Type commonDstAlpha = 0;
1346 for (size_t i = 0; i < mBlendStateExt.getDrawBufferCount() - 1; i++)
1347 {
1348 const gl::BlendStateExt::FactorStorage::Type tempCommonSrcColor =
1349 blendStateExt.expandSrcColorIndexed(i);
1350 const gl::BlendStateExt::FactorStorage::Type tempCommonDstColor =
1351 blendStateExt.expandDstColorIndexed(i);
1352 const gl::BlendStateExt::FactorStorage::Type tempCommonSrcAlpha =
1353 blendStateExt.expandSrcAlphaIndexed(i);
1354 const gl::BlendStateExt::FactorStorage::Type tempCommonDstAlpha =
1355 blendStateExt.expandDstAlphaIndexed(i);
1356
1357 const gl::DrawBufferMask tempDiffMask = blendStateExt.compareFactors(
1358 tempCommonSrcColor, tempCommonDstColor, tempCommonSrcAlpha, tempCommonDstAlpha);
1359
1360 const size_t tempDiffCount = tempDiffMask.count();
1361 if (tempDiffCount < diffCount)
1362 {
1363 found = true;
1364 diffMask = tempDiffMask;
1365 diffCount = tempDiffCount;
1366 commonSrcColor = tempCommonSrcColor;
1367 commonDstColor = tempCommonDstColor;
1368 commonSrcAlpha = tempCommonSrcAlpha;
1369 commonDstAlpha = tempCommonDstAlpha;
1370 if (tempDiffCount == 0)
1371 {
1372 break; // the blend factors are the same for all buffers
1373 }
1374 }
1375 }
1376 if (found)
1377 {
1378 mFunctions->blendFuncSeparate(
1379 ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonSrcColor)),
1380 ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonDstColor)),
1381 ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonSrcAlpha)),
1382 ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonDstAlpha)));
1383 }
1384 }
1385
1386 for (size_t drawBufferIndex : diffMask)
1387 {
1388 mFunctions->blendFuncSeparatei(static_cast<GLuint>(drawBufferIndex),
1389 blendStateExt.getSrcColorIndexed(drawBufferIndex),
1390 blendStateExt.getDstColorIndexed(drawBufferIndex),
1391 blendStateExt.getSrcAlphaIndexed(drawBufferIndex),
1392 blendStateExt.getDstAlphaIndexed(drawBufferIndex));
1393 }
1394 }
1395 mBlendStateExt.setSrcColorBits(blendStateExt.getSrcColorBits());
1396 mBlendStateExt.setDstColorBits(blendStateExt.getDstColorBits());
1397 mBlendStateExt.setSrcAlphaBits(blendStateExt.getSrcAlphaBits());
1398 mBlendStateExt.setDstAlphaBits(blendStateExt.getDstAlphaBits());
1399 mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_FUNCS);
1400 }
1401
setBlendEquations(const gl::BlendStateExt & blendStateExt)1402 void StateManagerGL::setBlendEquations(const gl::BlendStateExt &blendStateExt)
1403 {
1404 if (mBlendStateExt.getEquationColorBits() == blendStateExt.getEquationColorBits() &&
1405 mBlendStateExt.getEquationAlphaBits() == blendStateExt.getEquationAlphaBits())
1406 {
1407 return;
1408 }
1409
1410 if (!mIndependentBlendStates)
1411 {
1412 mFunctions->blendEquationSeparate(blendStateExt.getEquationColorIndexed(0),
1413 blendStateExt.getEquationAlphaIndexed(0));
1414 }
1415 else
1416 {
1417 // Get DrawBufferMask of buffers with different blend equations
1418 gl::DrawBufferMask diffMask = mBlendStateExt.compareEquations(blendStateExt);
1419 size_t diffCount = diffMask.count();
1420
1421 // Check if setting all buffers to the same value reduces the number of subsequent indexed
1422 // commands. Implicitly handles the case when the new blend equation state is the same for
1423 // all buffers.
1424 if (diffCount > 1)
1425 {
1426 bool found = false;
1427 gl::BlendStateExt::EquationStorage::Type commonEquationColor = 0;
1428 gl::BlendStateExt::EquationStorage::Type commonEquationAlpha = 0;
1429 for (size_t i = 0; i < mBlendStateExt.getDrawBufferCount() - 1; i++)
1430 {
1431 const gl::BlendStateExt::EquationStorage::Type tempCommonEquationColor =
1432 blendStateExt.expandEquationColorIndexed(i);
1433 const gl::BlendStateExt::EquationStorage::Type tempCommonEquationAlpha =
1434 blendStateExt.expandEquationAlphaIndexed(i);
1435
1436 const gl::DrawBufferMask tempDiffMask = blendStateExt.compareEquations(
1437 tempCommonEquationColor, tempCommonEquationAlpha);
1438
1439 const size_t tempDiffCount = tempDiffMask.count();
1440 if (tempDiffCount < diffCount)
1441 {
1442 found = true;
1443 diffMask = tempDiffMask;
1444 diffCount = tempDiffCount;
1445 commonEquationColor = tempCommonEquationColor;
1446 commonEquationAlpha = tempCommonEquationAlpha;
1447 if (tempDiffCount == 0)
1448 {
1449 break; // the new blend equations are the same for all buffers
1450 }
1451 }
1452 }
1453 if (found)
1454 {
1455 mFunctions->blendEquationSeparate(
1456 ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
1457 0, commonEquationColor)),
1458 ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
1459 0, commonEquationAlpha)));
1460 }
1461 }
1462
1463 for (size_t drawBufferIndex : diffMask)
1464 {
1465 mFunctions->blendEquationSeparatei(
1466 static_cast<GLuint>(drawBufferIndex),
1467 blendStateExt.getEquationColorIndexed(drawBufferIndex),
1468 blendStateExt.getEquationAlphaIndexed(drawBufferIndex));
1469 }
1470 }
1471 mBlendStateExt.setEquationColorBits(blendStateExt.getEquationColorBits());
1472 mBlendStateExt.setEquationAlphaBits(blendStateExt.getEquationAlphaBits());
1473 mLocalDirtyBits.set(gl::state::DIRTY_BIT_COLOR_MASK);
1474 }
1475
setColorMask(bool red,bool green,bool blue,bool alpha)1476 void StateManagerGL::setColorMask(bool red, bool green, bool blue, bool alpha)
1477 {
1478 const gl::BlendStateExt::ColorMaskStorage::Type mask =
1479 mBlendStateExt.expandColorMaskValue(red, green, blue, alpha);
1480 if (mBlendStateExt.getColorMaskBits() != mask)
1481 {
1482 mFunctions->colorMask(red, green, blue, alpha);
1483 mBlendStateExt.setColorMaskBits(mask);
1484 mLocalDirtyBits.set(gl::state::DIRTY_BIT_COLOR_MASK);
1485 }
1486 }
1487
setSampleAlphaToCoverageEnabled(bool enabled)1488 void StateManagerGL::setSampleAlphaToCoverageEnabled(bool enabled)
1489 {
1490 if (mSampleAlphaToCoverageEnabled != enabled)
1491 {
1492 mSampleAlphaToCoverageEnabled = enabled;
1493 if (mSampleAlphaToCoverageEnabled)
1494 {
1495 mFunctions->enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
1496 }
1497 else
1498 {
1499 mFunctions->disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
1500 }
1501
1502 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
1503 }
1504 }
1505
setSampleCoverageEnabled(bool enabled)1506 void StateManagerGL::setSampleCoverageEnabled(bool enabled)
1507 {
1508 if (mSampleCoverageEnabled != enabled)
1509 {
1510 mSampleCoverageEnabled = enabled;
1511 if (mSampleCoverageEnabled)
1512 {
1513 mFunctions->enable(GL_SAMPLE_COVERAGE);
1514 }
1515 else
1516 {
1517 mFunctions->disable(GL_SAMPLE_COVERAGE);
1518 }
1519
1520 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
1521 }
1522 }
1523
setSampleCoverage(float value,bool invert)1524 void StateManagerGL::setSampleCoverage(float value, bool invert)
1525 {
1526 if (mSampleCoverageValue != value || mSampleCoverageInvert != invert)
1527 {
1528 mSampleCoverageValue = value;
1529 mSampleCoverageInvert = invert;
1530 mFunctions->sampleCoverage(mSampleCoverageValue, mSampleCoverageInvert);
1531
1532 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_COVERAGE);
1533 }
1534 }
1535
setSampleMaskEnabled(bool enabled)1536 void StateManagerGL::setSampleMaskEnabled(bool enabled)
1537 {
1538 if (mSampleMaskEnabled != enabled)
1539 {
1540 mSampleMaskEnabled = enabled;
1541 if (mSampleMaskEnabled)
1542 {
1543 mFunctions->enable(GL_SAMPLE_MASK);
1544 }
1545 else
1546 {
1547 mFunctions->disable(GL_SAMPLE_MASK);
1548 }
1549
1550 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_MASK_ENABLED);
1551 }
1552 }
1553
setSampleMaski(GLuint maskNumber,GLbitfield mask)1554 void StateManagerGL::setSampleMaski(GLuint maskNumber, GLbitfield mask)
1555 {
1556 ASSERT(maskNumber < mSampleMaskValues.size());
1557 if (mSampleMaskValues[maskNumber] != mask)
1558 {
1559 mSampleMaskValues[maskNumber] = mask;
1560 mFunctions->sampleMaski(maskNumber, mask);
1561
1562 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_MASK);
1563 }
1564 }
1565
1566 // Depth and stencil redundant state changes are guarded in the
1567 // frontend so for related cases here just set the dirty bit
1568 // and update backend states.
setDepthTestEnabled(bool enabled)1569 void StateManagerGL::setDepthTestEnabled(bool enabled)
1570 {
1571 mDepthTestEnabled = enabled;
1572 if (mDepthTestEnabled)
1573 {
1574 mFunctions->enable(GL_DEPTH_TEST);
1575 }
1576 else
1577 {
1578 mFunctions->disable(GL_DEPTH_TEST);
1579 }
1580
1581 mLocalDirtyBits.set(gl::state::DIRTY_BIT_DEPTH_TEST_ENABLED);
1582 }
1583
setDepthFunc(GLenum depthFunc)1584 void StateManagerGL::setDepthFunc(GLenum depthFunc)
1585 {
1586 mDepthFunc = depthFunc;
1587 mFunctions->depthFunc(mDepthFunc);
1588
1589 mLocalDirtyBits.set(gl::state::DIRTY_BIT_DEPTH_FUNC);
1590 }
1591
setDepthMask(bool mask)1592 void StateManagerGL::setDepthMask(bool mask)
1593 {
1594 mDepthMask = mask;
1595 mFunctions->depthMask(mDepthMask);
1596
1597 mLocalDirtyBits.set(gl::state::DIRTY_BIT_DEPTH_MASK);
1598 }
1599
setStencilTestEnabled(bool enabled)1600 void StateManagerGL::setStencilTestEnabled(bool enabled)
1601 {
1602 mStencilTestEnabled = enabled;
1603 if (mStencilTestEnabled)
1604 {
1605 mFunctions->enable(GL_STENCIL_TEST);
1606 }
1607 else
1608 {
1609 mFunctions->disable(GL_STENCIL_TEST);
1610 }
1611
1612 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_TEST_ENABLED);
1613 }
1614
setStencilFrontWritemask(GLuint mask)1615 void StateManagerGL::setStencilFrontWritemask(GLuint mask)
1616 {
1617 mStencilFrontWritemask = mask;
1618 mFunctions->stencilMaskSeparate(GL_FRONT, mStencilFrontWritemask);
1619
1620 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
1621 }
1622
setStencilBackWritemask(GLuint mask)1623 void StateManagerGL::setStencilBackWritemask(GLuint mask)
1624 {
1625 mStencilBackWritemask = mask;
1626 mFunctions->stencilMaskSeparate(GL_BACK, mStencilBackWritemask);
1627
1628 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
1629 }
1630
setStencilFrontFuncs(GLenum func,GLint ref,GLuint mask)1631 void StateManagerGL::setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask)
1632 {
1633 mStencilFrontFunc = func;
1634 mStencilFrontRef = ref;
1635 mStencilFrontValueMask = mask;
1636 mFunctions->stencilFuncSeparate(GL_FRONT, mStencilFrontFunc, mStencilFrontRef,
1637 mStencilFrontValueMask);
1638
1639 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT);
1640 }
1641
setStencilBackFuncs(GLenum func,GLint ref,GLuint mask)1642 void StateManagerGL::setStencilBackFuncs(GLenum func, GLint ref, GLuint mask)
1643 {
1644 mStencilBackFunc = func;
1645 mStencilBackRef = ref;
1646 mStencilBackValueMask = mask;
1647 mFunctions->stencilFuncSeparate(GL_BACK, mStencilBackFunc, mStencilBackRef,
1648 mStencilBackValueMask);
1649
1650 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK);
1651 }
1652
setStencilFrontOps(GLenum sfail,GLenum dpfail,GLenum dppass)1653 void StateManagerGL::setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass)
1654 {
1655 mStencilFrontStencilFailOp = sfail;
1656 mStencilFrontStencilPassDepthFailOp = dpfail;
1657 mStencilFrontStencilPassDepthPassOp = dppass;
1658 mFunctions->stencilOpSeparate(GL_FRONT, mStencilFrontStencilFailOp,
1659 mStencilFrontStencilPassDepthFailOp,
1660 mStencilFrontStencilPassDepthPassOp);
1661
1662 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_OPS_FRONT);
1663 }
1664
setStencilBackOps(GLenum sfail,GLenum dpfail,GLenum dppass)1665 void StateManagerGL::setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass)
1666 {
1667 mStencilBackStencilFailOp = sfail;
1668 mStencilBackStencilPassDepthFailOp = dpfail;
1669 mStencilBackStencilPassDepthPassOp = dppass;
1670 mFunctions->stencilOpSeparate(GL_BACK, mStencilBackStencilFailOp,
1671 mStencilBackStencilPassDepthFailOp,
1672 mStencilBackStencilPassDepthPassOp);
1673
1674 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_OPS_BACK);
1675 }
1676
setCullFaceEnabled(bool enabled)1677 void StateManagerGL::setCullFaceEnabled(bool enabled)
1678 {
1679 if (mCullFaceEnabled != enabled)
1680 {
1681 mCullFaceEnabled = enabled;
1682 if (mCullFaceEnabled)
1683 {
1684 mFunctions->enable(GL_CULL_FACE);
1685 }
1686 else
1687 {
1688 mFunctions->disable(GL_CULL_FACE);
1689 }
1690
1691 mLocalDirtyBits.set(gl::state::DIRTY_BIT_CULL_FACE_ENABLED);
1692 }
1693 }
1694
setCullFace(gl::CullFaceMode cullFace)1695 void StateManagerGL::setCullFace(gl::CullFaceMode cullFace)
1696 {
1697 if (mCullFace != cullFace)
1698 {
1699 mCullFace = cullFace;
1700 mFunctions->cullFace(ToGLenum(mCullFace));
1701
1702 mLocalDirtyBits.set(gl::state::DIRTY_BIT_CULL_FACE);
1703 }
1704 }
1705
setFrontFace(GLenum frontFace)1706 void StateManagerGL::setFrontFace(GLenum frontFace)
1707 {
1708 if (mFrontFace != frontFace)
1709 {
1710 mFrontFace = frontFace;
1711 mFunctions->frontFace(mFrontFace);
1712
1713 mLocalDirtyBits.set(gl::state::DIRTY_BIT_FRONT_FACE);
1714 }
1715 }
1716
setPolygonMode(gl::PolygonMode mode)1717 void StateManagerGL::setPolygonMode(gl::PolygonMode mode)
1718 {
1719 if (mPolygonMode != mode)
1720 {
1721 mPolygonMode = mode;
1722 if (mFunctions->standard == STANDARD_GL_DESKTOP)
1723 {
1724 mFunctions->polygonMode(GL_FRONT_AND_BACK, ToGLenum(mPolygonMode));
1725 }
1726 else
1727 {
1728 ASSERT(mFunctions->polygonModeNV);
1729 mFunctions->polygonModeNV(GL_FRONT_AND_BACK, ToGLenum(mPolygonMode));
1730 }
1731
1732 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
1733 mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE);
1734 }
1735 }
1736
setPolygonOffsetPointEnabled(bool enabled)1737 void StateManagerGL::setPolygonOffsetPointEnabled(bool enabled)
1738 {
1739 if (mPolygonOffsetPointEnabled != enabled)
1740 {
1741 mPolygonOffsetPointEnabled = enabled;
1742 if (mPolygonOffsetPointEnabled)
1743 {
1744 mFunctions->enable(GL_POLYGON_OFFSET_POINT_NV);
1745 }
1746 else
1747 {
1748 mFunctions->disable(GL_POLYGON_OFFSET_POINT_NV);
1749 }
1750
1751 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
1752 mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_POINT_ENABLED);
1753 }
1754 }
1755
setPolygonOffsetLineEnabled(bool enabled)1756 void StateManagerGL::setPolygonOffsetLineEnabled(bool enabled)
1757 {
1758 if (mPolygonOffsetLineEnabled != enabled)
1759 {
1760 mPolygonOffsetLineEnabled = enabled;
1761 if (mPolygonOffsetLineEnabled)
1762 {
1763 mFunctions->enable(GL_POLYGON_OFFSET_LINE_NV);
1764 }
1765 else
1766 {
1767 mFunctions->disable(GL_POLYGON_OFFSET_LINE_NV);
1768 }
1769
1770 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
1771 mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED);
1772 }
1773 }
1774
setPolygonOffsetFillEnabled(bool enabled)1775 void StateManagerGL::setPolygonOffsetFillEnabled(bool enabled)
1776 {
1777 if (mPolygonOffsetFillEnabled != enabled)
1778 {
1779 mPolygonOffsetFillEnabled = enabled;
1780 if (mPolygonOffsetFillEnabled)
1781 {
1782 mFunctions->enable(GL_POLYGON_OFFSET_FILL);
1783 }
1784 else
1785 {
1786 mFunctions->disable(GL_POLYGON_OFFSET_FILL);
1787 }
1788
1789 mLocalDirtyBits.set(gl::state::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
1790 }
1791 }
1792
setPolygonOffset(float factor,float units,float clamp)1793 void StateManagerGL::setPolygonOffset(float factor, float units, float clamp)
1794 {
1795 if (mPolygonOffsetFactor != factor || mPolygonOffsetUnits != units ||
1796 mPolygonOffsetClamp != clamp)
1797 {
1798 mPolygonOffsetFactor = factor;
1799 mPolygonOffsetUnits = units;
1800 mPolygonOffsetClamp = clamp;
1801
1802 if (clamp == 0.0f)
1803 {
1804 mFunctions->polygonOffset(mPolygonOffsetFactor, mPolygonOffsetUnits);
1805 }
1806 else
1807 {
1808 ASSERT(mFunctions->polygonOffsetClampEXT);
1809 mFunctions->polygonOffsetClampEXT(mPolygonOffsetFactor, mPolygonOffsetUnits,
1810 mPolygonOffsetClamp);
1811 }
1812
1813 mLocalDirtyBits.set(gl::state::DIRTY_BIT_POLYGON_OFFSET);
1814 }
1815 }
1816
setDepthClampEnabled(bool enabled)1817 void StateManagerGL::setDepthClampEnabled(bool enabled)
1818 {
1819 if (mDepthClampEnabled != enabled)
1820 {
1821 mDepthClampEnabled = enabled;
1822 if (mDepthClampEnabled)
1823 {
1824 mFunctions->enable(GL_DEPTH_CLAMP_EXT);
1825 }
1826 else
1827 {
1828 mFunctions->disable(GL_DEPTH_CLAMP_EXT);
1829 }
1830
1831 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
1832 mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED);
1833 }
1834 }
1835
setRasterizerDiscardEnabled(bool enabled)1836 void StateManagerGL::setRasterizerDiscardEnabled(bool enabled)
1837 {
1838 if (mRasterizerDiscardEnabled != enabled)
1839 {
1840 mRasterizerDiscardEnabled = enabled;
1841 if (mRasterizerDiscardEnabled)
1842 {
1843 mFunctions->enable(GL_RASTERIZER_DISCARD);
1844 }
1845 else
1846 {
1847 mFunctions->disable(GL_RASTERIZER_DISCARD);
1848 }
1849
1850 mLocalDirtyBits.set(gl::state::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
1851 }
1852 }
1853
setLineWidth(float width)1854 void StateManagerGL::setLineWidth(float width)
1855 {
1856 if (mLineWidth != width)
1857 {
1858 mLineWidth = width;
1859 mFunctions->lineWidth(mLineWidth);
1860
1861 mLocalDirtyBits.set(gl::state::DIRTY_BIT_LINE_WIDTH);
1862 }
1863 }
1864
setPrimitiveRestartEnabled(const gl::Context * context,bool enabled)1865 angle::Result StateManagerGL::setPrimitiveRestartEnabled(const gl::Context *context, bool enabled)
1866 {
1867 if (mPrimitiveRestartEnabled != enabled)
1868 {
1869 GLenum cap = mFeatures.emulatePrimitiveRestartFixedIndex.enabled
1870 ? GL_PRIMITIVE_RESTART
1871 : GL_PRIMITIVE_RESTART_FIXED_INDEX;
1872
1873 if (enabled)
1874 {
1875 ANGLE_GL_TRY(context, mFunctions->enable(cap));
1876 }
1877 else
1878 {
1879 ANGLE_GL_TRY(context, mFunctions->disable(cap));
1880 }
1881 mPrimitiveRestartEnabled = enabled;
1882
1883 mLocalDirtyBits.set(gl::state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
1884 }
1885
1886 return angle::Result::Continue;
1887 }
1888
setPrimitiveRestartIndex(const gl::Context * context,GLuint index)1889 angle::Result StateManagerGL::setPrimitiveRestartIndex(const gl::Context *context, GLuint index)
1890 {
1891 if (mPrimitiveRestartIndex != index)
1892 {
1893 ANGLE_GL_TRY(context, mFunctions->primitiveRestartIndex(index));
1894 mPrimitiveRestartIndex = index;
1895
1896 // No dirty bit for this state, it is not exposed to the frontend.
1897 }
1898
1899 return angle::Result::Continue;
1900 }
1901
setClearDepth(float clearDepth)1902 void StateManagerGL::setClearDepth(float clearDepth)
1903 {
1904 if (mClearDepth != clearDepth)
1905 {
1906 mClearDepth = clearDepth;
1907
1908 // The glClearDepthf function isn't available until OpenGL 4.1. Prefer it when it is
1909 // available because OpenGL ES only works in floats.
1910 if (mFunctions->clearDepthf)
1911 {
1912 mFunctions->clearDepthf(mClearDepth);
1913 }
1914 else
1915 {
1916 ASSERT(mFunctions->clearDepth);
1917 mFunctions->clearDepth(mClearDepth);
1918 }
1919
1920 mLocalDirtyBits.set(gl::state::DIRTY_BIT_CLEAR_DEPTH);
1921 }
1922 }
1923
setClearColor(const gl::ColorF & clearColor)1924 void StateManagerGL::setClearColor(const gl::ColorF &clearColor)
1925 {
1926 gl::ColorF modifiedClearColor = clearColor;
1927 if (mFeatures.clearToZeroOrOneBroken.enabled &&
1928 (clearColor.red == 1.0f || clearColor.red == 0.0f) &&
1929 (clearColor.green == 1.0f || clearColor.green == 0.0f) &&
1930 (clearColor.blue == 1.0f || clearColor.blue == 0.0f) &&
1931 (clearColor.alpha == 1.0f || clearColor.alpha == 0.0f))
1932 {
1933 if (clearColor.alpha == 1.0f)
1934 {
1935 modifiedClearColor.alpha = 2.0f;
1936 }
1937 else
1938 {
1939 modifiedClearColor.alpha = -1.0f;
1940 }
1941 }
1942
1943 if (mClearColor != modifiedClearColor)
1944 {
1945 mClearColor = modifiedClearColor;
1946 mFunctions->clearColor(mClearColor.red, mClearColor.green, mClearColor.blue,
1947 mClearColor.alpha);
1948
1949 mLocalDirtyBits.set(gl::state::DIRTY_BIT_CLEAR_COLOR);
1950 }
1951 }
1952
setClearStencil(GLint clearStencil)1953 void StateManagerGL::setClearStencil(GLint clearStencil)
1954 {
1955 if (mClearStencil != clearStencil)
1956 {
1957 mClearStencil = clearStencil;
1958 mFunctions->clearStencil(mClearStencil);
1959
1960 mLocalDirtyBits.set(gl::state::DIRTY_BIT_CLEAR_STENCIL);
1961 }
1962 }
1963
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)1964 angle::Result StateManagerGL::syncState(const gl::Context *context,
1965 const gl::state::DirtyBits &glDirtyBits,
1966 const gl::state::DirtyBits &bitMask,
1967 const gl::state::ExtendedDirtyBits &extendedDirtyBits,
1968 const gl::state::ExtendedDirtyBits &extendedBitMask)
1969 {
1970 const gl::State &state = context->getState();
1971
1972 const gl::state::DirtyBits glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits) & bitMask;
1973 if (!glAndLocalDirtyBits.any())
1974 {
1975 return angle::Result::Continue;
1976 }
1977
1978 // TODO(jmadill): Investigate only syncing vertex state for active attributes
1979 for (auto iter = glAndLocalDirtyBits.begin(), endIter = glAndLocalDirtyBits.end();
1980 iter != endIter; ++iter)
1981 {
1982 switch (*iter)
1983 {
1984 case gl::state::DIRTY_BIT_SCISSOR_TEST_ENABLED:
1985 setScissorTestEnabled(state.isScissorTestEnabled());
1986 break;
1987 case gl::state::DIRTY_BIT_SCISSOR:
1988 {
1989 const gl::Rectangle &scissor = state.getScissor();
1990 setScissor(scissor);
1991 }
1992 break;
1993 case gl::state::DIRTY_BIT_VIEWPORT:
1994 {
1995 const gl::Rectangle &viewport = state.getViewport();
1996 setViewport(viewport);
1997 }
1998 break;
1999 case gl::state::DIRTY_BIT_DEPTH_RANGE:
2000 setDepthRange(state.getNearPlane(), state.getFarPlane());
2001 break;
2002 case gl::state::DIRTY_BIT_BLEND_ENABLED:
2003 if (mIndependentBlendStates)
2004 {
2005 setBlendEnabledIndexed(state.getBlendEnabledDrawBufferMask());
2006 }
2007 else
2008 {
2009 setBlendEnabled(state.isBlendEnabled());
2010 }
2011 break;
2012 case gl::state::DIRTY_BIT_BLEND_COLOR:
2013 setBlendColor(state.getBlendColor());
2014 break;
2015 case gl::state::DIRTY_BIT_BLEND_FUNCS:
2016 {
2017 setBlendFuncs(state.getBlendStateExt());
2018 break;
2019 }
2020 case gl::state::DIRTY_BIT_BLEND_EQUATIONS:
2021 {
2022 setBlendEquations(state.getBlendStateExt());
2023 break;
2024 }
2025 case gl::state::DIRTY_BIT_COLOR_MASK:
2026 {
2027 const gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
2028 const FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
2029 const bool disableAlphaWrite =
2030 framebufferGL->hasEmulatedAlphaChannelTextureAttachment();
2031
2032 setColorMaskForFramebuffer(state.getBlendStateExt(), disableAlphaWrite);
2033 break;
2034 }
2035 case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
2036 setSampleAlphaToCoverageEnabled(state.isSampleAlphaToCoverageEnabled());
2037 break;
2038 case gl::state::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
2039 setSampleCoverageEnabled(state.isSampleCoverageEnabled());
2040 break;
2041 case gl::state::DIRTY_BIT_SAMPLE_COVERAGE:
2042 setSampleCoverage(state.getSampleCoverageValue(), state.getSampleCoverageInvert());
2043 break;
2044 case gl::state::DIRTY_BIT_DEPTH_TEST_ENABLED:
2045 setDepthTestEnabled(state.isDepthTestEnabled());
2046 break;
2047 case gl::state::DIRTY_BIT_DEPTH_FUNC:
2048 setDepthFunc(state.getDepthStencilState().depthFunc);
2049 break;
2050 case gl::state::DIRTY_BIT_DEPTH_MASK:
2051 setDepthMask(state.getDepthStencilState().depthMask);
2052 break;
2053 case gl::state::DIRTY_BIT_STENCIL_TEST_ENABLED:
2054 setStencilTestEnabled(state.isStencilTestEnabled());
2055 break;
2056 case gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT:
2057 {
2058 const auto &depthStencilState = state.getDepthStencilState();
2059 setStencilFrontFuncs(depthStencilState.stencilFunc, state.getStencilRef(),
2060 depthStencilState.stencilMask);
2061 break;
2062 }
2063 case gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK:
2064 {
2065 const auto &depthStencilState = state.getDepthStencilState();
2066 setStencilBackFuncs(depthStencilState.stencilBackFunc, state.getStencilBackRef(),
2067 depthStencilState.stencilBackMask);
2068 break;
2069 }
2070 case gl::state::DIRTY_BIT_STENCIL_OPS_FRONT:
2071 {
2072 const auto &depthStencilState = state.getDepthStencilState();
2073 setStencilFrontOps(depthStencilState.stencilFail,
2074 depthStencilState.stencilPassDepthFail,
2075 depthStencilState.stencilPassDepthPass);
2076 break;
2077 }
2078 case gl::state::DIRTY_BIT_STENCIL_OPS_BACK:
2079 {
2080 const auto &depthStencilState = state.getDepthStencilState();
2081 setStencilBackOps(depthStencilState.stencilBackFail,
2082 depthStencilState.stencilBackPassDepthFail,
2083 depthStencilState.stencilBackPassDepthPass);
2084 break;
2085 }
2086 case gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
2087 setStencilFrontWritemask(state.getDepthStencilState().stencilWritemask);
2088 break;
2089 case gl::state::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
2090 setStencilBackWritemask(state.getDepthStencilState().stencilBackWritemask);
2091 break;
2092 case gl::state::DIRTY_BIT_CULL_FACE_ENABLED:
2093 setCullFaceEnabled(state.isCullFaceEnabled());
2094 break;
2095 case gl::state::DIRTY_BIT_CULL_FACE:
2096 setCullFace(state.getRasterizerState().cullMode);
2097 break;
2098 case gl::state::DIRTY_BIT_FRONT_FACE:
2099 setFrontFace(state.getRasterizerState().frontFace);
2100 break;
2101 case gl::state::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
2102 setPolygonOffsetFillEnabled(state.isPolygonOffsetFillEnabled());
2103 break;
2104 case gl::state::DIRTY_BIT_POLYGON_OFFSET:
2105 {
2106 const auto &rasterizerState = state.getRasterizerState();
2107 setPolygonOffset(rasterizerState.polygonOffsetFactor,
2108 rasterizerState.polygonOffsetUnits,
2109 rasterizerState.polygonOffsetClamp);
2110 break;
2111 }
2112 case gl::state::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
2113 setRasterizerDiscardEnabled(state.isRasterizerDiscardEnabled());
2114 break;
2115 case gl::state::DIRTY_BIT_LINE_WIDTH:
2116 setLineWidth(state.getLineWidth());
2117 break;
2118 case gl::state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
2119 ANGLE_TRY(setPrimitiveRestartEnabled(context, state.isPrimitiveRestartEnabled()));
2120 break;
2121 case gl::state::DIRTY_BIT_CLEAR_COLOR:
2122 setClearColor(state.getColorClearValue());
2123 break;
2124 case gl::state::DIRTY_BIT_CLEAR_DEPTH:
2125 setClearDepth(state.getDepthClearValue());
2126 break;
2127 case gl::state::DIRTY_BIT_CLEAR_STENCIL:
2128 setClearStencil(state.getStencilClearValue());
2129 break;
2130 case gl::state::DIRTY_BIT_UNPACK_STATE:
2131 ANGLE_TRY(setPixelUnpackState(context, state.getUnpackState()));
2132 break;
2133 case gl::state::DIRTY_BIT_UNPACK_BUFFER_BINDING:
2134 ANGLE_TRY(setPixelUnpackBuffer(
2135 context, state.getTargetBuffer(gl::BufferBinding::PixelUnpack)));
2136 break;
2137 case gl::state::DIRTY_BIT_PACK_STATE:
2138 ANGLE_TRY(setPixelPackState(context, state.getPackState()));
2139 break;
2140 case gl::state::DIRTY_BIT_PACK_BUFFER_BINDING:
2141 ANGLE_TRY(setPixelPackBuffer(context,
2142 state.getTargetBuffer(gl::BufferBinding::PixelPack)));
2143 break;
2144 case gl::state::DIRTY_BIT_DITHER_ENABLED:
2145 setDitherEnabled(state.isDitherEnabled());
2146 break;
2147 case gl::state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
2148 {
2149 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
2150
2151 // Necessary for an Intel TexImage workaround.
2152 if (!framebuffer)
2153 continue;
2154
2155 FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
2156 bindFramebuffer(
2157 mHasSeparateFramebufferBindings ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER,
2158 framebufferGL->getFramebufferID());
2159 break;
2160 }
2161 case gl::state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
2162 {
2163 gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
2164
2165 // Necessary for an Intel TexImage workaround.
2166 if (!framebuffer)
2167 continue;
2168
2169 FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
2170 bindFramebuffer(
2171 mHasSeparateFramebufferBindings ? GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER,
2172 framebufferGL->getFramebufferID());
2173
2174 const gl::Program *program = state.getProgram();
2175 if (program)
2176 {
2177 updateMultiviewBaseViewLayerIndexUniform(program, framebufferGL->getState());
2178 }
2179
2180 // Changing the draw framebuffer binding sometimes requires resetting srgb blending.
2181 iter.setLaterBit(gl::state::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE);
2182
2183 // If the framebuffer is emulating RGB on top of RGBA, the color mask has to be
2184 // updated
2185 iter.setLaterBit(gl::state::DIRTY_BIT_COLOR_MASK);
2186 break;
2187 }
2188 case gl::state::DIRTY_BIT_RENDERBUFFER_BINDING:
2189 // TODO(jmadill): implement this
2190 break;
2191 case gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING:
2192 {
2193 VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(state.getVertexArray());
2194 bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getNativeState());
2195
2196 ANGLE_TRY(propagateProgramToVAO(context, state.getProgram(),
2197 GetImplAs<VertexArrayGL>(state.getVertexArray())));
2198
2199 if (mFeatures.syncVertexArraysToDefault.enabled)
2200 {
2201 // Re-sync the vertex array because all frontend VAOs share the same backend
2202 // state. Only sync bits that can be set in ES2.0 or 3.0
2203 gl::VertexArray::DirtyBits dirtyBits;
2204 gl::VertexArray::DirtyAttribBitsArray dirtyAttribBits;
2205 gl::VertexArray::DirtyBindingBitsArray dirtBindingBits;
2206
2207 dirtyBits.set(gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
2208 for (size_t attrib = 0; attrib < mDefaultVAOState.attributes.size(); attrib++)
2209 {
2210 dirtyBits.set(gl::VertexArray::DIRTY_BIT_ATTRIB_0 + attrib);
2211 dirtyAttribBits[attrib].set(gl::VertexArray::DIRTY_ATTRIB_ENABLED);
2212 dirtyAttribBits[attrib].set(gl::VertexArray::DIRTY_ATTRIB_POINTER);
2213 dirtyAttribBits[attrib].set(gl::VertexArray::DIRTY_ATTRIB_POINTER_BUFFER);
2214 }
2215 for (size_t binding = 0; binding < mDefaultVAOState.bindings.size(); binding++)
2216 {
2217 dirtyBits.set(gl::VertexArray::DIRTY_BIT_BINDING_0 + binding);
2218 dirtBindingBits[binding].set(gl::VertexArray::DIRTY_BINDING_DIVISOR);
2219 }
2220
2221 ANGLE_TRY(
2222 vaoGL->syncState(context, dirtyBits, &dirtyAttribBits, &dirtBindingBits));
2223 }
2224 break;
2225 }
2226 case gl::state::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
2227 updateDrawIndirectBufferBinding(context);
2228 break;
2229 case gl::state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
2230 updateDispatchIndirectBufferBinding(context);
2231 break;
2232 case gl::state::DIRTY_BIT_PROGRAM_BINDING:
2233 {
2234 gl::Program *program = state.getProgram();
2235 if (program != nullptr)
2236 {
2237 useProgram(GetImplAs<ProgramGL>(program)->getProgramID());
2238 }
2239 break;
2240 }
2241 case gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE:
2242 {
2243 const gl::Program *program = state.getProgram();
2244 const gl::ProgramExecutable *executable = state.getProgramExecutable();
2245
2246 if (program && executable)
2247 {
2248 iter.setLaterBit(gl::state::DIRTY_BIT_TEXTURE_BINDINGS);
2249
2250 if (executable->getActiveImagesMask().any())
2251 {
2252 iter.setLaterBit(gl::state::DIRTY_BIT_IMAGE_BINDINGS);
2253 }
2254
2255 if (program->getActiveShaderStorageBlockCount() > 0)
2256 {
2257 iter.setLaterBit(gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
2258 }
2259
2260 if (program->getActiveUniformBlockCount() > 0)
2261 {
2262 iter.setLaterBit(gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
2263 }
2264
2265 if (program->getActiveAtomicCounterBufferCount() > 0)
2266 {
2267 iter.setLaterBit(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
2268 }
2269
2270 if (mIsMultiviewEnabled && program->usesMultiview())
2271 {
2272 updateMultiviewBaseViewLayerIndexUniform(
2273 program, state.getDrawFramebuffer()->getImplementation()->getState());
2274 }
2275
2276 if (mFeatures.emulateClipDistanceState.enabled)
2277 {
2278 updateEmulatedClipDistanceState(executable, program,
2279 state.getEnabledClipDistances());
2280 }
2281 }
2282
2283 if (!program ||
2284 !program->getExecutable().hasLinkedShaderStage(gl::ShaderType::Compute))
2285 {
2286 ANGLE_TRY(propagateProgramToVAO(
2287 context, program, GetImplAs<VertexArrayGL>(state.getVertexArray())));
2288 }
2289 break;
2290 }
2291 case gl::state::DIRTY_BIT_TEXTURE_BINDINGS:
2292 updateProgramTextureBindings(context);
2293 break;
2294 case gl::state::DIRTY_BIT_SAMPLER_BINDINGS:
2295 syncSamplersState(context);
2296 break;
2297 case gl::state::DIRTY_BIT_IMAGE_BINDINGS:
2298 updateProgramImageBindings(context);
2299 break;
2300 case gl::state::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
2301 syncTransformFeedbackState(context);
2302 break;
2303 case gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
2304 updateProgramStorageBufferBindings(context);
2305 break;
2306 case gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
2307 updateProgramUniformBufferBindings(context);
2308 break;
2309 case gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
2310 updateProgramAtomicCounterBufferBindings(context);
2311 break;
2312 case gl::state::DIRTY_BIT_MULTISAMPLING:
2313 setMultisamplingStateEnabled(state.isMultisamplingEnabled());
2314 break;
2315 case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
2316 setSampleAlphaToOneStateEnabled(state.isSampleAlphaToOneEnabled());
2317 break;
2318 case gl::state::DIRTY_BIT_COVERAGE_MODULATION:
2319 setCoverageModulation(state.getCoverageModulation());
2320 break;
2321 case gl::state::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE:
2322 setFramebufferSRGBEnabledForFramebuffer(
2323 context, state.getFramebufferSRGB(),
2324 GetImplAs<FramebufferGL>(state.getDrawFramebuffer()));
2325 break;
2326 case gl::state::DIRTY_BIT_SAMPLE_MASK_ENABLED:
2327 setSampleMaskEnabled(state.isSampleMaskEnabled());
2328 break;
2329 case gl::state::DIRTY_BIT_SAMPLE_MASK:
2330 {
2331 for (GLuint maskNumber = 0; maskNumber < state.getMaxSampleMaskWords();
2332 ++maskNumber)
2333 {
2334 setSampleMaski(maskNumber, state.getSampleMaskWord(maskNumber));
2335 }
2336 break;
2337 }
2338 case gl::state::DIRTY_BIT_CURRENT_VALUES:
2339 {
2340 gl::AttributesMask combinedMask =
2341 (state.getAndResetDirtyCurrentValues() | mLocalDirtyCurrentValues);
2342 mLocalDirtyCurrentValues.reset();
2343
2344 for (auto attribIndex : combinedMask)
2345 {
2346 setAttributeCurrentData(attribIndex,
2347 state.getVertexAttribCurrentValue(attribIndex));
2348 }
2349 break;
2350 }
2351 case gl::state::DIRTY_BIT_PROVOKING_VERTEX:
2352 setProvokingVertex(ToGLenum(state.getProvokingVertex()));
2353 break;
2354 case gl::state::DIRTY_BIT_EXTENDED:
2355 {
2356 const gl::state::ExtendedDirtyBits glAndLocalExtendedDirtyBits =
2357 extendedDirtyBits | mLocalExtendedDirtyBits;
2358 for (size_t extendedDirtyBit : glAndLocalExtendedDirtyBits)
2359 {
2360 switch (extendedDirtyBit)
2361 {
2362 case gl::state::EXTENDED_DIRTY_BIT_CLIP_CONTROL:
2363 setClipControl(state.getClipOrigin(), state.getClipDepthMode());
2364 break;
2365 case gl::state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES:
2366 setClipDistancesEnable(state.getEnabledClipDistances());
2367 if (mFeatures.emulateClipDistanceState.enabled)
2368 {
2369 updateEmulatedClipDistanceState(state.getProgramExecutable(),
2370 state.getProgram(),
2371 state.getEnabledClipDistances());
2372 }
2373 break;
2374 case gl::state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED:
2375 setDepthClampEnabled(state.isDepthClampEnabled());
2376 break;
2377 case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED:
2378 setLogicOpEnabled(state.isLogicOpEnabled());
2379 break;
2380 case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP:
2381 setLogicOp(state.getLogicOp());
2382 break;
2383 case gl::state::EXTENDED_DIRTY_BIT_MIPMAP_GENERATION_HINT:
2384 break;
2385 case gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE:
2386 setPolygonMode(state.getPolygonMode());
2387 break;
2388 case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_POINT_ENABLED:
2389 setPolygonOffsetPointEnabled(state.isPolygonOffsetPointEnabled());
2390 break;
2391 case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED:
2392 setPolygonOffsetLineEnabled(state.isPolygonOffsetLineEnabled());
2393 break;
2394 case gl::state::EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT:
2395 // These hints aren't forwarded to GL yet.
2396 break;
2397 case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE:
2398 // Unimplemented extensions.
2399 break;
2400 default:
2401 UNREACHABLE();
2402 break;
2403 }
2404 mLocalExtendedDirtyBits &= ~extendedDirtyBits;
2405 }
2406 break;
2407 }
2408 case gl::state::DIRTY_BIT_SAMPLE_SHADING:
2409 // Nothing to do until OES_sample_shading is implemented.
2410 break;
2411 case gl::state::DIRTY_BIT_PATCH_VERTICES:
2412 // Nothing to do until EXT_tessellation_shader is implemented.
2413 break;
2414 default:
2415 UNREACHABLE();
2416 break;
2417 }
2418 }
2419
2420 mLocalDirtyBits &= ~bitMask;
2421
2422 return angle::Result::Continue;
2423 }
2424
setFramebufferSRGBEnabled(const gl::Context * context,bool enabled)2425 void StateManagerGL::setFramebufferSRGBEnabled(const gl::Context *context, bool enabled)
2426 {
2427 if (!mFramebufferSRGBAvailable)
2428 {
2429 return;
2430 }
2431
2432 if (mFramebufferSRGBEnabled != enabled)
2433 {
2434 mFramebufferSRGBEnabled = enabled;
2435 if (mFramebufferSRGBEnabled)
2436 {
2437 mFunctions->enable(GL_FRAMEBUFFER_SRGB);
2438 }
2439 else
2440 {
2441 mFunctions->disable(GL_FRAMEBUFFER_SRGB);
2442 }
2443 mLocalDirtyBits.set(gl::state::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE);
2444 }
2445 }
2446
setFramebufferSRGBEnabledForFramebuffer(const gl::Context * context,bool enabled,const FramebufferGL * framebuffer)2447 void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context,
2448 bool enabled,
2449 const FramebufferGL *framebuffer)
2450 {
2451 if (framebuffer->isDefault())
2452 {
2453 // Obey the framebuffer sRGB state for blending on all framebuffers except the default
2454 // framebuffer.
2455 // When SRGB blending is enabled, only SRGB capable formats will use it but the default
2456 // framebuffer will always use it if it is enabled.
2457 // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
2458 setFramebufferSRGBEnabled(context, false);
2459 }
2460 else
2461 {
2462 setFramebufferSRGBEnabled(context, enabled);
2463 }
2464 }
2465
setColorMaskForFramebuffer(const gl::BlendStateExt & blendStateExt,const bool disableAlpha)2466 void StateManagerGL::setColorMaskForFramebuffer(const gl::BlendStateExt &blendStateExt,
2467 const bool disableAlpha)
2468 {
2469 bool r, g, b, a;
2470
2471 // Given that disableAlpha can be true only on macOS backbuffers and color mask is re-synced on
2472 // bound draw framebuffer change, switch all draw buffers color masks to avoid special case
2473 // later.
2474 if (!mIndependentBlendStates || disableAlpha)
2475 {
2476 blendStateExt.getColorMaskIndexed(0, &r, &g, &b, &a);
2477 setColorMask(r, g, b, disableAlpha ? false : a);
2478 return;
2479 }
2480
2481 // Check if the current mask already matches the new state
2482 if (mBlendStateExt.getColorMaskBits() == blendStateExt.getColorMaskBits())
2483 {
2484 return;
2485 }
2486
2487 // Get DrawBufferMask of buffers with different color masks
2488 gl::DrawBufferMask diffMask = mBlendStateExt.compareColorMask(blendStateExt.getColorMaskBits());
2489 size_t diffCount = diffMask.count();
2490
2491 // Check if setting all buffers to the same value reduces the number of subsequent indexed
2492 // commands. Implicitly handles the case when the new mask is the same for all buffers.
2493 // For instance, let's say that previously synced mask is ccccff00 and the new state is
2494 // ffeeeeee. Instead of calling colorMaski 8 times, ANGLE can set all buffers to `e` and then
2495 // use colorMaski only twice. On the other hand, if the new state is cceeee00, a non-indexed
2496 // call will increase the total number of GL commands.
2497 if (diffCount > 1)
2498 {
2499 bool found = false;
2500 gl::BlendStateExt::ColorMaskStorage::Type commonColorMask = 0;
2501 for (size_t i = 0; i < mBlendStateExt.getDrawBufferCount() - 1; i++)
2502 {
2503 const gl::BlendStateExt::ColorMaskStorage::Type tempCommonColorMask =
2504 blendStateExt.expandColorMaskIndexed(i);
2505 const gl::DrawBufferMask tempDiffMask =
2506 blendStateExt.compareColorMask(tempCommonColorMask);
2507 const size_t tempDiffCount = tempDiffMask.count();
2508 if (tempDiffCount < diffCount)
2509 {
2510 found = true;
2511 diffMask = tempDiffMask;
2512 diffCount = tempDiffCount;
2513 commonColorMask = tempCommonColorMask;
2514 if (tempDiffCount == 0)
2515 {
2516 break; // the new mask is the same for all buffers
2517 }
2518 }
2519 }
2520 if (found)
2521 {
2522 gl::BlendStateExt::UnpackColorMask(commonColorMask, &r, &g, &b, &a);
2523 mFunctions->colorMask(r, g, b, a);
2524 }
2525 }
2526
2527 for (size_t drawBufferIndex : diffMask)
2528 {
2529 blendStateExt.getColorMaskIndexed(drawBufferIndex, &r, &g, &b, &a);
2530 mFunctions->colorMaski(static_cast<GLuint>(drawBufferIndex), r, g, b, a);
2531 }
2532
2533 mBlendStateExt.setColorMaskBits(blendStateExt.getColorMaskBits());
2534 mLocalDirtyBits.set(gl::state::DIRTY_BIT_COLOR_MASK);
2535 }
2536
setDitherEnabled(bool enabled)2537 void StateManagerGL::setDitherEnabled(bool enabled)
2538 {
2539 if (mDitherEnabled != enabled)
2540 {
2541 mDitherEnabled = enabled;
2542 if (mDitherEnabled)
2543 {
2544 mFunctions->enable(GL_DITHER);
2545 }
2546 else
2547 {
2548 mFunctions->disable(GL_DITHER);
2549 }
2550 }
2551 }
2552
setMultisamplingStateEnabled(bool enabled)2553 void StateManagerGL::setMultisamplingStateEnabled(bool enabled)
2554 {
2555 if (mMultisamplingEnabled != enabled)
2556 {
2557 mMultisamplingEnabled = enabled;
2558 if (mMultisamplingEnabled)
2559 {
2560 mFunctions->enable(GL_MULTISAMPLE_EXT);
2561 }
2562 else
2563 {
2564 mFunctions->disable(GL_MULTISAMPLE_EXT);
2565 }
2566 mLocalDirtyBits.set(gl::state::DIRTY_BIT_MULTISAMPLING);
2567 }
2568 }
2569
setSampleAlphaToOneStateEnabled(bool enabled)2570 void StateManagerGL::setSampleAlphaToOneStateEnabled(bool enabled)
2571 {
2572 if (mSampleAlphaToOneEnabled != enabled)
2573 {
2574 mSampleAlphaToOneEnabled = enabled;
2575 if (mSampleAlphaToOneEnabled)
2576 {
2577 mFunctions->enable(GL_SAMPLE_ALPHA_TO_ONE);
2578 }
2579 else
2580 {
2581 mFunctions->disable(GL_SAMPLE_ALPHA_TO_ONE);
2582 }
2583 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
2584 }
2585 }
2586
setCoverageModulation(GLenum components)2587 void StateManagerGL::setCoverageModulation(GLenum components)
2588 {
2589 if (mCoverageModulation != components)
2590 {
2591 mCoverageModulation = components;
2592 mFunctions->coverageModulationNV(components);
2593
2594 mLocalDirtyBits.set(gl::state::DIRTY_BIT_COVERAGE_MODULATION);
2595 }
2596 }
2597
setProvokingVertex(GLenum mode)2598 void StateManagerGL::setProvokingVertex(GLenum mode)
2599 {
2600 if (mode != mProvokingVertex)
2601 {
2602 mFunctions->provokingVertex(mode);
2603 mProvokingVertex = mode;
2604
2605 mLocalDirtyBits.set(gl::state::DIRTY_BIT_PROVOKING_VERTEX);
2606 }
2607 }
2608
setClipDistancesEnable(const gl::ClipDistanceEnableBits & enables)2609 void StateManagerGL::setClipDistancesEnable(const gl::ClipDistanceEnableBits &enables)
2610 {
2611 if (enables == mEnabledClipDistances)
2612 {
2613 return;
2614 }
2615 ASSERT(mMaxClipDistances <= gl::IMPLEMENTATION_MAX_CLIP_DISTANCES);
2616
2617 gl::ClipDistanceEnableBits diff = enables ^ mEnabledClipDistances;
2618 for (size_t i : diff)
2619 {
2620 if (enables.test(i))
2621 {
2622 mFunctions->enable(GL_CLIP_DISTANCE0_EXT + static_cast<uint32_t>(i));
2623 }
2624 else
2625 {
2626 mFunctions->disable(GL_CLIP_DISTANCE0_EXT + static_cast<uint32_t>(i));
2627 }
2628 }
2629
2630 mEnabledClipDistances = enables;
2631 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
2632 mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES);
2633 }
2634
setLogicOpEnabled(bool enabled)2635 void StateManagerGL::setLogicOpEnabled(bool enabled)
2636 {
2637 if (enabled == mLogicOpEnabled)
2638 {
2639 return;
2640 }
2641 mLogicOpEnabled = enabled;
2642
2643 if (enabled)
2644 {
2645 mFunctions->enable(GL_COLOR_LOGIC_OP);
2646 }
2647 else
2648 {
2649 mFunctions->disable(GL_COLOR_LOGIC_OP);
2650 }
2651
2652 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
2653 mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED);
2654 }
2655
setLogicOp(gl::LogicalOperation opcode)2656 void StateManagerGL::setLogicOp(gl::LogicalOperation opcode)
2657 {
2658 if (opcode == mLogicOp)
2659 {
2660 return;
2661 }
2662 mLogicOp = opcode;
2663
2664 mFunctions->logicOp(ToGLenum(opcode));
2665
2666 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
2667 mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED);
2668 }
2669
setTextureCubemapSeamlessEnabled(bool enabled)2670 void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
2671 {
2672 // TODO(jmadill): Also check for seamless extension.
2673 if (!mFunctions->isAtLeastGL(gl::Version(3, 2)))
2674 {
2675 return;
2676 }
2677
2678 if (mTextureCubemapSeamlessEnabled != enabled)
2679 {
2680 mTextureCubemapSeamlessEnabled = enabled;
2681 if (mTextureCubemapSeamlessEnabled)
2682 {
2683 mFunctions->enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
2684 }
2685 else
2686 {
2687 mFunctions->disable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
2688 }
2689 }
2690 }
2691
propagateProgramToVAO(const gl::Context * context,const gl::Program * program,VertexArrayGL * vao)2692 angle::Result StateManagerGL::propagateProgramToVAO(const gl::Context *context,
2693 const gl::Program *program,
2694 VertexArrayGL *vao)
2695 {
2696 if (vao == nullptr)
2697 {
2698 return angle::Result::Continue;
2699 }
2700
2701 // Number of views:
2702 if (mIsMultiviewEnabled)
2703 {
2704 int programNumViews = 1;
2705 if (program && program->usesMultiview())
2706 {
2707 programNumViews = program->getNumViews();
2708 }
2709 ANGLE_TRY(vao->applyNumViewsToDivisor(context, programNumViews));
2710 }
2711
2712 // Attribute enabled mask:
2713 if (program)
2714 {
2715 ANGLE_TRY(vao->applyActiveAttribLocationsMask(
2716 context, program->getExecutable().getActiveAttribLocationsMask()));
2717 }
2718
2719 return angle::Result::Continue;
2720 }
2721
updateMultiviewBaseViewLayerIndexUniformImpl(const gl::Program * program,const gl::FramebufferState & drawFramebufferState) const2722 void StateManagerGL::updateMultiviewBaseViewLayerIndexUniformImpl(
2723 const gl::Program *program,
2724 const gl::FramebufferState &drawFramebufferState) const
2725 {
2726 ASSERT(mIsMultiviewEnabled && program && program->usesMultiview());
2727 const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
2728 if (drawFramebufferState.isMultiview())
2729 {
2730 programGL->enableLayeredRenderingPath(drawFramebufferState.getBaseViewIndex());
2731 }
2732 }
2733
updateEmulatedClipDistanceState(const gl::ProgramExecutable * executable,const gl::Program * program,const gl::ClipDistanceEnableBits enables) const2734 void StateManagerGL::updateEmulatedClipDistanceState(const gl::ProgramExecutable *executable,
2735 const gl::Program *program,
2736 const gl::ClipDistanceEnableBits enables) const
2737 {
2738 ASSERT(mFeatures.emulateClipDistanceState.enabled);
2739 if (executable && executable->hasClipDistance())
2740 {
2741 const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
2742 programGL->updateEnabledClipDistances(static_cast<uint8_t>(enables.bits()));
2743 }
2744 }
2745
syncSamplersState(const gl::Context * context)2746 void StateManagerGL::syncSamplersState(const gl::Context *context)
2747 {
2748 const gl::SamplerBindingVector &samplers = context->getState().getSamplers();
2749
2750 // This could be optimized by using a separate binding dirty bit per sampler.
2751 for (size_t samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex)
2752 {
2753 const gl::Sampler *sampler = samplers[samplerIndex].get();
2754 if (sampler != nullptr)
2755 {
2756 SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler);
2757 bindSampler(samplerIndex, samplerGL->getSamplerID());
2758 }
2759 else
2760 {
2761 bindSampler(samplerIndex, 0);
2762 }
2763 }
2764 }
2765
syncTransformFeedbackState(const gl::Context * context)2766 void StateManagerGL::syncTransformFeedbackState(const gl::Context *context)
2767 {
2768 // Set the current transform feedback state
2769 gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
2770 if (transformFeedback)
2771 {
2772 TransformFeedbackGL *transformFeedbackGL =
2773 GetImplAs<TransformFeedbackGL>(transformFeedback);
2774 bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID());
2775 transformFeedbackGL->syncActiveState(context, transformFeedback->isActive(),
2776 transformFeedback->getPrimitiveMode());
2777 transformFeedbackGL->syncPausedState(transformFeedback->isPaused());
2778 mCurrentTransformFeedback = transformFeedbackGL;
2779 }
2780 else
2781 {
2782 bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
2783 mCurrentTransformFeedback = nullptr;
2784 }
2785 }
2786
getDefaultVAO() const2787 GLuint StateManagerGL::getDefaultVAO() const
2788 {
2789 return mDefaultVAO;
2790 }
2791
getDefaultVAOState()2792 VertexArrayStateGL *StateManagerGL::getDefaultVAOState()
2793 {
2794 return &mDefaultVAOState;
2795 }
2796
validateState() const2797 void StateManagerGL::validateState() const
2798 {
2799 // Current program
2800 ValidateStateHelper(mFunctions, mProgram, GL_CURRENT_PROGRAM, "mProgram", "GL_CURRENT_PROGRAM");
2801
2802 // Buffers
2803 for (gl::BufferBinding bindingType : angle::AllEnums<gl::BufferBinding>())
2804 {
2805 // These binding types need compute support to be queried
2806 if (bindingType == gl::BufferBinding::AtomicCounter ||
2807 bindingType == gl::BufferBinding::DispatchIndirect ||
2808 bindingType == gl::BufferBinding::ShaderStorage)
2809 {
2810 if (!nativegl::SupportsCompute(mFunctions))
2811 {
2812 continue;
2813 }
2814 }
2815
2816 // Transform feedback buffer bindings are tracked in TransformFeedbackGL
2817 if (bindingType == gl::BufferBinding::TransformFeedback)
2818 {
2819 continue;
2820 }
2821
2822 GLenum bindingTypeGL = nativegl::GetBufferBindingQuery(bindingType);
2823 std::string localName = "mBuffers[" + ToString(bindingType) + "]";
2824 ValidateStateHelper(mFunctions, mBuffers[bindingType], bindingTypeGL, localName.c_str(),
2825 nativegl::GetBufferBindingString(bindingType).c_str());
2826 }
2827
2828 // Vertex array object
2829 ValidateStateHelper(mFunctions, mVAO, GL_VERTEX_ARRAY_BINDING, "mVAO",
2830 "GL_VERTEX_ARRAY_BINDING");
2831 }
2832
2833 template <>
get(GLenum name,GLboolean * value)2834 void StateManagerGL::get(GLenum name, GLboolean *value)
2835 {
2836 mFunctions->getBooleanv(name, value);
2837 ASSERT(mFunctions->getError() == GL_NO_ERROR);
2838 }
2839
2840 template <>
get(GLenum name,bool * value)2841 void StateManagerGL::get(GLenum name, bool *value)
2842 {
2843 GLboolean v;
2844 get(name, &v);
2845 *value = (v == GL_TRUE);
2846 }
2847
2848 template <>
get(GLenum name,std::array<bool,4> * values)2849 void StateManagerGL::get(GLenum name, std::array<bool, 4> *values)
2850 {
2851 GLboolean v[4];
2852 get(name, v);
2853 for (size_t i = 0; i < 4; i++)
2854 {
2855 (*values)[i] = (v[i] == GL_TRUE);
2856 }
2857 }
2858
2859 template <>
get(GLenum name,GLint * value)2860 void StateManagerGL::get(GLenum name, GLint *value)
2861 {
2862 mFunctions->getIntegerv(name, value);
2863 ASSERT(mFunctions->getError() == GL_NO_ERROR);
2864 }
2865
2866 template <>
get(GLenum name,GLenum * value)2867 void StateManagerGL::get(GLenum name, GLenum *value)
2868 {
2869 GLint v;
2870 get(name, &v);
2871 *value = static_cast<GLenum>(v);
2872 }
2873
2874 template <>
get(GLenum name,gl::Rectangle * rect)2875 void StateManagerGL::get(GLenum name, gl::Rectangle *rect)
2876 {
2877 GLint v[4];
2878 get(name, v);
2879 *rect = gl::Rectangle(v[0], v[1], v[2], v[3]);
2880 }
2881
2882 template <>
get(GLenum name,GLfloat * value)2883 void StateManagerGL::get(GLenum name, GLfloat *value)
2884 {
2885 mFunctions->getFloatv(name, value);
2886 ASSERT(mFunctions->getError() == GL_NO_ERROR);
2887 }
2888
2889 template <>
get(GLenum name,gl::ColorF * color)2890 void StateManagerGL::get(GLenum name, gl::ColorF *color)
2891 {
2892 GLfloat v[4];
2893 get(name, v);
2894 *color = gl::ColorF(v[0], v[1], v[2], v[3]);
2895 }
2896
syncFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)2897 void StateManagerGL::syncFromNativeContext(const gl::Extensions &extensions,
2898 ExternalContextState *state)
2899 {
2900 ASSERT(mFunctions->getError() == GL_NO_ERROR);
2901
2902 auto *platform = ANGLEPlatformCurrent();
2903 double startTime = platform->currentTime(platform);
2904
2905 get(GL_VIEWPORT, &state->viewport);
2906 if (mViewport != state->viewport)
2907 {
2908 mViewport = state->viewport;
2909 mLocalDirtyBits.set(gl::state::DIRTY_BIT_VIEWPORT);
2910 }
2911
2912 if (extensions.clipControlEXT)
2913 {
2914 get(GL_CLIP_ORIGIN, &state->clipOrigin);
2915 get(GL_CLIP_DEPTH_MODE, &state->clipDepthMode);
2916 if (mClipOrigin != gl::FromGLenum<gl::ClipOrigin>(state->clipOrigin) ||
2917 mClipDepthMode != gl::FromGLenum<gl::ClipDepthMode>(state->clipDepthMode))
2918 {
2919 mClipOrigin = gl::FromGLenum<gl::ClipOrigin>(state->clipOrigin);
2920 mClipDepthMode = gl::FromGLenum<gl::ClipDepthMode>(state->clipDepthMode);
2921 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
2922 mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_CLIP_CONTROL);
2923 }
2924 }
2925
2926 get(GL_SCISSOR_TEST, &state->scissorTest);
2927 if (mScissorTestEnabled != static_cast<bool>(state->scissorTest))
2928 {
2929 mScissorTestEnabled = state->scissorTest;
2930 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SCISSOR_TEST_ENABLED);
2931 }
2932
2933 get(GL_SCISSOR_BOX, &state->scissorBox);
2934 if (mScissor != state->scissorBox)
2935 {
2936 mScissor = state->scissorBox;
2937 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SCISSOR);
2938 }
2939
2940 get(GL_DEPTH_TEST, &state->depthTest);
2941 if (mDepthTestEnabled != state->depthTest)
2942 {
2943 mDepthTestEnabled = state->depthTest;
2944 mLocalDirtyBits.set(gl::state::DIRTY_BIT_DEPTH_TEST_ENABLED);
2945 }
2946
2947 get(GL_CULL_FACE, &state->cullFace);
2948 if (mCullFaceEnabled != state->cullFace)
2949 {
2950 mCullFaceEnabled = state->cullFace;
2951 mLocalDirtyBits.set(gl::state::DIRTY_BIT_CULL_FACE_ENABLED);
2952 }
2953
2954 get(GL_CULL_FACE_MODE, &state->cullFaceMode);
2955 if (mCullFace != gl::FromGLenum<gl::CullFaceMode>(state->cullFaceMode))
2956 {
2957 mCullFace = gl::FromGLenum<gl::CullFaceMode>(state->cullFaceMode);
2958 mLocalDirtyBits.set(gl::state::DIRTY_BIT_CULL_FACE);
2959 }
2960
2961 get(GL_COLOR_WRITEMASK, &state->colorMask);
2962 auto colorMask = mBlendStateExt.expandColorMaskValue(state->colorMask[0], state->colorMask[1],
2963 state->colorMask[2], state->colorMask[3]);
2964 if (mBlendStateExt.getColorMaskBits() != colorMask)
2965 {
2966 mBlendStateExt.setColorMaskBits(colorMask);
2967 mLocalDirtyBits.set(gl::state::DIRTY_BIT_COLOR_MASK);
2968 }
2969
2970 get(GL_CURRENT_PROGRAM, &state->currentProgram);
2971 if (mProgram != static_cast<GLuint>(state->currentProgram))
2972 {
2973 mProgram = state->currentProgram;
2974 mLocalDirtyBits.set(gl::state::DIRTY_BIT_PROGRAM_BINDING);
2975 }
2976
2977 get(GL_COLOR_CLEAR_VALUE, &state->colorClear);
2978 if (mClearColor != state->colorClear)
2979 {
2980 mClearColor = state->colorClear;
2981 mLocalDirtyBits.set(gl::state::DIRTY_BIT_CLEAR_COLOR);
2982 }
2983
2984 get(GL_DEPTH_CLEAR_VALUE, &state->depthClear);
2985 if (mClearDepth != state->depthClear)
2986 {
2987 mClearDepth = state->depthClear;
2988 mLocalDirtyBits.set(gl::state::DIRTY_BIT_CLEAR_DEPTH);
2989 }
2990
2991 get(GL_DEPTH_FUNC, &state->depthFunc);
2992 if (mDepthFunc != static_cast<GLenum>(state->depthFunc))
2993 {
2994 mDepthFunc = state->depthFunc;
2995 mLocalDirtyBits.set(gl::state::DIRTY_BIT_DEPTH_FUNC);
2996 }
2997
2998 get(GL_DEPTH_WRITEMASK, &state->depthMask);
2999 if (mDepthMask != state->depthMask)
3000 {
3001 mDepthMask = state->depthMask;
3002 mLocalDirtyBits.set(gl::state::DIRTY_BIT_DEPTH_MASK);
3003 }
3004
3005 get(GL_DEPTH_RANGE, state->depthRage);
3006 if (mNear != state->depthRage[0] || mFar != state->depthRage[1])
3007 {
3008 mNear = state->depthRage[0];
3009 mFar = state->depthRage[1];
3010 mLocalDirtyBits.set(gl::state::DIRTY_BIT_DEPTH_RANGE);
3011 }
3012
3013 get(GL_FRONT_FACE, &state->frontFace);
3014 if (mFrontFace != static_cast<GLenum>(state->frontFace))
3015 {
3016 mFrontFace = state->frontFace;
3017 mLocalDirtyBits.set(gl::state::DIRTY_BIT_FRONT_FACE);
3018 }
3019
3020 get(GL_LINE_WIDTH, &state->lineWidth);
3021 if (mLineWidth != state->lineWidth)
3022 {
3023 mLineWidth = state->lineWidth;
3024 mLocalDirtyBits.set(gl::state::DIRTY_BIT_LINE_WIDTH);
3025 }
3026
3027 get(GL_POLYGON_OFFSET_FACTOR, &state->polygonOffsetFactor);
3028 get(GL_POLYGON_OFFSET_UNITS, &state->polygonOffsetUnits);
3029 if (mPolygonOffsetFactor != state->polygonOffsetFactor ||
3030 mPolygonOffsetUnits != state->polygonOffsetUnits)
3031 {
3032 mPolygonOffsetFactor = state->polygonOffsetFactor;
3033 mPolygonOffsetUnits = state->polygonOffsetUnits;
3034 mLocalDirtyBits.set(gl::state::DIRTY_BIT_POLYGON_OFFSET);
3035 }
3036
3037 if (extensions.polygonOffsetClampEXT)
3038 {
3039 get(GL_POLYGON_OFFSET_CLAMP_EXT, &state->polygonOffsetClamp);
3040 if (mPolygonOffsetClamp != state->polygonOffsetClamp)
3041 {
3042 mPolygonOffsetClamp = state->polygonOffsetClamp;
3043 mLocalDirtyBits.set(gl::state::DIRTY_BIT_POLYGON_OFFSET);
3044 }
3045 }
3046
3047 if (extensions.depthClampEXT)
3048 {
3049 get(GL_DEPTH_CLAMP_EXT, &state->enableDepthClamp);
3050 if (mDepthClampEnabled != state->enableDepthClamp)
3051 {
3052 mDepthClampEnabled = state->enableDepthClamp;
3053 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
3054 mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED);
3055 }
3056 }
3057
3058 get(GL_SAMPLE_COVERAGE_VALUE, &state->sampleCoverageValue);
3059 get(GL_SAMPLE_COVERAGE_INVERT, &state->sampleCoverageInvert);
3060 if (mSampleCoverageValue != state->sampleCoverageValue ||
3061 mSampleCoverageInvert != state->sampleCoverageInvert)
3062 {
3063 mSampleCoverageValue = state->sampleCoverageValue;
3064 mSampleCoverageInvert = state->sampleCoverageInvert;
3065 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_COVERAGE);
3066 }
3067
3068 get(GL_DITHER, &state->enableDither);
3069 if (mDitherEnabled != state->enableDither)
3070 {
3071 mDitherEnabled = state->enableDither;
3072 mLocalDirtyBits.set(gl::state::DIRTY_BIT_DITHER_ENABLED);
3073 }
3074
3075 if (extensions.polygonModeAny())
3076 {
3077 get(GL_POLYGON_MODE_NV, &state->polygonMode);
3078 if (mPolygonMode != gl::FromGLenum<gl::PolygonMode>(state->polygonMode))
3079 {
3080 mPolygonMode = gl::FromGLenum<gl::PolygonMode>(state->polygonMode);
3081 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
3082 mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE);
3083 }
3084
3085 if (extensions.polygonModeNV)
3086 {
3087 get(GL_POLYGON_OFFSET_POINT_NV, &state->enablePolygonOffsetPoint);
3088 if (mPolygonOffsetPointEnabled != state->enablePolygonOffsetPoint)
3089 {
3090 mPolygonOffsetPointEnabled = state->enablePolygonOffsetPoint;
3091 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
3092 mLocalExtendedDirtyBits.set(
3093 gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_POINT_ENABLED);
3094 }
3095 }
3096
3097 get(GL_POLYGON_OFFSET_LINE_NV, &state->enablePolygonOffsetLine);
3098 if (mPolygonOffsetLineEnabled != state->enablePolygonOffsetLine)
3099 {
3100 mPolygonOffsetLineEnabled = state->enablePolygonOffsetLine;
3101 mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
3102 mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED);
3103 }
3104 }
3105
3106 get(GL_POLYGON_OFFSET_FILL, &state->enablePolygonOffsetFill);
3107 if (mPolygonOffsetFillEnabled != state->enablePolygonOffsetFill)
3108 {
3109 mPolygonOffsetFillEnabled = state->enablePolygonOffsetFill;
3110 mLocalDirtyBits.set(gl::state::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
3111 }
3112
3113 get(GL_SAMPLE_ALPHA_TO_COVERAGE, &state->enableSampleAlphaToCoverage);
3114 if (mSampleAlphaToOneEnabled != state->enableSampleAlphaToCoverage)
3115 {
3116 mSampleAlphaToOneEnabled = state->enableSampleAlphaToCoverage;
3117 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
3118 }
3119
3120 get(GL_SAMPLE_COVERAGE, &state->enableSampleCoverage);
3121 if (mSampleCoverageEnabled != state->enableSampleCoverage)
3122 {
3123 mSampleCoverageEnabled = state->enableSampleCoverage;
3124 mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
3125 }
3126
3127 if (extensions.multisampleCompatibilityEXT)
3128 {
3129 get(GL_MULTISAMPLE, &state->multisampleEnabled);
3130 if (mMultisamplingEnabled != state->multisampleEnabled)
3131 {
3132 mMultisamplingEnabled = state->multisampleEnabled;
3133 mLocalDirtyBits.set(gl::state::DIRTY_BIT_MULTISAMPLING);
3134 }
3135 }
3136
3137 syncBlendFromNativeContext(extensions, state);
3138 syncFramebufferFromNativeContext(extensions, state);
3139 syncPixelPackUnpackFromNativeContext(extensions, state);
3140 syncStencilFromNativeContext(extensions, state);
3141 syncVertexArraysFromNativeContext(extensions, state);
3142 syncBufferBindingsFromNativeContext(extensions, state);
3143 syncTextureUnitsFromNativeContext(extensions, state);
3144
3145 ASSERT(mFunctions->getError() == GL_NO_ERROR);
3146
3147 double delta = platform->currentTime(platform) - startTime;
3148 int us = static_cast<int>(delta * 1000000.0);
3149 ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.SyncFromNativeContextMicroseconds", us);
3150 }
3151
restoreNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)3152 void StateManagerGL::restoreNativeContext(const gl::Extensions &extensions,
3153 const ExternalContextState *state)
3154 {
3155 ASSERT(mFunctions->getError() == GL_NO_ERROR);
3156
3157 setViewport(state->viewport);
3158 if (extensions.clipControlEXT)
3159 {
3160 setClipControl(gl::FromGLenum<gl::ClipOrigin>(state->clipOrigin),
3161 gl::FromGLenum<gl::ClipDepthMode>(state->clipDepthMode));
3162 }
3163
3164 setScissorTestEnabled(state->scissorTest);
3165 setScissor(state->scissorBox);
3166
3167 setDepthTestEnabled(state->depthTest);
3168
3169 setCullFaceEnabled(state->cullFace);
3170 setCullFace(gl::FromGLenum<gl::CullFaceMode>(state->cullFaceMode));
3171
3172 setColorMask(state->colorMask[0], state->colorMask[1], state->colorMask[2],
3173 state->colorMask[3]);
3174
3175 forceUseProgram(state->currentProgram);
3176
3177 setClearColor(state->colorClear);
3178
3179 setClearDepth(state->depthClear);
3180 setDepthFunc(state->depthFunc);
3181 setDepthMask(state->depthMask);
3182 setDepthRange(state->depthRage[0], state->depthRage[1]);
3183
3184 setFrontFace(state->frontFace);
3185
3186 setLineWidth(state->lineWidth);
3187
3188 setPolygonOffset(state->polygonOffsetFactor, state->polygonOffsetUnits,
3189 state->polygonOffsetClamp);
3190
3191 if (extensions.depthClampEXT)
3192 {
3193 setDepthClampEnabled(state->enableDepthClamp);
3194 }
3195
3196 setSampleCoverage(state->sampleCoverageValue, state->sampleCoverageInvert);
3197
3198 setDitherEnabled(state->enableDither);
3199
3200 if (extensions.polygonModeAny())
3201 {
3202 setPolygonMode(gl::FromGLenum<gl::PolygonMode>(state->polygonMode));
3203 if (extensions.polygonModeNV)
3204 {
3205 setPolygonOffsetPointEnabled(state->enablePolygonOffsetPoint);
3206 }
3207 setPolygonOffsetLineEnabled(state->enablePolygonOffsetLine);
3208 }
3209
3210 setPolygonOffsetFillEnabled(state->enablePolygonOffsetFill);
3211
3212 setSampleAlphaToOneStateEnabled(state->enableSampleAlphaToCoverage);
3213
3214 setSampleCoverageEnabled(state->enableSampleCoverage);
3215
3216 if (extensions.multisampleCompatibilityEXT)
3217 setMultisamplingStateEnabled(state->multisampleEnabled);
3218
3219 restoreBlendNativeContext(extensions, state);
3220 restoreFramebufferNativeContext(extensions, state);
3221 restorePixelPackUnpackNativeContext(extensions, state);
3222 restoreStencilNativeContext(extensions, state);
3223 restoreVertexArraysNativeContext(extensions, state);
3224 restoreBufferBindingsNativeContext(extensions, state);
3225 restoreTextureUnitsNativeContext(extensions, state);
3226
3227 // if (mFunctions->coverageModulationNV) ?
3228 setCoverageModulation(GL_NONE);
3229
3230 ASSERT(mFunctions->getError() == GL_NO_ERROR);
3231 }
3232
syncBlendFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)3233 void StateManagerGL::syncBlendFromNativeContext(const gl::Extensions &extensions,
3234 ExternalContextState *state)
3235 {
3236 get(GL_BLEND, &state->blendEnabled);
3237 if (mBlendStateExt.getEnabledMask() !=
3238 (state->blendEnabled ? mBlendStateExt.getAllEnabledMask() : gl::DrawBufferMask::Zero()))
3239 {
3240 mBlendStateExt.setEnabled(state->blendEnabled);
3241 mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_ENABLED);
3242 }
3243
3244 get(GL_BLEND_SRC_RGB, &state->blendSrcRgb);
3245 get(GL_BLEND_DST_RGB, &state->blendDestRgb);
3246 get(GL_BLEND_SRC_ALPHA, &state->blendSrcAlpha);
3247 get(GL_BLEND_DST_ALPHA, &state->blendDestAlpha);
3248 if (mBlendStateExt.getSrcColorBits() != mBlendStateExt.expandFactorValue(state->blendSrcRgb) ||
3249 mBlendStateExt.getDstColorBits() != mBlendStateExt.expandFactorValue(state->blendDestRgb) ||
3250 mBlendStateExt.getSrcAlphaBits() !=
3251 mBlendStateExt.expandFactorValue(state->blendSrcAlpha) ||
3252 mBlendStateExt.getDstAlphaBits() != mBlendStateExt.expandFactorValue(state->blendDestAlpha))
3253 {
3254 mBlendStateExt.setFactors(state->blendSrcRgb, state->blendDestRgb, state->blendSrcAlpha,
3255 state->blendDestAlpha);
3256 mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_FUNCS);
3257 }
3258
3259 get(GL_BLEND_COLOR, &state->blendColor);
3260 if (mBlendColor != state->blendColor)
3261 {
3262 mBlendColor = state->blendColor;
3263 mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_COLOR);
3264 }
3265
3266 get(GL_BLEND_EQUATION_RGB, &state->blendEquationRgb);
3267 get(GL_BLEND_EQUATION_ALPHA, &state->blendEquationAlpha);
3268 if (mBlendStateExt.getEquationColorBits() !=
3269 mBlendStateExt.expandEquationValue(state->blendEquationRgb) ||
3270 mBlendStateExt.getEquationAlphaBits() !=
3271 mBlendStateExt.expandEquationValue(state->blendEquationAlpha))
3272 {
3273 mBlendStateExt.setEquations(state->blendEquationRgb, state->blendEquationAlpha);
3274 mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_EQUATIONS);
3275 }
3276 }
3277
restoreBlendNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)3278 void StateManagerGL::restoreBlendNativeContext(const gl::Extensions &extensions,
3279 const ExternalContextState *state)
3280 {
3281 setBlendEnabled(state->blendEnabled);
3282
3283 mFunctions->blendFuncSeparate(state->blendSrcRgb, state->blendDestRgb, state->blendSrcAlpha,
3284 state->blendDestAlpha);
3285 mBlendStateExt.setFactors(state->blendSrcRgb, state->blendDestRgb, state->blendSrcAlpha,
3286 state->blendDestAlpha);
3287 mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_FUNCS);
3288
3289 setBlendColor(state->blendColor);
3290
3291 mFunctions->blendEquationSeparate(state->blendEquationRgb, state->blendEquationAlpha);
3292 mBlendStateExt.setEquations(state->blendEquationRgb, state->blendEquationAlpha);
3293 mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_EQUATIONS);
3294 }
3295
syncFramebufferFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)3296 void StateManagerGL::syncFramebufferFromNativeContext(const gl::Extensions &extensions,
3297 ExternalContextState *state)
3298 {
3299 // TODO: wrap fbo into an EGLSurface
3300 get(GL_FRAMEBUFFER_BINDING, &state->framebufferBinding);
3301 if (mFramebuffers[angle::FramebufferBindingDraw] !=
3302 static_cast<GLenum>(state->framebufferBinding))
3303 {
3304 mFramebuffers[angle::FramebufferBindingDraw] =
3305 static_cast<GLenum>(state->framebufferBinding);
3306 mLocalDirtyBits.set(gl::state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
3307 }
3308 if (mFramebuffers[angle::FramebufferBindingRead] !=
3309 static_cast<GLenum>(state->framebufferBinding))
3310 {
3311 mFramebuffers[angle::FramebufferBindingRead] =
3312 static_cast<GLenum>(state->framebufferBinding);
3313 mLocalDirtyBits.set(gl::state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
3314 }
3315 }
3316
restoreFramebufferNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)3317 void StateManagerGL::restoreFramebufferNativeContext(const gl::Extensions &extensions,
3318 const ExternalContextState *state)
3319 {
3320 bindFramebuffer(GL_FRAMEBUFFER, state->framebufferBinding);
3321 }
3322
syncPixelPackUnpackFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)3323 void StateManagerGL::syncPixelPackUnpackFromNativeContext(const gl::Extensions &extensions,
3324 ExternalContextState *state)
3325 {
3326 get(GL_PACK_ALIGNMENT, &state->packAlignment);
3327 if (mPackAlignment != state->packAlignment)
3328 {
3329 mPackAlignment = state->packAlignment;
3330 mLocalDirtyBits.set(gl::state::DIRTY_BIT_PACK_STATE);
3331 }
3332
3333 get(GL_UNPACK_ALIGNMENT, &state->unpackAlignment);
3334 if (mUnpackAlignment != state->unpackAlignment)
3335 {
3336 mUnpackAlignment = state->unpackAlignment;
3337 mLocalDirtyBits.set(gl::state::DIRTY_BIT_UNPACK_STATE);
3338 }
3339 }
3340
restorePixelPackUnpackNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)3341 void StateManagerGL::restorePixelPackUnpackNativeContext(const gl::Extensions &extensions,
3342 const ExternalContextState *state)
3343 {
3344 if (mPackAlignment != state->packAlignment)
3345 {
3346 mFunctions->pixelStorei(GL_PACK_ALIGNMENT, state->packAlignment);
3347 mPackAlignment = state->packAlignment;
3348 mLocalDirtyBits.set(gl::state::DIRTY_BIT_PACK_STATE);
3349 }
3350
3351 if (mUnpackAlignment != state->unpackAlignment)
3352 {
3353 mFunctions->pixelStorei(GL_UNPACK_ALIGNMENT, state->unpackAlignment);
3354 mUnpackAlignment = state->unpackAlignment;
3355 mLocalDirtyBits.set(gl::state::DIRTY_BIT_UNPACK_STATE);
3356 }
3357 }
3358
syncStencilFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)3359 void StateManagerGL::syncStencilFromNativeContext(const gl::Extensions &extensions,
3360 ExternalContextState *state)
3361 {
3362 get(GL_STENCIL_TEST, &state->stencilState.stencilTestEnabled);
3363 if (state->stencilState.stencilTestEnabled != mStencilTestEnabled)
3364 {
3365 mStencilTestEnabled = state->stencilState.stencilTestEnabled;
3366 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_TEST_ENABLED);
3367 }
3368
3369 get(GL_STENCIL_FUNC, &state->stencilState.stencilFrontFunc);
3370 get(GL_STENCIL_VALUE_MASK, &state->stencilState.stencilFrontMask);
3371 get(GL_STENCIL_REF, &state->stencilState.stencilFrontRef);
3372 if (state->stencilState.stencilFrontFunc != mStencilFrontFunc ||
3373 state->stencilState.stencilFrontMask != mStencilFrontValueMask ||
3374 state->stencilState.stencilFrontRef != mStencilFrontRef)
3375 {
3376 mStencilFrontFunc = state->stencilState.stencilFrontFunc;
3377 mStencilFrontValueMask = state->stencilState.stencilFrontMask;
3378 mStencilFrontRef = state->stencilState.stencilFrontRef;
3379 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT);
3380 }
3381
3382 get(GL_STENCIL_BACK_FUNC, &state->stencilState.stencilBackFunc);
3383 get(GL_STENCIL_BACK_VALUE_MASK, &state->stencilState.stencilBackMask);
3384 get(GL_STENCIL_BACK_REF, &state->stencilState.stencilBackRef);
3385 if (state->stencilState.stencilBackFunc != mStencilBackFunc ||
3386 state->stencilState.stencilBackMask != mStencilBackValueMask ||
3387 state->stencilState.stencilBackRef != mStencilBackRef)
3388 {
3389 mStencilBackFunc = state->stencilState.stencilBackFunc;
3390 mStencilBackValueMask = state->stencilState.stencilBackMask;
3391 mStencilBackRef = state->stencilState.stencilBackRef;
3392 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK);
3393 }
3394
3395 get(GL_STENCIL_CLEAR_VALUE, &state->stencilState.stencilClear);
3396 if (mClearStencil != state->stencilState.stencilClear)
3397 {
3398 mClearStencil = state->stencilState.stencilClear;
3399 mLocalDirtyBits.set(gl::state::DIRTY_BIT_CLEAR_STENCIL);
3400 }
3401
3402 get(GL_STENCIL_WRITEMASK, &state->stencilState.stencilFrontWritemask);
3403 if (mStencilFrontWritemask != static_cast<GLenum>(state->stencilState.stencilFrontWritemask))
3404 {
3405 mStencilFrontWritemask = state->stencilState.stencilFrontWritemask;
3406 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
3407 }
3408
3409 get(GL_STENCIL_BACK_WRITEMASK, &state->stencilState.stencilBackWritemask);
3410 if (mStencilBackWritemask != static_cast<GLenum>(state->stencilState.stencilBackWritemask))
3411 {
3412 mStencilBackWritemask = state->stencilState.stencilBackWritemask;
3413 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
3414 }
3415
3416 get(GL_STENCIL_FAIL, &state->stencilState.stencilFrontFailOp);
3417 get(GL_STENCIL_PASS_DEPTH_FAIL, &state->stencilState.stencilFrontZFailOp);
3418 get(GL_STENCIL_PASS_DEPTH_PASS, &state->stencilState.stencilFrontZPassOp);
3419 if (mStencilFrontStencilFailOp != static_cast<GLenum>(state->stencilState.stencilFrontFailOp) ||
3420 mStencilFrontStencilPassDepthFailOp !=
3421 static_cast<GLenum>(state->stencilState.stencilFrontZFailOp) ||
3422 mStencilFrontStencilPassDepthPassOp !=
3423 static_cast<GLenum>(state->stencilState.stencilFrontZPassOp))
3424 {
3425 mStencilFrontStencilFailOp = static_cast<GLenum>(state->stencilState.stencilFrontFailOp);
3426 mStencilFrontStencilPassDepthFailOp =
3427 static_cast<GLenum>(state->stencilState.stencilFrontZFailOp);
3428 mStencilFrontStencilPassDepthPassOp =
3429 static_cast<GLenum>(state->stencilState.stencilFrontZPassOp);
3430 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_OPS_FRONT);
3431 }
3432
3433 get(GL_STENCIL_BACK_FAIL, &state->stencilState.stencilBackFailOp);
3434 get(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &state->stencilState.stencilBackZFailOp);
3435 get(GL_STENCIL_BACK_PASS_DEPTH_PASS, &state->stencilState.stencilBackZPassOp);
3436 if (mStencilBackStencilFailOp != static_cast<GLenum>(state->stencilState.stencilBackFailOp) ||
3437 mStencilBackStencilPassDepthFailOp !=
3438 static_cast<GLenum>(state->stencilState.stencilBackZFailOp) ||
3439 mStencilBackStencilPassDepthPassOp !=
3440 static_cast<GLenum>(state->stencilState.stencilBackZPassOp))
3441 {
3442 mStencilBackStencilFailOp = static_cast<GLenum>(state->stencilState.stencilBackFailOp);
3443 mStencilBackStencilPassDepthFailOp =
3444 static_cast<GLenum>(state->stencilState.stencilBackZFailOp);
3445 mStencilBackStencilPassDepthPassOp =
3446 static_cast<GLenum>(state->stencilState.stencilBackZPassOp);
3447 mLocalDirtyBits.set(gl::state::DIRTY_BIT_STENCIL_OPS_BACK);
3448 }
3449 }
3450
restoreStencilNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)3451 void StateManagerGL::restoreStencilNativeContext(const gl::Extensions &extensions,
3452 const ExternalContextState *state)
3453 {
3454 setStencilTestEnabled(state->stencilState.stencilTestEnabled);
3455 setStencilFrontFuncs(state->stencilState.stencilFrontFunc, state->stencilState.stencilFrontMask,
3456 state->stencilState.stencilFrontRef);
3457 setStencilBackFuncs(state->stencilState.stencilBackFunc, state->stencilState.stencilBackMask,
3458 state->stencilState.stencilBackRef);
3459 setClearStencil(state->stencilState.stencilClear);
3460 setStencilFrontWritemask(state->stencilState.stencilFrontWritemask);
3461 setStencilBackWritemask(state->stencilState.stencilBackWritemask);
3462 setStencilFrontOps(state->stencilState.stencilFrontFailOp,
3463 state->stencilState.stencilFrontZFailOp,
3464 state->stencilState.stencilFrontZPassOp);
3465 setStencilBackOps(state->stencilState.stencilBackFailOp, state->stencilState.stencilBackZFailOp,
3466 state->stencilState.stencilBackZPassOp);
3467 }
3468
syncBufferBindingsFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)3469 void StateManagerGL::syncBufferBindingsFromNativeContext(const gl::Extensions &extensions,
3470 ExternalContextState *state)
3471 {
3472 get(GL_ARRAY_BUFFER_BINDING, &state->vertexArrayBufferBinding);
3473 mBuffers[gl::BufferBinding::Array] = state->vertexArrayBufferBinding;
3474
3475 get(GL_ELEMENT_ARRAY_BUFFER_BINDING, &state->elementArrayBufferBinding);
3476 mBuffers[gl::BufferBinding::ElementArray] = state->elementArrayBufferBinding;
3477 }
3478
restoreBufferBindingsNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)3479 void StateManagerGL::restoreBufferBindingsNativeContext(const gl::Extensions &extensions,
3480 const ExternalContextState *state)
3481 {
3482 bindBuffer(gl::BufferBinding::Array, state->vertexArrayBufferBinding);
3483 bindBuffer(gl::BufferBinding::ElementArray, state->elementArrayBufferBinding);
3484 }
3485
syncTextureUnitsFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)3486 void StateManagerGL::syncTextureUnitsFromNativeContext(const gl::Extensions &extensions,
3487 ExternalContextState *state)
3488 {
3489 get(GL_ACTIVE_TEXTURE, &state->activeTexture);
3490
3491 for (size_t i = 0; i < state->textureBindings.size(); ++i)
3492 {
3493 auto &bindings = state->textureBindings[i];
3494 activeTexture(i);
3495 get(GL_TEXTURE_BINDING_2D, &bindings.texture2d);
3496 get(GL_TEXTURE_BINDING_CUBE_MAP, &bindings.textureCubeMap);
3497 get(GL_TEXTURE_BINDING_EXTERNAL_OES, &bindings.textureExternalOES);
3498 if (mTextures[gl::TextureType::_2D][i] != static_cast<GLuint>(bindings.texture2d) ||
3499 mTextures[gl::TextureType::CubeMap][i] !=
3500 static_cast<GLuint>(bindings.textureCubeMap) ||
3501 mTextures[gl::TextureType::External][i] !=
3502 static_cast<GLuint>(bindings.textureExternalOES))
3503 {
3504 mTextures[gl::TextureType::_2D][i] = bindings.texture2d;
3505 mTextures[gl::TextureType::CubeMap][i] = bindings.textureCubeMap;
3506 mTextures[gl::TextureType::External][i] = bindings.textureExternalOES;
3507 mLocalDirtyBits.set(gl::state::DIRTY_BIT_TEXTURE_BINDINGS);
3508 }
3509 }
3510 }
3511
restoreTextureUnitsNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)3512 void StateManagerGL::restoreTextureUnitsNativeContext(const gl::Extensions &extensions,
3513 const ExternalContextState *state)
3514 {
3515 for (size_t i = 0; i < state->textureBindings.size(); ++i)
3516 {
3517 const auto &bindings = state->textureBindings[i];
3518 activeTexture(i);
3519 bindTexture(gl::TextureType::_2D, bindings.texture2d);
3520 bindTexture(gl::TextureType::CubeMap, bindings.textureCubeMap);
3521 bindTexture(gl::TextureType::External, bindings.textureExternalOES);
3522 bindSampler(i, 0);
3523 }
3524 activeTexture(state->activeTexture - GL_TEXTURE0);
3525 }
3526
syncVertexArraysFromNativeContext(const gl::Extensions & extensions,ExternalContextState * state)3527 void StateManagerGL::syncVertexArraysFromNativeContext(const gl::Extensions &extensions,
3528 ExternalContextState *state)
3529 {
3530 if (mSupportsVertexArrayObjects)
3531 {
3532 get(GL_VERTEX_ARRAY_BINDING, &state->vertexArrayBinding);
3533 if (mVAO != static_cast<GLuint>(state->vertexArrayBinding))
3534 {
3535 mVAO = state->vertexArrayBinding;
3536 mBuffers[gl::BufferBinding::ElementArray] = 0;
3537 mLocalDirtyBits.set(gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING);
3538 }
3539 }
3540 }
3541
restoreVertexArraysNativeContext(const gl::Extensions & extensions,const ExternalContextState * state)3542 void StateManagerGL::restoreVertexArraysNativeContext(const gl::Extensions &extensions,
3543 const ExternalContextState *state)
3544 {
3545 if (mSupportsVertexArrayObjects)
3546 {
3547 bindVertexArray(state->vertexArrayBinding, 0);
3548 }
3549 }
3550
setDefaultVAOStateDirty()3551 void StateManagerGL::setDefaultVAOStateDirty()
3552 {
3553 mLocalDirtyBits.set(gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING);
3554 }
3555
3556 } // namespace rx
3557