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