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