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