1 //
2 // Copyright (c) 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 <limits>
12 #include <string.h>
13
14 #include "common/BitSetIterator.h"
15 #include "common/mathutil.h"
16 #include "common/matrix_utils.h"
17 #include "libANGLE/ContextState.h"
18 #include "libANGLE/Framebuffer.h"
19 #include "libANGLE/TransformFeedback.h"
20 #include "libANGLE/VertexArray.h"
21 #include "libANGLE/Query.h"
22 #include "libANGLE/renderer/gl/BufferGL.h"
23 #include "libANGLE/renderer/gl/FramebufferGL.h"
24 #include "libANGLE/renderer/gl/FunctionsGL.h"
25 #include "libANGLE/renderer/gl/ProgramGL.h"
26 #include "libANGLE/renderer/gl/SamplerGL.h"
27 #include "libANGLE/renderer/gl/TextureGL.h"
28 #include "libANGLE/renderer/gl/TransformFeedbackGL.h"
29 #include "libANGLE/renderer/gl/VertexArrayGL.h"
30 #include "libANGLE/renderer/gl/QueryGL.h"
31
32 namespace rx
33 {
34
35 static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
36 GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED,
37 GL_COMMANDS_COMPLETED_CHROMIUM};
38
IndexedBufferBinding()39 StateManagerGL::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0)
40 {
41 }
42
StateManagerGL(const FunctionsGL * functions,const gl::Caps & rendererCaps)43 StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &rendererCaps)
44 : mFunctions(functions),
45 mProgram(0),
46 mVAO(0),
47 mVertexAttribCurrentValues(rendererCaps.maxVertexAttributes),
48 mBuffers(),
49 mIndexedBuffers(),
50 mTextureUnitIndex(0),
51 mTextures(),
52 mSamplers(rendererCaps.maxCombinedTextureImageUnits, 0),
53 mTransformFeedback(0),
54 mQueries(),
55 mPrevDrawTransformFeedback(nullptr),
56 mCurrentQueries(),
57 mPrevDrawContext(0),
58 mUnpackAlignment(4),
59 mUnpackRowLength(0),
60 mUnpackSkipRows(0),
61 mUnpackSkipPixels(0),
62 mUnpackImageHeight(0),
63 mUnpackSkipImages(0),
64 mPackAlignment(4),
65 mPackRowLength(0),
66 mPackSkipRows(0),
67 mPackSkipPixels(0),
68 mFramebuffers(angle::FramebufferBindingSingletonMax, 0),
69 mRenderbuffer(0),
70 mScissorTestEnabled(false),
71 mScissor(0, 0, 0, 0),
72 mViewport(0, 0, 0, 0),
73 mNear(0.0f),
74 mFar(1.0f),
75 mBlendEnabled(false),
76 mBlendColor(0, 0, 0, 0),
77 mSourceBlendRGB(GL_ONE),
78 mDestBlendRGB(GL_ZERO),
79 mSourceBlendAlpha(GL_ONE),
80 mDestBlendAlpha(GL_ZERO),
81 mBlendEquationRGB(GL_FUNC_ADD),
82 mBlendEquationAlpha(GL_FUNC_ADD),
83 mColorMaskRed(true),
84 mColorMaskGreen(true),
85 mColorMaskBlue(true),
86 mColorMaskAlpha(true),
87 mSampleAlphaToCoverageEnabled(false),
88 mSampleCoverageEnabled(false),
89 mSampleCoverageValue(1.0f),
90 mSampleCoverageInvert(false),
91 mDepthTestEnabled(false),
92 mDepthFunc(GL_LESS),
93 mDepthMask(true),
94 mStencilTestEnabled(false),
95 mStencilFrontFunc(GL_ALWAYS),
96 mStencilFrontRef(0),
97 mStencilFrontValueMask(static_cast<GLuint>(-1)),
98 mStencilFrontStencilFailOp(GL_KEEP),
99 mStencilFrontStencilPassDepthFailOp(GL_KEEP),
100 mStencilFrontStencilPassDepthPassOp(GL_KEEP),
101 mStencilFrontWritemask(static_cast<GLuint>(-1)),
102 mStencilBackFunc(GL_ALWAYS),
103 mStencilBackRef(0),
104 mStencilBackValueMask(static_cast<GLuint>(-1)),
105 mStencilBackStencilFailOp(GL_KEEP),
106 mStencilBackStencilPassDepthFailOp(GL_KEEP),
107 mStencilBackStencilPassDepthPassOp(GL_KEEP),
108 mStencilBackWritemask(static_cast<GLuint>(-1)),
109 mCullFaceEnabled(false),
110 mCullFace(GL_BACK),
111 mFrontFace(GL_CCW),
112 mPolygonOffsetFillEnabled(false),
113 mPolygonOffsetFactor(0.0f),
114 mPolygonOffsetUnits(0.0f),
115 mRasterizerDiscardEnabled(false),
116 mLineWidth(1.0f),
117 mPrimitiveRestartEnabled(false),
118 mClearColor(0.0f, 0.0f, 0.0f, 0.0f),
119 mClearDepth(1.0f),
120 mClearStencil(0),
121 mFramebufferSRGBEnabled(false),
122 mDitherEnabled(true),
123 mTextureCubemapSeamlessEnabled(false),
124 mMultisamplingEnabled(true),
125 mSampleAlphaToOneEnabled(false),
126 mCoverageModulation(GL_NONE),
127 mPathStencilFunc(GL_ALWAYS),
128 mPathStencilRef(0),
129 mPathStencilMask(std::numeric_limits<GLuint>::max()),
130 mLocalDirtyBits()
131 {
132 ASSERT(mFunctions);
133
134 mTextures[GL_TEXTURE_2D].resize(rendererCaps.maxCombinedTextureImageUnits);
135 mTextures[GL_TEXTURE_CUBE_MAP].resize(rendererCaps.maxCombinedTextureImageUnits);
136 mTextures[GL_TEXTURE_2D_ARRAY].resize(rendererCaps.maxCombinedTextureImageUnits);
137 mTextures[GL_TEXTURE_3D].resize(rendererCaps.maxCombinedTextureImageUnits);
138
139 mIndexedBuffers[GL_UNIFORM_BUFFER].resize(rendererCaps.maxCombinedUniformBlocks);
140
141 for (GLenum queryType : QueryTypes)
142 {
143 mQueries[queryType] = 0;
144 }
145
146 // Initialize point sprite state for desktop GL
147 if (mFunctions->standard == STANDARD_GL_DESKTOP)
148 {
149 mFunctions->enable(GL_PROGRAM_POINT_SIZE);
150
151 // GL_POINT_SPRITE was deprecated in the core profile. Point rasterization is always
152 // performed
153 // as though POINT_SPRITE were enabled.
154 if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) == 0)
155 {
156 mFunctions->enable(GL_POINT_SPRITE);
157 }
158 }
159
160 angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
161 angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
162 }
163
deleteProgram(GLuint program)164 void StateManagerGL::deleteProgram(GLuint program)
165 {
166 if (program != 0)
167 {
168 if (mProgram == program)
169 {
170 useProgram(0);
171 }
172
173 mFunctions->deleteProgram(program);
174 }
175 }
176
deleteVertexArray(GLuint vao)177 void StateManagerGL::deleteVertexArray(GLuint vao)
178 {
179 if (vao != 0)
180 {
181 if (mVAO == vao)
182 {
183 bindVertexArray(0, 0);
184 }
185
186 mFunctions->deleteVertexArrays(1, &vao);
187 }
188 }
189
deleteTexture(GLuint texture)190 void StateManagerGL::deleteTexture(GLuint texture)
191 {
192 if (texture != 0)
193 {
194 for (const auto &textureTypeIter : mTextures)
195 {
196 const std::vector<GLuint> &textureVector = textureTypeIter.second;
197 for (size_t textureUnitIndex = 0; textureUnitIndex < textureVector.size(); textureUnitIndex++)
198 {
199 if (textureVector[textureUnitIndex] == texture)
200 {
201 activeTexture(textureUnitIndex);
202 bindTexture(textureTypeIter.first, 0);
203 }
204 }
205 }
206
207 mFunctions->deleteTextures(1, &texture);
208 }
209 }
210
deleteSampler(GLuint sampler)211 void StateManagerGL::deleteSampler(GLuint sampler)
212 {
213 if (sampler != 0)
214 {
215 for (size_t unit = 0; unit < mSamplers.size(); unit++)
216 {
217 if (mSamplers[unit] == sampler)
218 {
219 bindSampler(unit, 0);
220 }
221 }
222
223 mFunctions->deleteSamplers(1, &sampler);
224 }
225 }
226
deleteBuffer(GLuint buffer)227 void StateManagerGL::deleteBuffer(GLuint buffer)
228 {
229 if (buffer != 0)
230 {
231 for (const auto &bufferTypeIter : mBuffers)
232 {
233 if (bufferTypeIter.second == buffer)
234 {
235 bindBuffer(bufferTypeIter.first, 0);
236 }
237 }
238
239 for (const auto &bufferTypeIter : mIndexedBuffers)
240 {
241 for (size_t bindIndex = 0; bindIndex < bufferTypeIter.second.size(); bindIndex++)
242 {
243 if (bufferTypeIter.second[bindIndex].buffer == buffer)
244 {
245 bindBufferBase(bufferTypeIter.first, bindIndex, 0);
246 }
247 }
248 }
249
250 mFunctions->deleteBuffers(1, &buffer);
251 }
252 }
253
deleteFramebuffer(GLuint fbo)254 void StateManagerGL::deleteFramebuffer(GLuint fbo)
255 {
256 if (fbo != 0)
257 {
258 for (size_t binding = 0; binding < mFramebuffers.size(); ++binding)
259 {
260 if (mFramebuffers[binding] == fbo)
261 {
262 GLenum enumValue = angle::FramebufferBindingToEnum(
263 static_cast<angle::FramebufferBinding>(binding));
264 bindFramebuffer(enumValue, 0);
265 }
266 mFunctions->deleteFramebuffers(1, &fbo);
267 }
268 }
269 }
270
deleteRenderbuffer(GLuint rbo)271 void StateManagerGL::deleteRenderbuffer(GLuint rbo)
272 {
273 if (rbo != 0)
274 {
275 if (mRenderbuffer == rbo)
276 {
277 bindRenderbuffer(GL_RENDERBUFFER, 0);
278 }
279
280 mFunctions->deleteRenderbuffers(1, &rbo);
281 }
282 }
283
deleteTransformFeedback(GLuint transformFeedback)284 void StateManagerGL::deleteTransformFeedback(GLuint transformFeedback)
285 {
286 if (transformFeedback != 0)
287 {
288 if (mTransformFeedback == transformFeedback)
289 {
290 bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
291 }
292
293 if (mPrevDrawTransformFeedback != nullptr &&
294 mPrevDrawTransformFeedback->getTransformFeedbackID() == transformFeedback)
295 {
296 mPrevDrawTransformFeedback = nullptr;
297 }
298
299 mFunctions->deleteTransformFeedbacks(1, &transformFeedback);
300 }
301 }
302
deleteQuery(GLuint query)303 void StateManagerGL::deleteQuery(GLuint query)
304 {
305 if (query != 0)
306 {
307 for (auto &activeQuery : mQueries)
308 {
309 GLuint activeQueryID = activeQuery.second;
310 if (activeQueryID == query)
311 {
312 GLenum type = activeQuery.first;
313 endQuery(type, query);
314 }
315 }
316 }
317 }
318
useProgram(GLuint program)319 void StateManagerGL::useProgram(GLuint program)
320 {
321 if (mProgram != program)
322 {
323 forceUseProgram(program);
324 }
325 }
326
forceUseProgram(GLuint program)327 void StateManagerGL::forceUseProgram(GLuint program)
328 {
329 mProgram = program;
330 mFunctions->useProgram(mProgram);
331 }
332
bindVertexArray(GLuint vao,GLuint elementArrayBuffer)333 void StateManagerGL::bindVertexArray(GLuint vao, GLuint elementArrayBuffer)
334 {
335 if (mVAO != vao)
336 {
337 mVAO = vao;
338 mBuffers[GL_ELEMENT_ARRAY_BUFFER] = elementArrayBuffer;
339 mFunctions->bindVertexArray(vao);
340 }
341 }
342
bindBuffer(GLenum type,GLuint buffer)343 void StateManagerGL::bindBuffer(GLenum type, GLuint buffer)
344 {
345 if (mBuffers[type] != buffer)
346 {
347 mBuffers[type] = buffer;
348 mFunctions->bindBuffer(type, buffer);
349 }
350 }
351
bindBufferBase(GLenum type,size_t index,GLuint buffer)352 void StateManagerGL::bindBufferBase(GLenum type, size_t index, GLuint buffer)
353 {
354 auto &binding = mIndexedBuffers[type][index];
355 if (binding.buffer != buffer || binding.offset != static_cast<size_t>(-1) ||
356 binding.size != static_cast<size_t>(-1))
357 {
358 binding.buffer = buffer;
359 binding.offset = static_cast<size_t>(-1);
360 binding.size = static_cast<size_t>(-1);
361 mFunctions->bindBufferBase(type, static_cast<GLuint>(index), buffer);
362 }
363 }
364
bindBufferRange(GLenum type,size_t index,GLuint buffer,size_t offset,size_t size)365 void StateManagerGL::bindBufferRange(GLenum type,
366 size_t index,
367 GLuint buffer,
368 size_t offset,
369 size_t size)
370 {
371 auto &binding = mIndexedBuffers[type][index];
372 if (binding.buffer != buffer || binding.offset != offset || binding.size != size)
373 {
374 binding.buffer = buffer;
375 binding.offset = offset;
376 binding.size = size;
377 mFunctions->bindBufferRange(type, static_cast<GLuint>(index), buffer, offset, size);
378 }
379 }
380
activeTexture(size_t unit)381 void StateManagerGL::activeTexture(size_t unit)
382 {
383 if (mTextureUnitIndex != unit)
384 {
385 mTextureUnitIndex = unit;
386 mFunctions->activeTexture(GL_TEXTURE0 + static_cast<GLenum>(mTextureUnitIndex));
387 }
388 }
389
bindTexture(GLenum type,GLuint texture)390 void StateManagerGL::bindTexture(GLenum type, GLuint texture)
391 {
392 if (mTextures[type][mTextureUnitIndex] != texture)
393 {
394 mTextures[type][mTextureUnitIndex] = texture;
395 mFunctions->bindTexture(type, texture);
396 }
397 }
398
bindSampler(size_t unit,GLuint sampler)399 void StateManagerGL::bindSampler(size_t unit, GLuint sampler)
400 {
401 if (mSamplers[unit] != sampler)
402 {
403 mSamplers[unit] = sampler;
404 mFunctions->bindSampler(static_cast<GLuint>(unit), sampler);
405 }
406 }
407
setPixelUnpackState(const gl::PixelUnpackState & unpack)408 void StateManagerGL::setPixelUnpackState(const gl::PixelUnpackState &unpack)
409 {
410 GLuint unpackBufferID = 0;
411 const gl::Buffer *unpackBuffer = unpack.pixelBuffer.get();
412 if (unpackBuffer != nullptr)
413 {
414 unpackBufferID = GetImplAs<BufferGL>(unpackBuffer)->getBufferID();
415 }
416 setPixelUnpackState(unpack.alignment, unpack.rowLength, unpack.skipRows, unpack.skipPixels,
417 unpack.imageHeight, unpack.skipImages, unpackBufferID);
418 }
419
setPixelUnpackState(GLint alignment,GLint rowLength,GLint skipRows,GLint skipPixels,GLint imageHeight,GLint skipImages,GLuint unpackBuffer)420 void StateManagerGL::setPixelUnpackState(GLint alignment,
421 GLint rowLength,
422 GLint skipRows,
423 GLint skipPixels,
424 GLint imageHeight,
425 GLint skipImages,
426 GLuint unpackBuffer)
427 {
428 if (mUnpackAlignment != alignment)
429 {
430 mUnpackAlignment = alignment;
431 mFunctions->pixelStorei(GL_UNPACK_ALIGNMENT, mUnpackAlignment);
432
433 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_ALIGNMENT);
434 }
435
436 if (mUnpackRowLength != rowLength)
437 {
438 mUnpackRowLength = rowLength;
439 mFunctions->pixelStorei(GL_UNPACK_ROW_LENGTH, mUnpackRowLength);
440
441 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH);
442 }
443
444 if (mUnpackSkipRows != skipRows)
445 {
446 mUnpackSkipRows = skipRows;
447 mFunctions->pixelStorei(GL_UNPACK_SKIP_ROWS, mUnpackSkipRows);
448
449 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_SKIP_ROWS);
450 }
451
452 if (mUnpackSkipPixels != skipPixels)
453 {
454 mUnpackSkipPixels = skipPixels;
455 mFunctions->pixelStorei(GL_UNPACK_SKIP_PIXELS, mUnpackSkipPixels);
456
457 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_SKIP_PIXELS);
458 }
459
460 if (mUnpackImageHeight != imageHeight)
461 {
462 mUnpackImageHeight = imageHeight;
463 mFunctions->pixelStorei(GL_UNPACK_IMAGE_HEIGHT, mUnpackImageHeight);
464
465 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
466 }
467
468 if (mUnpackSkipImages != skipImages)
469 {
470 mUnpackSkipImages = skipImages;
471 mFunctions->pixelStorei(GL_UNPACK_SKIP_IMAGES, mUnpackSkipImages);
472
473 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_SKIP_IMAGES);
474 }
475
476 bindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
477 }
478
setPixelPackState(const gl::PixelPackState & pack)479 void StateManagerGL::setPixelPackState(const gl::PixelPackState &pack)
480 {
481 GLuint packBufferID = 0;
482 const gl::Buffer *packBuffer = pack.pixelBuffer.get();
483 if (packBuffer != nullptr)
484 {
485 packBufferID = GetImplAs<BufferGL>(packBuffer)->getBufferID();
486 }
487 setPixelPackState(pack.alignment, pack.rowLength, pack.skipRows, pack.skipPixels, packBufferID);
488 }
489
setPixelPackState(GLint alignment,GLint rowLength,GLint skipRows,GLint skipPixels,GLuint packBuffer)490 void StateManagerGL::setPixelPackState(GLint alignment,
491 GLint rowLength,
492 GLint skipRows,
493 GLint skipPixels,
494 GLuint packBuffer)
495 {
496 if (mPackAlignment != alignment)
497 {
498 mPackAlignment = alignment;
499 mFunctions->pixelStorei(GL_PACK_ALIGNMENT, mPackAlignment);
500
501 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_ALIGNMENT);
502 }
503
504 if (mPackRowLength != rowLength)
505 {
506 mPackRowLength = rowLength;
507 mFunctions->pixelStorei(GL_PACK_ROW_LENGTH, mPackRowLength);
508
509 mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH);
510 }
511
512 if (mPackSkipRows != skipRows)
513 {
514 mPackSkipRows = skipRows;
515 mFunctions->pixelStorei(GL_PACK_SKIP_ROWS, mPackSkipRows);
516
517 // TODO: set dirty bit once one exists
518 }
519
520 if (mPackSkipPixels != skipPixels)
521 {
522 mPackSkipPixels = skipPixels;
523 mFunctions->pixelStorei(GL_PACK_SKIP_PIXELS, mPackSkipPixels);
524
525 // TODO: set dirty bit once one exists
526 }
527
528 bindBuffer(GL_PIXEL_PACK_BUFFER, packBuffer);
529 }
530
bindFramebuffer(GLenum type,GLuint framebuffer)531 void StateManagerGL::bindFramebuffer(GLenum type, GLuint framebuffer)
532 {
533 if (type == GL_FRAMEBUFFER)
534 {
535 if (mFramebuffers[angle::FramebufferBindingRead] != framebuffer ||
536 mFramebuffers[angle::FramebufferBindingDraw] != framebuffer)
537 {
538 mFramebuffers[angle::FramebufferBindingRead] = framebuffer;
539 mFramebuffers[angle::FramebufferBindingDraw] = framebuffer;
540 mFunctions->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
541 }
542 }
543 else
544 {
545 angle::FramebufferBinding binding = angle::EnumToFramebufferBinding(type);
546
547 if (mFramebuffers[binding] != framebuffer)
548 {
549 mFramebuffers[binding] = framebuffer;
550 mFunctions->bindFramebuffer(type, framebuffer);
551 }
552 }
553 }
554
bindRenderbuffer(GLenum type,GLuint renderbuffer)555 void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer)
556 {
557 ASSERT(type == GL_RENDERBUFFER);
558 if (mRenderbuffer != renderbuffer)
559 {
560 mRenderbuffer = renderbuffer;
561 mFunctions->bindRenderbuffer(type, mRenderbuffer);
562 }
563 }
564
bindTransformFeedback(GLenum type,GLuint transformFeedback)565 void StateManagerGL::bindTransformFeedback(GLenum type, GLuint transformFeedback)
566 {
567 ASSERT(type == GL_TRANSFORM_FEEDBACK);
568 if (mTransformFeedback != transformFeedback)
569 {
570 // Pause the current transform feedback if one is active.
571 // To handle virtualized contexts, StateManagerGL needs to be able to bind a new transform
572 // feedback at any time, even if there is one active.
573 if (mPrevDrawTransformFeedback != nullptr &&
574 mPrevDrawTransformFeedback->getTransformFeedbackID() != transformFeedback)
575 {
576 mPrevDrawTransformFeedback->syncPausedState(true);
577 mPrevDrawTransformFeedback = nullptr;
578 }
579
580 mTransformFeedback = transformFeedback;
581 mFunctions->bindTransformFeedback(type, mTransformFeedback);
582 }
583 }
584
beginQuery(GLenum type,GLuint query)585 void StateManagerGL::beginQuery(GLenum type, GLuint query)
586 {
587 // Make sure this is a valid query type and there is no current active query of this type
588 ASSERT(mQueries.find(type) != mQueries.end());
589 ASSERT(mQueries[type] == 0);
590 ASSERT(query != 0);
591
592 mQueries[type] = query;
593 mFunctions->beginQuery(type, query);
594 }
595
endQuery(GLenum type,GLuint query)596 void StateManagerGL::endQuery(GLenum type, GLuint query)
597 {
598 ASSERT(mQueries[type] == query);
599 mQueries[type] = 0;
600 mFunctions->endQuery(type);
601 }
602
onBeginQuery(QueryGL * query)603 void StateManagerGL::onBeginQuery(QueryGL *query)
604 {
605 mCurrentQueries.insert(query);
606 }
607
onDeleteQueryObject(QueryGL * query)608 void StateManagerGL::onDeleteQueryObject(QueryGL *query)
609 {
610 mCurrentQueries.erase(query);
611 }
612
setDrawArraysState(const gl::ContextState & data,GLint first,GLsizei count,GLsizei instanceCount)613 gl::Error StateManagerGL::setDrawArraysState(const gl::ContextState &data,
614 GLint first,
615 GLsizei count,
616 GLsizei instanceCount)
617 {
618 const gl::State &state = data.getState();
619
620 const gl::Program *program = state.getProgram();
621
622 const gl::VertexArray *vao = state.getVertexArray();
623 const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
624
625 gl::Error error = vaoGL->syncDrawArraysState(program->getActiveAttribLocationsMask(), first,
626 count, instanceCount);
627 if (error.isError())
628 {
629 return error;
630 }
631
632 bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
633
634 return setGenericDrawState(data);
635 }
636
setDrawElementsState(const gl::ContextState & data,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instanceCount,const GLvoid ** outIndices)637 gl::Error StateManagerGL::setDrawElementsState(const gl::ContextState &data,
638 GLsizei count,
639 GLenum type,
640 const GLvoid *indices,
641 GLsizei instanceCount,
642 const GLvoid **outIndices)
643 {
644 const gl::State &state = data.getState();
645
646 const gl::Program *program = state.getProgram();
647
648 const gl::VertexArray *vao = state.getVertexArray();
649 const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
650
651 gl::Error error =
652 vaoGL->syncDrawElementsState(program->getActiveAttribLocationsMask(), count, type, indices,
653 instanceCount, state.isPrimitiveRestartEnabled(), outIndices);
654 if (error.isError())
655 {
656 return error;
657 }
658
659 bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
660
661 return setGenericDrawState(data);
662 }
663
pauseTransformFeedback(const gl::ContextState & data)664 gl::Error StateManagerGL::pauseTransformFeedback(const gl::ContextState &data)
665 {
666 // If the context is going to be changed, pause the previous context's transform feedback
667 if (data.getContext() != mPrevDrawContext)
668 {
669 if (mPrevDrawTransformFeedback != nullptr)
670 {
671 mPrevDrawTransformFeedback->syncPausedState(true);
672 }
673 }
674 return gl::Error(GL_NO_ERROR);
675 }
676
onMakeCurrent(const gl::ContextState & data)677 gl::Error StateManagerGL::onMakeCurrent(const gl::ContextState &data)
678 {
679 const gl::State &state = data.getState();
680
681 // If the context has changed, pause the previous context's queries
682 if (data.getContext() != mPrevDrawContext)
683 {
684 for (QueryGL *prevQuery : mCurrentQueries)
685 {
686 prevQuery->pause();
687 }
688 }
689 mCurrentQueries.clear();
690 mPrevDrawTransformFeedback = nullptr;
691 mPrevDrawContext = data.getContext();
692
693 // Set the current query state
694 for (GLenum queryType : QueryTypes)
695 {
696 gl::Query *query = state.getActiveQuery(queryType);
697 if (query != nullptr)
698 {
699 QueryGL *queryGL = GetImplAs<QueryGL>(query);
700 queryGL->resume();
701
702 mCurrentQueries.insert(queryGL);
703 }
704 }
705
706 return gl::Error(GL_NO_ERROR);
707 }
708
setGenericDrawState(const gl::ContextState & data)709 gl::Error StateManagerGL::setGenericDrawState(const gl::ContextState &data)
710 {
711 const gl::State &state = data.getState();
712
713 // Sync the current program state
714 const gl::Program *program = state.getProgram();
715 const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
716 useProgram(programGL->getProgramID());
717
718 for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
719 uniformBlockIndex++)
720 {
721 GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
722 const auto &uniformBuffer = state.getIndexedUniformBuffer(binding);
723
724 if (uniformBuffer.get() != nullptr)
725 {
726 BufferGL *bufferGL = GetImplAs<BufferGL>(uniformBuffer.get());
727
728 if (uniformBuffer.getSize() == 0)
729 {
730 bindBufferBase(GL_UNIFORM_BUFFER, binding, bufferGL->getBufferID());
731 }
732 else
733 {
734 bindBufferRange(GL_UNIFORM_BUFFER, binding, bufferGL->getBufferID(),
735 uniformBuffer.getOffset(), uniformBuffer.getSize());
736 }
737 }
738 }
739
740 const std::vector<SamplerBindingGL> &appliedSamplerUniforms = programGL->getAppliedSamplerUniforms();
741 for (const SamplerBindingGL &samplerUniform : appliedSamplerUniforms)
742 {
743 GLenum textureType = samplerUniform.textureType;
744 for (GLuint textureUnitIndex : samplerUniform.boundTextureUnits)
745 {
746 gl::Texture *texture = state.getSamplerTexture(textureUnitIndex, textureType);
747 if (texture != nullptr)
748 {
749 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
750
751 if (mTextures[textureType][textureUnitIndex] != textureGL->getTextureID() ||
752 texture->hasAnyDirtyBit() || textureGL->hasAnyDirtyBit())
753 {
754 activeTexture(textureUnitIndex);
755 bindTexture(textureType, textureGL->getTextureID());
756
757 // TODO: Call this from the gl:: layer once other backends use dirty bits for
758 // texture state.
759 texture->syncImplState();
760 }
761 }
762 else
763 {
764 if (mTextures[textureType][textureUnitIndex] != 0)
765 {
766 activeTexture(textureUnitIndex);
767 bindTexture(textureType, 0);
768 }
769 }
770
771 const gl::Sampler *sampler = state.getSampler(textureUnitIndex);
772 if (sampler != nullptr)
773 {
774 const SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler);
775 samplerGL->syncState(sampler->getSamplerState());
776 bindSampler(textureUnitIndex, samplerGL->getSamplerID());
777 }
778 else
779 {
780 bindSampler(textureUnitIndex, 0);
781 }
782 }
783 }
784
785 const gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
786 const FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
787 bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferGL->getFramebufferID());
788
789 // Seamless cubemaps are required for ES3 and higher contexts.
790 setTextureCubemapSeamlessEnabled(data.getClientMajorVersion() >= 3);
791
792 // Set the current transform feedback state
793 gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
794 if (transformFeedback)
795 {
796 TransformFeedbackGL *transformFeedbackGL =
797 GetImplAs<TransformFeedbackGL>(transformFeedback);
798 bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID());
799 transformFeedbackGL->syncActiveState(transformFeedback->isActive(),
800 transformFeedback->getPrimitiveMode());
801 transformFeedbackGL->syncPausedState(transformFeedback->isPaused());
802 mPrevDrawTransformFeedback = transformFeedbackGL;
803 }
804 else
805 {
806 bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
807 mPrevDrawTransformFeedback = nullptr;
808 }
809
810 return gl::Error(GL_NO_ERROR);
811 }
812
setAttributeCurrentData(size_t index,const gl::VertexAttribCurrentValueData & data)813 void StateManagerGL::setAttributeCurrentData(size_t index,
814 const gl::VertexAttribCurrentValueData &data)
815 {
816 if (mVertexAttribCurrentValues[index] != data)
817 {
818 mVertexAttribCurrentValues[index] = data;
819 switch (mVertexAttribCurrentValues[index].Type)
820 {
821 case GL_FLOAT:
822 mFunctions->vertexAttrib4fv(static_cast<GLuint>(index),
823 mVertexAttribCurrentValues[index].FloatValues);
824 break;
825 case GL_INT:
826 mFunctions->vertexAttribI4iv(static_cast<GLuint>(index),
827 mVertexAttribCurrentValues[index].IntValues);
828 break;
829 case GL_UNSIGNED_INT:
830 mFunctions->vertexAttribI4uiv(static_cast<GLuint>(index),
831 mVertexAttribCurrentValues[index].UnsignedIntValues);
832 break;
833 default: UNREACHABLE();
834 }
835
836 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CURRENT_VALUE_0 + index);
837 }
838 }
839
setScissorTestEnabled(bool enabled)840 void StateManagerGL::setScissorTestEnabled(bool enabled)
841 {
842 if (mScissorTestEnabled != enabled)
843 {
844 mScissorTestEnabled = enabled;
845 if (mScissorTestEnabled)
846 {
847 mFunctions->enable(GL_SCISSOR_TEST);
848 }
849 else
850 {
851 mFunctions->disable(GL_SCISSOR_TEST);
852 }
853
854 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
855 }
856 }
857
setScissor(const gl::Rectangle & scissor)858 void StateManagerGL::setScissor(const gl::Rectangle &scissor)
859 {
860 if (scissor != mScissor)
861 {
862 mScissor = scissor;
863 mFunctions->scissor(mScissor.x, mScissor.y, mScissor.width, mScissor.height);
864
865 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR);
866 }
867 }
868
setViewport(const gl::Rectangle & viewport)869 void StateManagerGL::setViewport(const gl::Rectangle &viewport)
870 {
871 if (viewport != mViewport)
872 {
873 mViewport = viewport;
874 mFunctions->viewport(mViewport.x, mViewport.y, mViewport.width, mViewport.height);
875
876 mLocalDirtyBits.set(gl::State::DIRTY_BIT_VIEWPORT);
877 }
878 }
879
setDepthRange(float near,float far)880 void StateManagerGL::setDepthRange(float near, float far)
881 {
882 if (mNear != near || mFar != far)
883 {
884 mNear = near;
885 mFar = far;
886
887 // The glDepthRangef function isn't available until OpenGL 4.1. Prefer it when it is
888 // available because OpenGL ES only works in floats.
889 if (mFunctions->depthRangef)
890 {
891 mFunctions->depthRangef(mNear, mFar);
892 }
893 else
894 {
895 ASSERT(mFunctions->depthRange);
896 mFunctions->depthRange(mNear, mFar);
897 }
898
899 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_RANGE);
900 }
901 }
902
setBlendEnabled(bool enabled)903 void StateManagerGL::setBlendEnabled(bool enabled)
904 {
905 if (mBlendEnabled != enabled)
906 {
907 mBlendEnabled = enabled;
908 if (mBlendEnabled)
909 {
910 mFunctions->enable(GL_BLEND);
911 }
912 else
913 {
914 mFunctions->disable(GL_BLEND);
915 }
916
917 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
918 }
919 }
920
setBlendColor(const gl::ColorF & blendColor)921 void StateManagerGL::setBlendColor(const gl::ColorF &blendColor)
922 {
923 if (mBlendColor != blendColor)
924 {
925 mBlendColor = blendColor;
926 mFunctions->blendColor(mBlendColor.red, mBlendColor.green, mBlendColor.blue, mBlendColor.alpha);
927
928 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_COLOR);
929 }
930 }
931
setBlendFuncs(GLenum sourceBlendRGB,GLenum destBlendRGB,GLenum sourceBlendAlpha,GLenum destBlendAlpha)932 void StateManagerGL::setBlendFuncs(GLenum sourceBlendRGB,
933 GLenum destBlendRGB,
934 GLenum sourceBlendAlpha,
935 GLenum destBlendAlpha)
936 {
937 if (mSourceBlendRGB != sourceBlendRGB || mDestBlendRGB != destBlendRGB ||
938 mSourceBlendAlpha != sourceBlendAlpha || mDestBlendAlpha != destBlendAlpha)
939 {
940 mSourceBlendRGB = sourceBlendRGB;
941 mDestBlendRGB = destBlendRGB;
942 mSourceBlendAlpha = sourceBlendAlpha;
943 mDestBlendAlpha = destBlendAlpha;
944
945 mFunctions->blendFuncSeparate(mSourceBlendRGB, mDestBlendRGB, mSourceBlendAlpha, mDestBlendAlpha);
946
947 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);
948 }
949 }
950
setBlendEquations(GLenum blendEquationRGB,GLenum blendEquationAlpha)951 void StateManagerGL::setBlendEquations(GLenum blendEquationRGB, GLenum blendEquationAlpha)
952 {
953 if (mBlendEquationRGB != blendEquationRGB || mBlendEquationAlpha != blendEquationAlpha)
954 {
955 mBlendEquationRGB = blendEquationRGB;
956 mBlendEquationAlpha = blendEquationAlpha;
957
958 mFunctions->blendEquationSeparate(mBlendEquationRGB, mBlendEquationAlpha);
959
960 mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_EQUATIONS);
961 }
962 }
963
setColorMask(bool red,bool green,bool blue,bool alpha)964 void StateManagerGL::setColorMask(bool red, bool green, bool blue, bool alpha)
965 {
966 if (mColorMaskRed != red || mColorMaskGreen != green || mColorMaskBlue != blue || mColorMaskAlpha != alpha)
967 {
968 mColorMaskRed = red;
969 mColorMaskGreen = green;
970 mColorMaskBlue = blue;
971 mColorMaskAlpha = alpha;
972 mFunctions->colorMask(mColorMaskRed, mColorMaskGreen, mColorMaskBlue, mColorMaskAlpha);
973
974 mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
975 }
976 }
977
setSampleAlphaToCoverageEnabled(bool enabled)978 void StateManagerGL::setSampleAlphaToCoverageEnabled(bool enabled)
979 {
980 if (mSampleAlphaToCoverageEnabled != enabled)
981 {
982 mSampleAlphaToCoverageEnabled = enabled;
983 if (mSampleAlphaToCoverageEnabled)
984 {
985 mFunctions->enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
986 }
987 else
988 {
989 mFunctions->disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
990 }
991
992 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
993 }
994 }
995
setSampleCoverageEnabled(bool enabled)996 void StateManagerGL::setSampleCoverageEnabled(bool enabled)
997 {
998 if (mSampleCoverageEnabled != enabled)
999 {
1000 mSampleCoverageEnabled = enabled;
1001 if (mSampleCoverageEnabled)
1002 {
1003 mFunctions->enable(GL_SAMPLE_COVERAGE);
1004 }
1005 else
1006 {
1007 mFunctions->disable(GL_SAMPLE_COVERAGE);
1008 }
1009
1010 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
1011 }
1012 }
1013
setSampleCoverage(float value,bool invert)1014 void StateManagerGL::setSampleCoverage(float value, bool invert)
1015 {
1016 if (mSampleCoverageValue != value || mSampleCoverageInvert != invert)
1017 {
1018 mSampleCoverageValue = value;
1019 mSampleCoverageInvert = invert;
1020 mFunctions->sampleCoverage(mSampleCoverageValue, mSampleCoverageInvert);
1021
1022 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE);
1023 }
1024 }
1025
setDepthTestEnabled(bool enabled)1026 void StateManagerGL::setDepthTestEnabled(bool enabled)
1027 {
1028 if (mDepthTestEnabled != enabled)
1029 {
1030 mDepthTestEnabled = enabled;
1031 if (mDepthTestEnabled)
1032 {
1033 mFunctions->enable(GL_DEPTH_TEST);
1034 }
1035 else
1036 {
1037 mFunctions->disable(GL_DEPTH_TEST);
1038 }
1039
1040 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED);
1041 }
1042 }
1043
setDepthFunc(GLenum depthFunc)1044 void StateManagerGL::setDepthFunc(GLenum depthFunc)
1045 {
1046 if (mDepthFunc != depthFunc)
1047 {
1048 mDepthFunc = depthFunc;
1049 mFunctions->depthFunc(mDepthFunc);
1050
1051 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_FUNC);
1052 }
1053 }
1054
setDepthMask(bool mask)1055 void StateManagerGL::setDepthMask(bool mask)
1056 {
1057 if (mDepthMask != mask)
1058 {
1059 mDepthMask = mask;
1060 mFunctions->depthMask(mDepthMask);
1061
1062 mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_MASK);
1063 }
1064 }
1065
setStencilTestEnabled(bool enabled)1066 void StateManagerGL::setStencilTestEnabled(bool enabled)
1067 {
1068 if (mStencilTestEnabled != enabled)
1069 {
1070 mStencilTestEnabled = enabled;
1071 if (mStencilTestEnabled)
1072 {
1073 mFunctions->enable(GL_STENCIL_TEST);
1074 }
1075 else
1076 {
1077 mFunctions->disable(GL_STENCIL_TEST);
1078 }
1079
1080 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED);
1081 }
1082 }
1083
setStencilFrontWritemask(GLuint mask)1084 void StateManagerGL::setStencilFrontWritemask(GLuint mask)
1085 {
1086 if (mStencilFrontWritemask != mask)
1087 {
1088 mStencilFrontWritemask = mask;
1089 mFunctions->stencilMaskSeparate(GL_FRONT, mStencilFrontWritemask);
1090
1091 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
1092 }
1093 }
1094
setStencilBackWritemask(GLuint mask)1095 void StateManagerGL::setStencilBackWritemask(GLuint mask)
1096 {
1097 if (mStencilBackWritemask != mask)
1098 {
1099 mStencilBackWritemask = mask;
1100 mFunctions->stencilMaskSeparate(GL_BACK, mStencilBackWritemask);
1101
1102 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
1103 }
1104 }
1105
setStencilFrontFuncs(GLenum func,GLint ref,GLuint mask)1106 void StateManagerGL::setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask)
1107 {
1108 if (mStencilFrontFunc != func || mStencilFrontRef != ref || mStencilFrontValueMask != mask)
1109 {
1110 mStencilFrontFunc = func;
1111 mStencilFrontRef = ref;
1112 mStencilFrontValueMask = mask;
1113 mFunctions->stencilFuncSeparate(GL_FRONT, mStencilFrontFunc, mStencilFrontRef, mStencilFrontValueMask);
1114
1115 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT);
1116 }
1117 }
1118
setStencilBackFuncs(GLenum func,GLint ref,GLuint mask)1119 void StateManagerGL::setStencilBackFuncs(GLenum func, GLint ref, GLuint mask)
1120 {
1121 if (mStencilBackFunc != func || mStencilBackRef != ref || mStencilBackValueMask != mask)
1122 {
1123 mStencilBackFunc = func;
1124 mStencilBackRef = ref;
1125 mStencilBackValueMask = mask;
1126 mFunctions->stencilFuncSeparate(GL_BACK, mStencilBackFunc, mStencilBackRef, mStencilBackValueMask);
1127
1128 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK);
1129 }
1130 }
1131
setStencilFrontOps(GLenum sfail,GLenum dpfail,GLenum dppass)1132 void StateManagerGL::setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass)
1133 {
1134 if (mStencilFrontStencilFailOp != sfail || mStencilFrontStencilPassDepthFailOp != dpfail || mStencilFrontStencilPassDepthPassOp != dppass)
1135 {
1136 mStencilFrontStencilFailOp = sfail;
1137 mStencilFrontStencilPassDepthFailOp = dpfail;
1138 mStencilFrontStencilPassDepthPassOp = dppass;
1139 mFunctions->stencilOpSeparate(GL_FRONT, mStencilFrontStencilFailOp, mStencilFrontStencilPassDepthFailOp, mStencilFrontStencilPassDepthPassOp);
1140
1141 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_FRONT);
1142 }
1143 }
1144
setStencilBackOps(GLenum sfail,GLenum dpfail,GLenum dppass)1145 void StateManagerGL::setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass)
1146 {
1147 if (mStencilBackStencilFailOp != sfail || mStencilBackStencilPassDepthFailOp != dpfail || mStencilBackStencilPassDepthPassOp != dppass)
1148 {
1149 mStencilBackStencilFailOp = sfail;
1150 mStencilBackStencilPassDepthFailOp = dpfail;
1151 mStencilBackStencilPassDepthPassOp = dppass;
1152 mFunctions->stencilOpSeparate(GL_BACK, mStencilBackStencilFailOp, mStencilBackStencilPassDepthFailOp, mStencilBackStencilPassDepthPassOp);
1153
1154 mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_BACK);
1155 }
1156 }
1157
setCullFaceEnabled(bool enabled)1158 void StateManagerGL::setCullFaceEnabled(bool enabled)
1159 {
1160 if (mCullFaceEnabled != enabled)
1161 {
1162 mCullFaceEnabled = enabled;
1163 if (mCullFaceEnabled)
1164 {
1165 mFunctions->enable(GL_CULL_FACE);
1166 }
1167 else
1168 {
1169 mFunctions->disable(GL_CULL_FACE);
1170 }
1171
1172 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE_ENABLED);
1173 }
1174 }
1175
setCullFace(GLenum cullFace)1176 void StateManagerGL::setCullFace(GLenum cullFace)
1177 {
1178 if (mCullFace != cullFace)
1179 {
1180 mCullFace = cullFace;
1181 mFunctions->cullFace(mCullFace);
1182
1183 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE);
1184 }
1185 }
1186
setFrontFace(GLenum frontFace)1187 void StateManagerGL::setFrontFace(GLenum frontFace)
1188 {
1189 if (mFrontFace != frontFace)
1190 {
1191 mFrontFace = frontFace;
1192 mFunctions->frontFace(mFrontFace);
1193
1194 mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRONT_FACE);
1195 }
1196 }
1197
setPolygonOffsetFillEnabled(bool enabled)1198 void StateManagerGL::setPolygonOffsetFillEnabled(bool enabled)
1199 {
1200 if (mPolygonOffsetFillEnabled != enabled)
1201 {
1202 mPolygonOffsetFillEnabled = enabled;
1203 if (mPolygonOffsetFillEnabled)
1204 {
1205 mFunctions->enable(GL_POLYGON_OFFSET_FILL);
1206 }
1207 else
1208 {
1209 mFunctions->disable(GL_POLYGON_OFFSET_FILL);
1210 }
1211
1212 mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
1213 }
1214 }
1215
setPolygonOffset(float factor,float units)1216 void StateManagerGL::setPolygonOffset(float factor, float units)
1217 {
1218 if (mPolygonOffsetFactor != factor || mPolygonOffsetUnits != units)
1219 {
1220 mPolygonOffsetFactor = factor;
1221 mPolygonOffsetUnits = units;
1222 mFunctions->polygonOffset(mPolygonOffsetFactor, mPolygonOffsetUnits);
1223
1224 mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET);
1225 }
1226 }
1227
setRasterizerDiscardEnabled(bool enabled)1228 void StateManagerGL::setRasterizerDiscardEnabled(bool enabled)
1229 {
1230 if (mRasterizerDiscardEnabled != enabled)
1231 {
1232 mRasterizerDiscardEnabled = enabled;
1233 if (mRasterizerDiscardEnabled)
1234 {
1235 mFunctions->enable(GL_RASTERIZER_DISCARD);
1236 }
1237 else
1238 {
1239 mFunctions->disable(GL_RASTERIZER_DISCARD);
1240 }
1241
1242 mLocalDirtyBits.set(gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
1243 }
1244 }
1245
setLineWidth(float width)1246 void StateManagerGL::setLineWidth(float width)
1247 {
1248 if (mLineWidth != width)
1249 {
1250 mLineWidth = width;
1251 mFunctions->lineWidth(mLineWidth);
1252
1253 mLocalDirtyBits.set(gl::State::DIRTY_BIT_LINE_WIDTH);
1254 }
1255 }
1256
setPrimitiveRestartEnabled(bool enabled)1257 void StateManagerGL::setPrimitiveRestartEnabled(bool enabled)
1258 {
1259 if (mPrimitiveRestartEnabled != enabled)
1260 {
1261 mPrimitiveRestartEnabled = enabled;
1262
1263 if (mPrimitiveRestartEnabled)
1264 {
1265 mFunctions->enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
1266 }
1267 else
1268 {
1269 mFunctions->disable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
1270 }
1271
1272 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
1273 }
1274 }
1275
setClearDepth(float clearDepth)1276 void StateManagerGL::setClearDepth(float clearDepth)
1277 {
1278 if (mClearDepth != clearDepth)
1279 {
1280 mClearDepth = clearDepth;
1281
1282 // The glClearDepthf function isn't available until OpenGL 4.1. Prefer it when it is
1283 // available because OpenGL ES only works in floats.
1284 if (mFunctions->clearDepthf)
1285 {
1286 mFunctions->clearDepthf(mClearDepth);
1287 }
1288 else
1289 {
1290 ASSERT(mFunctions->clearDepth);
1291 mFunctions->clearDepth(mClearDepth);
1292 }
1293
1294 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_DEPTH);
1295 }
1296 }
1297
setClearColor(const gl::ColorF & clearColor)1298 void StateManagerGL::setClearColor(const gl::ColorF &clearColor)
1299 {
1300 if (mClearColor != clearColor)
1301 {
1302 mClearColor = clearColor;
1303 mFunctions->clearColor(mClearColor.red, mClearColor.green, mClearColor.blue, mClearColor.alpha);
1304
1305 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_COLOR);
1306 }
1307 }
1308
setClearStencil(GLint clearStencil)1309 void StateManagerGL::setClearStencil(GLint clearStencil)
1310 {
1311 if (mClearStencil != clearStencil)
1312 {
1313 mClearStencil = clearStencil;
1314 mFunctions->clearStencil(mClearStencil);
1315
1316 mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_STENCIL);
1317 }
1318 }
1319
syncState(const gl::State & state,const gl::State::DirtyBits & glDirtyBits)1320 void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBits &glDirtyBits)
1321 {
1322 // The the current framebuffer binding sometimes requires resetting the srgb blending
1323 if (glDirtyBits[gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING] &&
1324 mFunctions->standard == STANDARD_GL_DESKTOP)
1325 {
1326 mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
1327 }
1328
1329 const auto &glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits);
1330
1331 if (!glAndLocalDirtyBits.any())
1332 {
1333 return;
1334 }
1335
1336 // TODO(jmadill): Investigate only syncing vertex state for active attributes
1337 for (auto dirtyBit : angle::IterateBitSet(glAndLocalDirtyBits))
1338 {
1339 switch (dirtyBit)
1340 {
1341 case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
1342 setScissorTestEnabled(state.isScissorTestEnabled());
1343 break;
1344 case gl::State::DIRTY_BIT_SCISSOR:
1345 setScissor(state.getScissor());
1346 break;
1347 case gl::State::DIRTY_BIT_VIEWPORT:
1348 setViewport(state.getViewport());
1349 break;
1350 case gl::State::DIRTY_BIT_DEPTH_RANGE:
1351 setDepthRange(state.getNearPlane(), state.getFarPlane());
1352 break;
1353 case gl::State::DIRTY_BIT_BLEND_ENABLED:
1354 setBlendEnabled(state.isBlendEnabled());
1355 break;
1356 case gl::State::DIRTY_BIT_BLEND_COLOR:
1357 setBlendColor(state.getBlendColor());
1358 break;
1359 case gl::State::DIRTY_BIT_BLEND_FUNCS:
1360 {
1361 const auto &blendState = state.getBlendState();
1362 setBlendFuncs(blendState.sourceBlendRGB, blendState.destBlendRGB,
1363 blendState.sourceBlendAlpha, blendState.destBlendAlpha);
1364 break;
1365 }
1366 case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
1367 {
1368 const auto &blendState = state.getBlendState();
1369 setBlendEquations(blendState.blendEquationRGB, blendState.blendEquationAlpha);
1370 break;
1371 }
1372 case gl::State::DIRTY_BIT_COLOR_MASK:
1373 {
1374 const auto &blendState = state.getBlendState();
1375 setColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
1376 blendState.colorMaskBlue, blendState.colorMaskAlpha);
1377 break;
1378 }
1379 case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
1380 setSampleAlphaToCoverageEnabled(state.isSampleAlphaToCoverageEnabled());
1381 break;
1382 case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
1383 setSampleCoverageEnabled(state.isSampleCoverageEnabled());
1384 break;
1385 case gl::State::DIRTY_BIT_SAMPLE_COVERAGE:
1386 setSampleCoverage(state.getSampleCoverageValue(), state.getSampleCoverageInvert());
1387 break;
1388 case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
1389 setDepthTestEnabled(state.isDepthTestEnabled());
1390 break;
1391 case gl::State::DIRTY_BIT_DEPTH_FUNC:
1392 setDepthFunc(state.getDepthStencilState().depthFunc);
1393 break;
1394 case gl::State::DIRTY_BIT_DEPTH_MASK:
1395 setDepthMask(state.getDepthStencilState().depthMask);
1396 break;
1397 case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
1398 setStencilTestEnabled(state.isStencilTestEnabled());
1399 break;
1400 case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
1401 {
1402 const auto &depthStencilState = state.getDepthStencilState();
1403 setStencilFrontFuncs(depthStencilState.stencilFunc, state.getStencilRef(),
1404 depthStencilState.stencilMask);
1405 break;
1406 }
1407 case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
1408 {
1409 const auto &depthStencilState = state.getDepthStencilState();
1410 setStencilBackFuncs(depthStencilState.stencilBackFunc, state.getStencilBackRef(),
1411 depthStencilState.stencilBackMask);
1412 break;
1413 }
1414 case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
1415 {
1416 const auto &depthStencilState = state.getDepthStencilState();
1417 setStencilFrontOps(depthStencilState.stencilFail,
1418 depthStencilState.stencilPassDepthFail,
1419 depthStencilState.stencilPassDepthPass);
1420 break;
1421 }
1422 case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
1423 {
1424 const auto &depthStencilState = state.getDepthStencilState();
1425 setStencilBackOps(depthStencilState.stencilBackFail,
1426 depthStencilState.stencilBackPassDepthFail,
1427 depthStencilState.stencilBackPassDepthPass);
1428 break;
1429 }
1430 case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
1431 setStencilFrontWritemask(state.getDepthStencilState().stencilWritemask);
1432 break;
1433 case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
1434 setStencilBackWritemask(state.getDepthStencilState().stencilBackWritemask);
1435 break;
1436 case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
1437 setCullFaceEnabled(state.isCullFaceEnabled());
1438 break;
1439 case gl::State::DIRTY_BIT_CULL_FACE:
1440 setCullFace(state.getRasterizerState().cullMode);
1441 break;
1442 case gl::State::DIRTY_BIT_FRONT_FACE:
1443 setFrontFace(state.getRasterizerState().frontFace);
1444 break;
1445 case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
1446 setPolygonOffsetFillEnabled(state.isPolygonOffsetFillEnabled());
1447 break;
1448 case gl::State::DIRTY_BIT_POLYGON_OFFSET:
1449 {
1450 const auto &rasterizerState = state.getRasterizerState();
1451 setPolygonOffset(rasterizerState.polygonOffsetFactor,
1452 rasterizerState.polygonOffsetUnits);
1453 break;
1454 }
1455 case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
1456 setRasterizerDiscardEnabled(state.isRasterizerDiscardEnabled());
1457 break;
1458 case gl::State::DIRTY_BIT_LINE_WIDTH:
1459 setLineWidth(state.getLineWidth());
1460 break;
1461 case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
1462 setPrimitiveRestartEnabled(state.isPrimitiveRestartEnabled());
1463 break;
1464 case gl::State::DIRTY_BIT_CLEAR_COLOR:
1465 setClearColor(state.getColorClearValue());
1466 break;
1467 case gl::State::DIRTY_BIT_CLEAR_DEPTH:
1468 setClearDepth(state.getDepthClearValue());
1469 break;
1470 case gl::State::DIRTY_BIT_CLEAR_STENCIL:
1471 setClearStencil(state.getStencilClearValue());
1472 break;
1473 case gl::State::DIRTY_BIT_UNPACK_ALIGNMENT:
1474 // TODO(jmadill): split this
1475 setPixelUnpackState(state.getUnpackState());
1476 break;
1477 case gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH:
1478 // TODO(jmadill): split this
1479 setPixelUnpackState(state.getUnpackState());
1480 break;
1481 case gl::State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT:
1482 // TODO(jmadill): split this
1483 setPixelUnpackState(state.getUnpackState());
1484 break;
1485 case gl::State::DIRTY_BIT_UNPACK_SKIP_IMAGES:
1486 // TODO(jmadill): split this
1487 setPixelUnpackState(state.getUnpackState());
1488 break;
1489 case gl::State::DIRTY_BIT_UNPACK_SKIP_ROWS:
1490 // TODO(jmadill): split this
1491 setPixelUnpackState(state.getUnpackState());
1492 break;
1493 case gl::State::DIRTY_BIT_UNPACK_SKIP_PIXELS:
1494 // TODO(jmadill): split this
1495 setPixelUnpackState(state.getUnpackState());
1496 break;
1497 case gl::State::DIRTY_BIT_UNPACK_BUFFER_BINDING:
1498 // TODO(jmadill): split this
1499 setPixelUnpackState(state.getUnpackState());
1500 break;
1501 case gl::State::DIRTY_BIT_PACK_ALIGNMENT:
1502 // TODO(jmadill): split this
1503 setPixelPackState(state.getPackState());
1504 break;
1505 case gl::State::DIRTY_BIT_PACK_REVERSE_ROW_ORDER:
1506 // TODO(jmadill): split this
1507 setPixelPackState(state.getPackState());
1508 break;
1509 case gl::State::DIRTY_BIT_PACK_ROW_LENGTH:
1510 // TODO(jmadill): split this
1511 setPixelPackState(state.getPackState());
1512 break;
1513 case gl::State::DIRTY_BIT_PACK_SKIP_ROWS:
1514 // TODO(jmadill): split this
1515 setPixelPackState(state.getPackState());
1516 break;
1517 case gl::State::DIRTY_BIT_PACK_SKIP_PIXELS:
1518 // TODO(jmadill): split this
1519 setPixelPackState(state.getPackState());
1520 break;
1521 case gl::State::DIRTY_BIT_PACK_BUFFER_BINDING:
1522 // TODO(jmadill): split this
1523 setPixelPackState(state.getPackState());
1524 break;
1525 case gl::State::DIRTY_BIT_DITHER_ENABLED:
1526 setDitherEnabled(state.isDitherEnabled());
1527 break;
1528 case gl::State::DIRTY_BIT_GENERATE_MIPMAP_HINT:
1529 // TODO(jmadill): implement this
1530 break;
1531 case gl::State::DIRTY_BIT_SHADER_DERIVATIVE_HINT:
1532 // TODO(jmadill): implement this
1533 break;
1534 case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
1535 // TODO(jmadill): implement this
1536 break;
1537 case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
1538 // TODO(jmadill): implement this
1539 break;
1540 case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
1541 // TODO(jmadill): implement this
1542 break;
1543 case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
1544 // TODO(jmadill): implement this
1545 break;
1546 case gl::State::DIRTY_BIT_PROGRAM_BINDING:
1547 // TODO(jmadill): implement this
1548 break;
1549 case gl::State::DIRTY_BIT_MULTISAMPLING:
1550 setMultisamplingStateEnabled(state.isMultisamplingEnabled());
1551 break;
1552 case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
1553 setSampleAlphaToOneStateEnabled(state.isSampleAlphaToOneEnabled());
1554 case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
1555 setCoverageModulation(state.getCoverageModulation());
1556 break;
1557 case gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_MV:
1558 setPathRenderingModelViewMatrix(
1559 state.getPathRenderingMatrix(GL_PATH_MODELVIEW_MATRIX_CHROMIUM));
1560 break;
1561 case gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ:
1562 setPathRenderingProjectionMatrix(
1563 state.getPathRenderingMatrix(GL_PATH_PROJECTION_MATRIX_CHROMIUM));
1564 break;
1565 case gl::State::DIRTY_BIT_PATH_RENDERING_STENCIL_STATE:
1566 setPathRenderingStencilState(state.getPathStencilFunc(), state.getPathStencilRef(),
1567 state.getPathStencilMask());
1568 break;
1569 case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB:
1570 setFramebufferSRGBEnabledForFramebuffer(
1571 state.getFramebufferSRGB(),
1572 GetImplAs<FramebufferGL>(state.getDrawFramebuffer()));
1573 break;
1574 default:
1575 {
1576 ASSERT(dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 &&
1577 dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX);
1578 size_t attribIndex =
1579 static_cast<size_t>(dirtyBit) - gl::State::DIRTY_BIT_CURRENT_VALUE_0;
1580 setAttributeCurrentData(attribIndex, state.getVertexAttribCurrentValue(
1581 static_cast<unsigned int>(attribIndex)));
1582 break;
1583 }
1584 }
1585
1586 mLocalDirtyBits.reset();
1587 }
1588 }
1589
setFramebufferSRGBEnabled(bool enabled)1590 void StateManagerGL::setFramebufferSRGBEnabled(bool enabled)
1591 {
1592 if (mFramebufferSRGBEnabled != enabled)
1593 {
1594 mFramebufferSRGBEnabled = enabled;
1595 if (mFramebufferSRGBEnabled)
1596 {
1597 mFunctions->enable(GL_FRAMEBUFFER_SRGB);
1598 }
1599 else
1600 {
1601 mFunctions->disable(GL_FRAMEBUFFER_SRGB);
1602 }
1603 mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
1604 }
1605 }
1606
setFramebufferSRGBEnabledForFramebuffer(bool enabled,const FramebufferGL * framebuffer)1607 void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(bool enabled,
1608 const FramebufferGL *framebuffer)
1609 {
1610 if (mFunctions->standard == STANDARD_GL_DESKTOP && framebuffer->isDefault())
1611 {
1612 // Obey the framebuffer sRGB state for blending on all framebuffers except the default
1613 // framebuffer on Desktop OpenGL.
1614 // When SRGB blending is enabled, only SRGB capable formats will use it but the default
1615 // framebuffer will always use it if it is enabled.
1616 // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
1617 setFramebufferSRGBEnabled(false);
1618 }
1619 else
1620 {
1621 setFramebufferSRGBEnabled(enabled);
1622 }
1623 }
1624
setDitherEnabled(bool enabled)1625 void StateManagerGL::setDitherEnabled(bool enabled)
1626 {
1627 if (mDitherEnabled != enabled)
1628 {
1629 mDitherEnabled = enabled;
1630 if (mDitherEnabled)
1631 {
1632 mFunctions->enable(GL_DITHER);
1633 }
1634 else
1635 {
1636 mFunctions->disable(GL_DITHER);
1637 }
1638 }
1639 }
1640
setMultisamplingStateEnabled(bool enabled)1641 void StateManagerGL::setMultisamplingStateEnabled(bool enabled)
1642 {
1643 if (mMultisamplingEnabled != enabled)
1644 {
1645 mMultisamplingEnabled = enabled;
1646 if (mMultisamplingEnabled)
1647 {
1648 mFunctions->enable(GL_MULTISAMPLE_EXT);
1649 }
1650 else
1651 {
1652 mFunctions->disable(GL_MULTISAMPLE_EXT);
1653 }
1654 mLocalDirtyBits.set(gl::State::DIRTY_BIT_MULTISAMPLING);
1655 }
1656 }
1657
setSampleAlphaToOneStateEnabled(bool enabled)1658 void StateManagerGL::setSampleAlphaToOneStateEnabled(bool enabled)
1659 {
1660 if (mSampleAlphaToOneEnabled != enabled)
1661 {
1662 mSampleAlphaToOneEnabled = enabled;
1663 if (mSampleAlphaToOneEnabled)
1664 {
1665 mFunctions->enable(GL_SAMPLE_ALPHA_TO_ONE);
1666 }
1667 else
1668 {
1669 mFunctions->disable(GL_SAMPLE_ALPHA_TO_ONE);
1670 }
1671 mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
1672 }
1673 }
1674
setCoverageModulation(GLenum components)1675 void StateManagerGL::setCoverageModulation(GLenum components)
1676 {
1677 if (mCoverageModulation != components)
1678 {
1679 mCoverageModulation = components;
1680 mFunctions->coverageModulationNV(components);
1681
1682 mLocalDirtyBits.set(gl::State::DIRTY_BIT_COVERAGE_MODULATION);
1683 }
1684 }
1685
setPathRenderingModelViewMatrix(const GLfloat * m)1686 void StateManagerGL::setPathRenderingModelViewMatrix(const GLfloat *m)
1687 {
1688 if (memcmp(mPathMatrixMV, m, sizeof(mPathMatrixMV)) != 0)
1689 {
1690 memcpy(mPathMatrixMV, m, sizeof(mPathMatrixMV));
1691 mFunctions->matrixLoadEXT(GL_PATH_MODELVIEW_CHROMIUM, m);
1692
1693 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_MV);
1694 }
1695 }
1696
setPathRenderingProjectionMatrix(const GLfloat * m)1697 void StateManagerGL::setPathRenderingProjectionMatrix(const GLfloat *m)
1698 {
1699 if (memcmp(mPathMatrixProj, m, sizeof(mPathMatrixProj)) != 0)
1700 {
1701 memcpy(mPathMatrixProj, m, sizeof(mPathMatrixProj));
1702 mFunctions->matrixLoadEXT(GL_PATH_PROJECTION_CHROMIUM, m);
1703
1704 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ);
1705 }
1706 }
1707
setPathRenderingStencilState(GLenum func,GLint ref,GLuint mask)1708 void StateManagerGL::setPathRenderingStencilState(GLenum func, GLint ref, GLuint mask)
1709 {
1710 if (func != mPathStencilFunc || ref != mPathStencilRef || mask != mPathStencilMask)
1711 {
1712 mPathStencilFunc = func;
1713 mPathStencilRef = ref;
1714 mPathStencilMask = mask;
1715 mFunctions->pathStencilFuncNV(func, ref, mask);
1716
1717 mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_STENCIL_STATE);
1718 }
1719 }
1720
setTextureCubemapSeamlessEnabled(bool enabled)1721 void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
1722 {
1723 if (mTextureCubemapSeamlessEnabled != enabled)
1724 {
1725 mTextureCubemapSeamlessEnabled = enabled;
1726 if (mTextureCubemapSeamlessEnabled)
1727 {
1728 mFunctions->enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
1729 }
1730 else
1731 {
1732 mFunctions->disable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
1733 }
1734 }
1735 }
1736
getBoundBuffer(GLenum type)1737 GLuint StateManagerGL::getBoundBuffer(GLenum type)
1738 {
1739 ASSERT(mBuffers.find(type) != mBuffers.end());
1740 return mBuffers[type];
1741 }
1742 }
1743