• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "GLClientState.h"
17 #include "GLESTextureUtils.h"
18 #include "ErrorLog.h"
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "glUtils.h"
23 
24 #if PLATFORM_SDK_VERSION < 26
25 #include <cutils/log.h>
26 #else
27 #include <log/log.h>
28 #endif
29 
30 #ifndef MAX
31 #define MAX(a, b) ((a) < (b) ? (b) : (a))
32 #endif
33 
34 // Don't include these in the .h file, or we get weird compile errors.
35 #include <GLES2/gl2ext.h>
36 #include <GLES3/gl3.h>
37 #include <GLES3/gl31.h>
38 
init()39 void GLClientState::init() {
40     m_initialized = false;
41 
42     state_GL_STENCIL_TEST = false;
43     state_GL_STENCIL_FUNC = GL_ALWAYS;
44     state_GL_STENCIL_VALUE_MASK = ~(0);
45     state_GL_STENCIL_REF = 0;
46     state_GL_STENCIL_FAIL = GL_KEEP;
47     state_GL_STENCIL_PASS_DEPTH_FAIL = GL_KEEP;
48     state_GL_STENCIL_PASS_DEPTH_PASS = GL_KEEP;
49     state_GL_STENCIL_BACK_FUNC = GL_ALWAYS;
50     state_GL_STENCIL_BACK_VALUE_MASK = ~(0);
51     state_GL_STENCIL_BACK_REF = 0;
52     state_GL_STENCIL_BACK_FAIL = GL_KEEP;
53     state_GL_STENCIL_BACK_PASS_DEPTH_FAIL = GL_KEEP;
54     state_GL_STENCIL_BACK_PASS_DEPTH_PASS = GL_KEEP;
55     state_GL_STENCIL_WRITEMASK = ~(0);
56     state_GL_STENCIL_BACK_WRITEMASK = ~(0);
57     state_GL_STENCIL_CLEAR_VALUE = 0;
58 
59 
60     m_arrayBuffer = 0;
61     m_arrayBuffer_lastEncode = 0;
62 
63     m_attribEnableCache = 0;
64     m_vaoAttribBindingCacheInvalid = 0xffff;
65     m_vaoAttribBindingHasClientArrayCache = 0;
66     m_vaoAttribBindingHasVboCache = 0;
67     m_noClientArraysCache = 0;
68 
69     addVertexArrayObject(0);
70     setVertexArrayObject(0);
71     // init gl constans;
72     m_currVaoState[VERTEX_LOCATION].glConst = GL_VERTEX_ARRAY;
73     m_currVaoState[NORMAL_LOCATION].glConst = GL_NORMAL_ARRAY;
74     m_currVaoState[COLOR_LOCATION].glConst = GL_COLOR_ARRAY;
75     m_currVaoState[POINTSIZE_LOCATION].glConst = GL_POINT_SIZE_ARRAY_OES;
76     m_currVaoState[TEXCOORD0_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
77     m_currVaoState[TEXCOORD1_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
78     m_currVaoState[TEXCOORD2_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
79     m_currVaoState[TEXCOORD3_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
80     m_currVaoState[TEXCOORD4_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
81     m_currVaoState[TEXCOORD5_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
82     m_currVaoState[TEXCOORD6_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
83     m_currVaoState[TEXCOORD7_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
84     m_currVaoState[MATRIXINDEX_LOCATION].glConst = GL_MATRIX_INDEX_ARRAY_OES;
85     m_currVaoState[WEIGHT_LOCATION].glConst = GL_WEIGHT_ARRAY_OES;
86 
87     m_copyReadBuffer = 0;
88     m_copyWriteBuffer = 0;
89     m_pixelPackBuffer = 0;
90     m_pixelUnpackBuffer = 0;
91     m_transformFeedbackBuffer = 0;
92     m_uniformBuffer = 0;
93     m_atomicCounterBuffer = 0;
94     m_dispatchIndirectBuffer = 0;
95     m_drawIndirectBuffer = 0;
96     m_shaderStorageBuffer = 0;
97 
98     m_transformFeedbackActive = false;
99     m_transformFeedbackUnpaused = false;
100     m_transformFeedbackVaryingsCountForLinking = 0;
101 
102     m_activeTexture = 0;
103     m_currentProgram = 0;
104     m_currentShaderProgram = 0;
105 
106     m_pixelStore.unpack_alignment = 4;
107     m_pixelStore.pack_alignment = 4;
108 
109     m_pixelStore.unpack_row_length = 0;
110     m_pixelStore.unpack_image_height = 0;
111     m_pixelStore.unpack_skip_pixels = 0;
112     m_pixelStore.unpack_skip_rows = 0;
113     m_pixelStore.unpack_skip_images = 0;
114 
115     m_pixelStore.pack_row_length = 0;
116     m_pixelStore.pack_skip_pixels = 0;
117     m_pixelStore.pack_skip_rows = 0;
118 
119     memset(m_tex.unit, 0, sizeof(m_tex.unit));
120     m_tex.activeUnit = &m_tex.unit[0];
121     m_tex.textureRecs = NULL;
122 
123     mRboState.boundRenderbuffer = 0;
124 
125     mFboState.boundDrawFramebuffer = 0;
126     mFboState.boundReadFramebuffer = 0;
127     mFboState.drawFboCheckStatus = GL_NONE;
128     mFboState.readFboCheckStatus = GL_NONE;
129 
130     m_extensions_set = false;
131 
132 #ifdef GFXSTREAM
133     // The default transform feedback buffer object
134     // The default sampler object
135     GLuint defaultId = 0;
136     setExistence(ObjectType::TransformFeedback, true, 1, &defaultId);
137 
138     mBoundTransformFeedbackValidity.id = 0;
139     mBoundTransformFeedbackValidity.valid = true;
140 
141     // query must take id that was created via glGenQueries
142     mBoundQueryValidity_AnySamplesPassed.valid = false;
143     mBoundQueryValidity_AnySamplesPassedConservative.valid = false;
144     mBoundQueryValidity_TransformFeedbackPrimitivesWritten.valid = false;
145 #endif
146 }
147 
GLClientState()148 GLClientState::GLClientState()
149 {
150     init();
151 }
152 
GLClientState(int majorVersion,int minorVersion)153 GLClientState::GLClientState(int majorVersion, int minorVersion) :
154     m_glesMajorVersion(majorVersion),
155     m_glesMinorVersion(minorVersion) {
156     init();
157 }
158 
~GLClientState()159 GLClientState::~GLClientState()
160 {
161 }
162 
enable(int location,int state)163 void GLClientState::enable(int location, int state)
164 {
165     m_currVaoState[location].enableDirty |= (state != m_currVaoState[location].enabled);
166     m_currVaoState[location].enabled = state;
167     if (state) {
168         m_attribEnableCache |= (1 << location);
169         m_noClientArraysCache = 0;
170     } else {
171         m_attribEnableCache &= ~(1 << location);
172     }
173 }
174 
setVertexAttribState(int location,int size,GLenum type,GLboolean normalized,GLsizei stride,const void * data,bool isInt)175 void GLClientState::setVertexAttribState(int location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data, bool isInt)
176 {
177     m_currVaoState[location].size = size;
178     m_currVaoState[location].type = type;
179     m_currVaoState[location].stride = stride;
180     m_currVaoState[location].data = (void*)data;
181     m_currVaoState[location].bufferObject = m_arrayBuffer;
182     m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
183     switch (type) {
184         case GL_INT_2_10_10_10_REV:
185         case GL_UNSIGNED_INT_2_10_10_10_REV:
186             m_currVaoState[location].elementSize =
187                 m_currVaoState[location].elementSize / 4;
188             break;
189         default:
190             break;
191     }
192     m_currVaoState[location].normalized = normalized;
193     m_currVaoState[location].isInt = isInt;
194 }
195 
setVertexBindingDivisor(int bindingindex,GLuint divisor)196 void GLClientState::setVertexBindingDivisor(int bindingindex, GLuint divisor) {
197     m_currVaoState.bufferBinding(bindingindex).divisor = divisor;
198 }
199 
getCurrAttributeBindingInfo(int attribindex)200 const GLClientState::BufferBinding& GLClientState::getCurrAttributeBindingInfo(int attribindex) {
201     return m_currVaoState.bufferBindings_const()[m_currVaoState[attribindex].bindingindex];
202 }
203 
setVertexAttribBinding(int attribindex,int bindingindex)204 void GLClientState::setVertexAttribBinding(int attribindex, int bindingindex) {
205     m_currVaoState[attribindex].bindingindex = bindingindex;
206     m_currVaoState.bufferBinding(bindingindex).vertexAttribLoc = attribindex;
207     m_vaoAttribBindingCacheInvalid |= (1 << attribindex);
208     m_noClientArraysCache = 0;
209 }
210 
setVertexAttribFormat(int location,int size,GLenum type,GLboolean normalized,GLuint reloffset,bool isInt)211 void GLClientState::setVertexAttribFormat(int location, int size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt) {
212     m_currVaoState[location].size = size;
213     m_currVaoState[location].type = type;
214     m_currVaoState[location].normalized = normalized;
215     m_currVaoState[location].reloffset = reloffset;
216     m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
217     switch (type) {
218         case GL_INT_2_10_10_10_REV:
219         case GL_UNSIGNED_INT_2_10_10_10_REV:
220             m_currVaoState[location].elementSize =
221                 m_currVaoState[location].elementSize / 4;
222             break;
223         default:
224             break;
225     }
226     m_currVaoState[location].isInt = isInt;
227 }
228 
addVertexArrayObjects(GLsizei n,GLuint * arrays)229 void GLClientState::addVertexArrayObjects(GLsizei n, GLuint* arrays) {
230     for (GLsizei i = 0; i < n; i++) {
231         addVertexArrayObject(arrays[i]);
232     }
233 }
234 
removeVertexArrayObjects(GLsizei n,const GLuint * arrays)235 void GLClientState::removeVertexArrayObjects(GLsizei n, const GLuint* arrays) {
236     for (GLsizei i = 0; i < n; i++) {
237         if (arrays[i] && m_currVaoState.vaoId() == arrays[i]) {
238             setVertexArrayObject(0);
239         }
240         removeVertexArrayObject(arrays[i]);
241     }
242 }
243 
addVertexArrayObject(GLuint name)244 void GLClientState::addVertexArrayObject(GLuint name) {
245     if (m_vaoMap.find(name) !=
246         m_vaoMap.end()) {
247         ALOGE("%s: ERROR: %u already part of current VAO state!",
248               __FUNCTION__, name);
249         return;
250     }
251 
252     m_vaoMap.insert(
253             VAOStateMap::value_type(
254                 name,
255                 VAOState(0, CODEC_MAX_VERTEX_ATTRIBUTES, CODEC_MAX_VERTEX_ATTRIBUTES)));
256     VertexAttribStateVector& attribState =
257         m_vaoMap.find(name)->second.attribState;
258     for (int i = 0; i < CODEC_MAX_VERTEX_ATTRIBUTES; i++) {
259         attribState[i].enabled = 0;
260         attribState[i].enableDirty = false;
261         attribState[i].data = 0;
262         attribState[i].reloffset = 0;
263         attribState[i].bindingindex = i;
264         attribState[i].divisor = 0;
265         attribState[i].size = 4; // 4 is the default size
266         attribState[i].type = GL_FLOAT; // GL_FLOAT is the default type
267     }
268 
269     VertexAttribBindingVector& bindingState =
270         m_vaoMap.find(name)->second.bindingState;
271     for (int i = 0; i < bindingState.size(); i++) {
272         bindingState[i].effectiveStride = 16;
273     }
274 }
275 
removeVertexArrayObject(GLuint name)276 void GLClientState::removeVertexArrayObject(GLuint name) {
277     if (name == 0) {
278         ALOGE("%s: ERROR: cannot delete VAO 0!",
279               __FUNCTION__);
280         return;
281     }
282     if (m_vaoMap.find(name) ==
283         m_vaoMap.end()) {
284         ALOGE("%s: ERROR: %u not found in VAO state!",
285               __FUNCTION__, name);
286         return;
287     }
288     m_vaoMap.erase(name);
289 }
290 
setVertexArrayObject(GLuint name)291 void GLClientState::setVertexArrayObject(GLuint name) {
292     if (m_vaoMap.find(name) ==
293         m_vaoMap.end()) {
294         ALOGE("%s: ERROR: %u not found in VAO state!",
295               __FUNCTION__, name);
296         return;
297     }
298 
299     if (name && m_currVaoState.vaoId() == name) {
300         ALOGV("%s: set vao to self, no-op (%u)",
301               __FUNCTION__, name);
302         return;
303     }
304 
305     m_currVaoState =
306         VAOStateRef(m_vaoMap.find(name));
307 }
308 
isVertexArrayObject(GLuint vao) const309 bool GLClientState::isVertexArrayObject(GLuint vao) const {
310     return m_vaoMap.find(vao) != m_vaoMap.end();
311 }
312 
getVBOUsage(bool * hasClientArrays,bool * hasVBOs)313 void GLClientState::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) {
314     uint8_t todo_count = 0;
315     uint8_t todo[CODEC_MAX_VERTEX_ATTRIBUTES];
316 
317     if (m_noClientArraysCache) {
318         *hasClientArrays = false;
319         *hasVBOs = true;
320         return;
321     }
322 
323     for (int i = 0; i < CODEC_MAX_VERTEX_ATTRIBUTES; i++) {
324         if ((1 << i) & (m_attribEnableCache)) {
325             if (!((1 << i) & m_vaoAttribBindingCacheInvalid)) {
326                 if ((1 << i) & m_vaoAttribBindingHasClientArrayCache) {
327                     *hasClientArrays = true;
328                 }
329                 if ((1 << i) & m_vaoAttribBindingHasVboCache) {
330                     *hasVBOs = true;
331                 }
332                 if (*hasClientArrays && *hasVBOs) return;
333             } else {
334                 todo[todo_count] = i;
335                 ++todo_count;
336             }
337         }
338     }
339 
340     if (todo_count == 0 &&
341         !(*hasClientArrays) &&
342         *hasVBOs) {
343         m_noClientArraysCache = 1;
344     }
345 
346     for (int k = 0; k < todo_count; ++k) {
347         int i = todo[k];
348         const GLClientState::BufferBinding& curr_binding =
349             m_currVaoState.bufferBindings_const()[
350                 m_currVaoState[i].bindingindex];
351         GLuint bufferObject = curr_binding.buffer;
352         if (bufferObject == 0 && curr_binding.offset && hasClientArrays) {
353             *hasClientArrays = true;
354             m_vaoAttribBindingHasClientArrayCache |= (1 << i);
355         } else {
356             m_vaoAttribBindingHasClientArrayCache &= ~(1 << i);
357         }
358         if (bufferObject != 0 && hasVBOs) {
359             *hasVBOs = true;
360             m_vaoAttribBindingHasVboCache |= (1 << i);
361         } else {
362             m_vaoAttribBindingHasVboCache &= ~(1 << i);
363         }
364         m_vaoAttribBindingCacheInvalid &= ~(1 << i);
365         if (*hasClientArrays && *hasVBOs) return;
366     }
367 
368     if (!(*hasClientArrays) &&
369         *hasVBOs) {
370         m_noClientArraysCache = 1;
371     }
372 }
373 
getState(int location)374 const GLClientState::VertexAttribState& GLClientState::getState(int location) {
375     return m_currVaoState[location];
376 }
377 
getStateAndEnableDirty(int location,bool * enableChanged)378 const GLClientState::VertexAttribState& GLClientState::getStateAndEnableDirty(int location, bool *enableChanged)
379 {
380     if (enableChanged) {
381         *enableChanged = m_currVaoState[location].enableDirty;
382     }
383 
384     m_currVaoState[location].enableDirty = false;
385     return m_currVaoState[location];
386 }
387 
updateEnableDirtyArrayForDraw()388 void GLClientState::updateEnableDirtyArrayForDraw() {
389     bool enableChanged;
390     VAOState& vaoState = m_currVaoState.vaoState();
391 
392     int k = 0;
393     for (int i = 0; i < CODEC_MAX_VERTEX_ATTRIBUTES; ++i) {
394         const VertexAttribState &state = getStateAndEnableDirty(i, &enableChanged);
395         if (enableChanged || state.enabled) {
396             vaoState.attributesNeedingUpdateForDraw[k] = i;
397             ++k;
398         }
399     }
400     vaoState.numAttributesNeedingUpdateForDraw = k;
401 }
402 
currentVaoState()403 GLClientState::VAOState& GLClientState::currentVaoState() {
404     return m_currVaoState.vaoState();
405 }
406 
getLocation(GLenum loc)407 int GLClientState::getLocation(GLenum loc)
408 {
409     int retval;
410 
411     switch(loc) {
412     case GL_VERTEX_ARRAY:
413         retval = int(VERTEX_LOCATION);
414         break;
415     case GL_NORMAL_ARRAY:
416         retval = int(NORMAL_LOCATION);
417         break;
418     case GL_COLOR_ARRAY:
419         retval = int(COLOR_LOCATION);
420         break;
421     case GL_POINT_SIZE_ARRAY_OES:
422         retval = int(POINTSIZE_LOCATION);
423         break;
424     case GL_TEXTURE_COORD_ARRAY:
425         retval = int (TEXCOORD0_LOCATION + m_activeTexture);
426         break;
427     case GL_MATRIX_INDEX_ARRAY_OES:
428         retval = int (MATRIXINDEX_LOCATION);
429         break;
430     case GL_WEIGHT_ARRAY_OES:
431         retval = int (WEIGHT_LOCATION);
432         break;
433     default:
434         retval = loc;
435     }
436     return retval;
437 }
438 
sClearIndexedBufferBinding(GLuint id,std::vector<GLClientState::BufferBinding> & bindings)439 static void sClearIndexedBufferBinding(GLuint id, std::vector<GLClientState::BufferBinding>& bindings) {
440     for (size_t i = 0; i < bindings.size(); i++) {
441         if (bindings[i].buffer == id) {
442             bindings[i].offset = 0;
443             bindings[i].stride = 0;
444             bindings[i].effectiveStride = 16;
445             bindings[i].size = 0;
446             bindings[i].buffer = 0;
447         }
448     }
449 }
450 
451 #ifdef GFXSTREAM
452 
addBuffer(GLuint id)453 void GLClientState::addBuffer(GLuint id) {
454     mBufferIds.add(id);
455     mBufferIds.set(id, true);
456     mHostMappedBufferDirty.add(id);
457 }
458 
removeBuffer(GLuint id)459 void GLClientState::removeBuffer(GLuint id) {
460     mHostMappedBufferDirty.remove(id);
461     mBufferIds.remove(id);
462 }
463 
bufferIdExists(GLuint id) const464 bool GLClientState::bufferIdExists(GLuint id) const {
465     return mBufferIds.get(id);
466 }
467 
setBufferHostMapDirty(GLuint id,bool dirty)468 void GLClientState::setBufferHostMapDirty(GLuint id, bool dirty) {
469     mHostMappedBufferDirty.set(id, dirty);
470 }
471 
isBufferHostMapDirty(GLuint id) const472 bool GLClientState::isBufferHostMapDirty(GLuint id) const {
473     return mHostMappedBufferDirty.get(id);
474 }
475 
setExistence(ObjectType type,bool exists,GLsizei count,const GLuint * ids)476 void GLClientState::setExistence(ObjectType type, bool exists, GLsizei count, const GLuint* ids) {
477     if (type == ObjectType::Sampler) {
478         SamplerInfo::ScopedView view(mSamplerInfo);
479         if (exists) {
480             for (GLsizei i = 0; i < count; ++i) {
481                 view.addFresh(ids[i]);
482             }
483         } else {
484             for (GLsizei i = 0; i < count; ++i) {
485                 view.unref(ids[i]);
486             }
487         }
488     } else {
489         ExistenceMap* existenceMap = &mBufferIds;
490 
491         switch (type) {
492             case ObjectType::Buffer:
493                 existenceMap = &mBufferIds;
494                 break;
495             case ObjectType::TransformFeedback:
496                 existenceMap = &mTransformFeedbackIds;
497                 break;
498             case ObjectType::Query:
499                 existenceMap = &mQueryIds;
500                 for (GLsizei i = 0; i < count; ++i) {
501                     // reset the last query target
502                     mLastQueryTargets.add(ids[i], 0);
503                 }
504                 break;
505             case ObjectType::Sampler:
506             default:
507                 ALOGE("%s: Unreachable code\n", __func__);
508                 abort();
509         }
510 
511         if (exists) {
512             for (GLsizei i = 0; i < count; ++i) {
513                 existenceMap->add(ids[i]);
514                 existenceMap->set(ids[i], true);
515             }
516         } else {
517             for (GLsizei i = 0; i < count; ++i) {
518                 existenceMap->remove(ids[i]);
519             }
520         }
521     }
522 }
523 
queryExistence(ObjectType type,GLuint id) const524 bool GLClientState::queryExistence(ObjectType type, GLuint id) const {
525     switch (type) {
526         case ObjectType::Buffer:
527             return mBufferIds.get(id);
528         case ObjectType::TransformFeedback:
529             return mTransformFeedbackIds.get(id);
530         case ObjectType::Sampler:
531             return samplerExists(id);
532         case ObjectType::Query:
533             return mQueryIds.get(id);
534         default:
535             ALOGD("%s: unknown object type: 0x%x\n", __func__, type);
536             abort();
537     }
538 }
539 
samplerExists(GLuint id) const540 bool GLClientState::samplerExists(GLuint id) const {
541     if (!id) return true;
542     SamplerInfo::ScopedView view(mSamplerInfo);
543     return view.samplerExists(id);
544 }
545 
tryBind(GLenum target,GLuint id)546 bool GLClientState::tryBind(GLenum target, GLuint id) {
547     if (0 == id) { // unbind operation
548         switch (target) {
549             case GL_TRANSFORM_FEEDBACK:
550                 mBoundTransformFeedbackValidity.id = 0;
551                 mBoundTransformFeedbackValidity.valid = true;
552                 break;
553             case GL_ANY_SAMPLES_PASSED:
554                 mBoundQueryValidity_AnySamplesPassed.id = 0;
555                 mBoundQueryValidity_AnySamplesPassed.valid = false;
556                 break;
557             case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
558                 mBoundQueryValidity_AnySamplesPassedConservative.id = 0;
559                 mBoundQueryValidity_AnySamplesPassedConservative.valid = false;
560                 break;
561             case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
562                 mBoundQueryValidity_TransformFeedbackPrimitivesWritten.id = 0;
563                 mBoundQueryValidity_TransformFeedbackPrimitivesWritten.valid = false;
564                 break;
565             default:
566                 ALOGE("%s: target 0x%x not yet supported in new state tracking model\n", __func__, target);
567                 abort();
568         }
569         return true;
570     }
571 
572     switch (target) {
573         case GL_TRANSFORM_FEEDBACK:
574             if (!queryExistence(ObjectType::TransformFeedback, id)) return false;
575             break;
576         case GL_ANY_SAMPLES_PASSED:
577         case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
578         case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
579             if (!queryExistence(ObjectType::Query, id)) {
580                 return false;
581             }
582             break;
583         default:
584             ALOGE("%s: target 0x%x not yet supported in new state tracking model\n", __func__, target);
585             abort();
586     }
587 
588     // valid bind
589     switch (target) {
590     case GL_TRANSFORM_FEEDBACK:
591         mBoundTransformFeedbackValidity.id = id;
592         mBoundTransformFeedbackValidity.valid = true;
593         break;
594     case GL_ANY_SAMPLES_PASSED:
595         mBoundQueryValidity_AnySamplesPassed.id = id;
596         mBoundQueryValidity_AnySamplesPassed.valid = true;
597         break;
598     case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
599         mBoundQueryValidity_AnySamplesPassedConservative.id = id;
600         mBoundQueryValidity_AnySamplesPassedConservative.valid = true;
601         break;
602     case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
603         mBoundQueryValidity_TransformFeedbackPrimitivesWritten.id = id;
604         mBoundQueryValidity_TransformFeedbackPrimitivesWritten.valid = true;
605         break;
606     default:
607         ALOGE("%s: target 0x%x not yet supported in new state tracking model\n", __func__, target);
608         abort();
609     }
610     return true;
611 }
612 
isBoundTargetValid(GLenum target)613 bool GLClientState::isBoundTargetValid(GLenum target) {
614     switch (target) {
615     case GL_TRANSFORM_FEEDBACK:
616         return mBoundTransformFeedbackValidity.valid;
617     case GL_ANY_SAMPLES_PASSED:
618         return mBoundQueryValidity_AnySamplesPassed.valid;
619     case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
620         return mBoundQueryValidity_AnySamplesPassedConservative.valid;
621     case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
622         return mBoundQueryValidity_TransformFeedbackPrimitivesWritten.valid;
623     default:
624         ALOGE("%s: target 0x%x not yet supported in new state tracking model\n", __func__, target);
625         abort();
626     }
627 }
628 
isQueryBound(GLenum target)629 bool GLClientState::isQueryBound(GLenum target) {
630     switch (target) {
631     case GL_ANY_SAMPLES_PASSED:
632         return mBoundQueryValidity_AnySamplesPassed.valid;
633     case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
634         return mBoundQueryValidity_AnySamplesPassedConservative.valid;
635     case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
636         return mBoundQueryValidity_TransformFeedbackPrimitivesWritten.valid;
637     default:
638         return false;
639     }
640 }
641 
isQueryObjectActive(GLuint id)642 bool GLClientState::isQueryObjectActive(GLuint id) {
643     if (mBoundQueryValidity_AnySamplesPassed.valid &&
644         (id == mBoundQueryValidity_AnySamplesPassed.id))
645         return true;
646     if (mBoundQueryValidity_AnySamplesPassedConservative.valid &&
647         (id == mBoundQueryValidity_AnySamplesPassedConservative.id))
648         return true;
649     if (mBoundQueryValidity_TransformFeedbackPrimitivesWritten.valid &&
650         (id == mBoundQueryValidity_TransformFeedbackPrimitivesWritten.id))
651         return true;
652     return false;
653 }
654 
setLastQueryTarget(GLenum target,GLuint id)655 void GLClientState::setLastQueryTarget(GLenum target, GLuint id) {
656     mLastQueryTargets.add(id, target);
657 }
658 
getLastQueryTarget(GLuint id)659 GLenum GLClientState::getLastQueryTarget(GLuint id) {
660     auto targetPtr = mLastQueryTargets.get_const(id);
661     if (!targetPtr) return 0;
662     return *targetPtr;
663 }
664 
665 #else // GFXSTREAM
666 
addBuffer(GLuint id)667 void GLClientState::addBuffer(GLuint id) {
668     mBufferIds.insert(id);
669 }
670 
removeBuffer(GLuint id)671 void GLClientState::removeBuffer(GLuint id) {
672     mBufferIds.erase(id);
673 }
674 
bufferIdExists(GLuint id) const675 bool GLClientState::bufferIdExists(GLuint id) const {
676     return mBufferIds.find(id) != mBufferIds.end();
677 }
678 
setBufferHostMapDirty(GLuint id,bool dirty)679 void GLClientState::setBufferHostMapDirty(GLuint id, bool dirty) {
680     (void)id;
681     (void)dirty;
682 }
683 
isBufferHostMapDirty(GLuint id) const684 bool GLClientState::isBufferHostMapDirty(GLuint id) const {
685     (void)id;
686     return true;
687 }
688 
setExistence(ObjectType,bool,GLsizei,const GLuint *)689 void GLClientState::setExistence(ObjectType, bool, GLsizei, const GLuint*) {
690     // no-op in non-gfxstream
691 }
692 
693 #endif // !GFXSTREAM
694 
setBoundPixelPackBufferDirtyForHostMap()695 void GLClientState::setBoundPixelPackBufferDirtyForHostMap() {
696     if (m_pixelPackBuffer)
697         setBufferHostMapDirty(m_pixelPackBuffer, true /* dirty */);
698 }
699 
setBoundTransformFeedbackBuffersDirtyForHostMap()700 void GLClientState::setBoundTransformFeedbackBuffersDirtyForHostMap() {
701     if (m_transformFeedbackBuffer)
702         setBufferHostMapDirty(
703             m_transformFeedbackBuffer,
704             true /* dirty */);
705 
706     for (size_t i = 0; i < m_indexedTransformFeedbackBuffers.size(); ++i)
707         if (m_indexedTransformFeedbackBuffers[i].buffer)
708             setBufferHostMapDirty(
709                 m_indexedTransformFeedbackBuffers[i].buffer,
710                 true /* dirty */);
711 }
712 
setBoundShaderStorageBuffersDirtyForHostMap()713 void GLClientState::setBoundShaderStorageBuffersDirtyForHostMap() {
714     if (m_glesMajorVersion == 3 && m_glesMinorVersion == 0) return;
715 
716     if (m_shaderStorageBuffer)
717         setBufferHostMapDirty(
718             m_shaderStorageBuffer,
719             true /* dirty */);
720 
721     for (size_t i = 0; i < m_indexedShaderStorageBuffers.size(); ++i)
722         if (m_indexedShaderStorageBuffers[i].buffer)
723             setBufferHostMapDirty(
724                 m_indexedShaderStorageBuffers[i].buffer,
725                 true /* dirty */);
726 }
727 
setBoundAtomicCounterBuffersDirtyForHostMap()728 void GLClientState::setBoundAtomicCounterBuffersDirtyForHostMap() {
729     if (m_glesMajorVersion == 3 && m_glesMinorVersion == 0) return;
730 
731     if (m_atomicCounterBuffer)
732         setBufferHostMapDirty(
733             m_atomicCounterBuffer,
734             true /* dirty */);
735 
736     for (size_t i = 0; i < m_indexedAtomicCounterBuffers.size(); ++i)
737         if (m_indexedAtomicCounterBuffers[i].buffer)
738             setBufferHostMapDirty(
739                 m_indexedAtomicCounterBuffers[i].buffer,
740                 true /* dirty */);
741 }
742 
unBindBuffer(GLuint id)743 void GLClientState::unBindBuffer(GLuint id) {
744     if (m_arrayBuffer == id) {
745         m_arrayBuffer = 0;
746         m_arrayBuffer_lastEncode = 0;
747     }
748 
749     if (m_currVaoState.iboId() == id) {
750         m_currVaoState.iboId() = 0;
751         m_currVaoState.iboIdLastEncode() = 0;
752     }
753 
754     if (m_copyReadBuffer == id)
755         m_copyReadBuffer = 0;
756     if (m_copyWriteBuffer == id)
757         m_copyWriteBuffer = 0;
758     if (m_pixelPackBuffer == id)
759         m_pixelPackBuffer = 0;
760     if (m_pixelUnpackBuffer == id)
761         m_pixelUnpackBuffer = 0;
762     if (m_transformFeedbackBuffer == id)
763         m_transformFeedbackBuffer = 0;
764     if (m_uniformBuffer == id)
765         m_uniformBuffer = 0;
766     if (m_atomicCounterBuffer == id)
767         m_atomicCounterBuffer = 0;
768     if (m_dispatchIndirectBuffer == id)
769         m_dispatchIndirectBuffer = 0;
770     if (m_drawIndirectBuffer == id)
771         m_drawIndirectBuffer = 0;
772     if (m_shaderStorageBuffer == id)
773         m_shaderStorageBuffer = 0;
774 
775     sClearIndexedBufferBinding(id, m_indexedTransformFeedbackBuffers);
776     sClearIndexedBufferBinding(id, m_indexedUniformBuffers);
777     sClearIndexedBufferBinding(id, m_indexedAtomicCounterBuffers);
778     sClearIndexedBufferBinding(id, m_indexedShaderStorageBuffers);
779     sClearIndexedBufferBinding(id, m_currVaoState.bufferBindings());
780     m_vaoAttribBindingCacheInvalid = 0xffff;
781     m_noClientArraysCache = 0;
782 }
783 
bindBuffer(GLenum target,GLuint id)784 int GLClientState::bindBuffer(GLenum target, GLuint id)
785 {
786     int err = 0;
787     switch(target) {
788     case GL_ARRAY_BUFFER:
789         m_arrayBuffer = id;
790         break;
791     case GL_ELEMENT_ARRAY_BUFFER:
792         m_currVaoState.iboId() = id;
793         break;
794     case GL_COPY_READ_BUFFER:
795         m_copyReadBuffer = id;
796         break;
797     case GL_COPY_WRITE_BUFFER:
798         m_copyWriteBuffer = id;
799         break;
800     case GL_PIXEL_PACK_BUFFER:
801         m_pixelPackBuffer = id;
802         break;
803     case GL_PIXEL_UNPACK_BUFFER:
804         m_pixelUnpackBuffer = id;
805         break;
806     case GL_TRANSFORM_FEEDBACK_BUFFER:
807         m_transformFeedbackBuffer = id;
808         break;
809     case GL_UNIFORM_BUFFER:
810         m_uniformBuffer = id;
811         break;
812     case GL_ATOMIC_COUNTER_BUFFER:
813         m_atomicCounterBuffer = id;
814         break;
815     case GL_DISPATCH_INDIRECT_BUFFER:
816         m_dispatchIndirectBuffer = id;
817         break;
818     case GL_DRAW_INDIRECT_BUFFER:
819         m_drawIndirectBuffer = id;
820         break;
821     case GL_SHADER_STORAGE_BUFFER:
822         m_shaderStorageBuffer = id;
823         break;
824     default:
825         err = -1;
826     }
827     return err;
828 }
829 
bindIndexedBuffer(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size,GLintptr stride,GLintptr effectiveStride)830 void GLClientState::bindIndexedBuffer(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride) {
831     switch (target) {
832     case GL_TRANSFORM_FEEDBACK_BUFFER:
833         m_indexedTransformFeedbackBuffers[index].buffer = buffer;
834         m_indexedTransformFeedbackBuffers[index].offset = offset;
835         m_indexedTransformFeedbackBuffers[index].size = size;
836         m_indexedTransformFeedbackBuffers[index].stride = stride;
837         break;
838     case GL_UNIFORM_BUFFER:
839         m_indexedUniformBuffers[index].buffer = buffer;
840         m_indexedUniformBuffers[index].offset = offset;
841         m_indexedUniformBuffers[index].size = size;
842         m_indexedUniformBuffers[index].stride = stride;
843         break;
844     case GL_ATOMIC_COUNTER_BUFFER:
845         m_indexedAtomicCounterBuffers[index].buffer = buffer;
846         m_indexedAtomicCounterBuffers[index].offset = offset;
847         m_indexedAtomicCounterBuffers[index].size = size;
848         m_indexedAtomicCounterBuffers[index].stride = stride;
849         break;
850     case GL_SHADER_STORAGE_BUFFER:
851         m_indexedShaderStorageBuffers[index].buffer = buffer;
852         m_indexedShaderStorageBuffers[index].offset = offset;
853         m_indexedShaderStorageBuffers[index].size = size;
854         m_indexedShaderStorageBuffers[index].stride = stride;
855         break;
856     default:
857         m_currVaoState.bufferBinding(index).buffer = buffer;
858         m_currVaoState.bufferBinding(index).offset = offset;
859         m_currVaoState.bufferBinding(index).size = size;
860         m_currVaoState.bufferBinding(index).stride = stride;
861         m_currVaoState.bufferBinding(index).effectiveStride = effectiveStride;
862         m_vaoAttribBindingCacheInvalid |= (1 << m_currVaoState.bufferBinding(index).vertexAttribLoc);
863         return;
864     }
865 }
866 
getMaxIndexedBufferBindings(GLenum target) const867 int GLClientState::getMaxIndexedBufferBindings(GLenum target) const {
868     switch (target) {
869     case GL_TRANSFORM_FEEDBACK_BUFFER:
870         return m_indexedTransformFeedbackBuffers.size();
871     case GL_UNIFORM_BUFFER:
872         return m_indexedUniformBuffers.size();
873     case GL_ATOMIC_COUNTER_BUFFER:
874         return m_indexedAtomicCounterBuffers.size();
875     case GL_SHADER_STORAGE_BUFFER:
876         return m_indexedShaderStorageBuffers.size();
877     default:
878         return m_currVaoState.bufferBindings_const().size();
879     }
880 }
881 
isNonIndexedBindNoOp(GLenum target,GLuint buffer)882 bool GLClientState::isNonIndexedBindNoOp(GLenum target, GLuint buffer) {
883     if (buffer != !getLastEncodedBufferBind(target)) return false;
884 
885     int idOrError = getBuffer(target);
886     if (idOrError < 0) {
887         return false;
888     } else {
889         return buffer == (GLuint)idOrError;
890     }
891 }
892 
isIndexedBindNoOp(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size,GLintptr stride,GLintptr effectiveStride)893 bool GLClientState::isIndexedBindNoOp(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride) {
894 
895     if (target == GL_TRANSFORM_FEEDBACK_BUFFER) return false;
896 
897     if (buffer != getLastEncodedBufferBind(target)) return false;
898 
899     switch (target) {
900     case GL_TRANSFORM_FEEDBACK_BUFFER:
901         return m_indexedTransformFeedbackBuffers[index].buffer == buffer &&
902                m_indexedTransformFeedbackBuffers[index].offset == offset &&
903                m_indexedTransformFeedbackBuffers[index].size == size &&
904                m_indexedTransformFeedbackBuffers[index].stride == stride;
905     case GL_UNIFORM_BUFFER:
906         return m_indexedUniformBuffers[index].buffer == buffer &&
907                m_indexedUniformBuffers[index].offset == offset &&
908                m_indexedUniformBuffers[index].size == size &&
909                m_indexedUniformBuffers[index].stride == stride;
910     case GL_ATOMIC_COUNTER_BUFFER:
911         return m_indexedAtomicCounterBuffers[index].buffer == buffer &&
912                m_indexedAtomicCounterBuffers[index].offset == offset &&
913                m_indexedAtomicCounterBuffers[index].size == size &&
914                m_indexedAtomicCounterBuffers[index].stride == stride;
915     case GL_SHADER_STORAGE_BUFFER:
916         return m_indexedShaderStorageBuffers[index].buffer == buffer &&
917                m_indexedShaderStorageBuffers[index].offset == offset &&
918                m_indexedShaderStorageBuffers[index].size == size &&
919                m_indexedShaderStorageBuffers[index].stride == stride;
920     default:
921         return m_currVaoState.bufferBinding(index).buffer == buffer &&
922                m_currVaoState.bufferBinding(index).offset == offset &&
923                m_currVaoState.bufferBinding(index).size == size &&
924                m_currVaoState.bufferBinding(index).stride == stride &&
925                m_currVaoState.bufferBinding(index).effectiveStride == effectiveStride;
926     }
927 }
928 
getMaxTextureSize() const929 int GLClientState::getMaxTextureSize() const {
930     return m_hostDriverCaps.max_texture_size;
931 }
932 
getMaxTextureSize3D() const933 int GLClientState::getMaxTextureSize3D() const {
934     return m_hostDriverCaps.max_texture_size_3d;
935 }
936 
getMaxTextureSizeCubeMap() const937 int GLClientState::getMaxTextureSizeCubeMap() const {
938     return m_hostDriverCaps.max_texture_size_cube_map;
939 }
940 
getLog2MaxTextureSize() const941 int GLClientState::getLog2MaxTextureSize() const {
942     return m_log2MaxTextureSize;
943 }
944 
postDraw()945 void GLClientState::postDraw() {
946     setBoundTransformFeedbackBuffersDirtyForHostMap();
947     setBoundShaderStorageBuffersDirtyForHostMap();
948     setBoundAtomicCounterBuffersDirtyForHostMap();
949 }
950 
postReadPixels()951 void GLClientState::postReadPixels() {
952     setBoundPixelPackBufferDirtyForHostMap();
953 }
954 
postDispatchCompute()955 void GLClientState::postDispatchCompute() {
956     setBoundShaderStorageBuffersDirtyForHostMap();
957     setBoundAtomicCounterBuffersDirtyForHostMap();
958 }
959 
shouldSkipHostMapBuffer(GLenum target)960 bool GLClientState::shouldSkipHostMapBuffer(GLenum target) {
961     GLuint id = getBuffer(target);
962     return !isBufferHostMapDirty(id);
963 }
964 
onHostMappedBuffer(GLenum target)965 void GLClientState::onHostMappedBuffer(GLenum target) {
966     GLuint id = getBuffer(target);
967     setBufferHostMapDirty(id, false /* not dirty */);
968 }
969 
getBuffer(GLenum target)970 int GLClientState::getBuffer(GLenum target) {
971     int ret=0;
972     switch (target) {
973         case GL_ARRAY_BUFFER:
974             ret = m_arrayBuffer;
975             break;
976         case GL_ELEMENT_ARRAY_BUFFER:
977             ret = m_currVaoState.iboId();
978             break;
979         case GL_COPY_READ_BUFFER:
980             ret = m_copyReadBuffer;
981             break;
982         case GL_COPY_WRITE_BUFFER:
983             ret = m_copyWriteBuffer;
984             break;
985         case GL_PIXEL_PACK_BUFFER:
986             ret = m_pixelPackBuffer;
987             break;
988         case GL_PIXEL_UNPACK_BUFFER:
989             ret = m_pixelUnpackBuffer;
990             break;
991         case GL_TRANSFORM_FEEDBACK_BUFFER:
992             ret = m_transformFeedbackBuffer;
993             break;
994         case GL_UNIFORM_BUFFER:
995             ret = m_uniformBuffer;
996             break;
997         case GL_ATOMIC_COUNTER_BUFFER:
998             ret = m_atomicCounterBuffer;
999             break;
1000         case GL_DISPATCH_INDIRECT_BUFFER:
1001             ret = m_dispatchIndirectBuffer;
1002             break;
1003         case GL_DRAW_INDIRECT_BUFFER:
1004             ret = m_drawIndirectBuffer;
1005             break;
1006         case GL_SHADER_STORAGE_BUFFER:
1007             ret = m_shaderStorageBuffer;
1008             break;
1009         default:
1010             ret = -1;
1011     }
1012     return ret;
1013 }
1014 
getLastEncodedBufferBind(GLenum target)1015 GLuint GLClientState::getLastEncodedBufferBind(GLenum target) {
1016     GLuint ret;
1017     switch (target)
1018     {
1019     case GL_ARRAY_BUFFER:
1020         ret = m_arrayBuffer_lastEncode;
1021         break;
1022     case GL_ELEMENT_ARRAY_BUFFER:
1023         ret = m_currVaoState.iboIdLastEncode();
1024         break;
1025     default:
1026     {
1027         int idOrError = getBuffer(target);
1028         ret = (idOrError < 0) ? 0 : (GLuint)idOrError;
1029     }
1030     }
1031 
1032     return ret;
1033 }
1034 
setLastEncodedBufferBind(GLenum target,GLuint id)1035 void GLClientState::setLastEncodedBufferBind(GLenum target, GLuint id)
1036 {
1037     switch (target)
1038     {
1039     case GL_ARRAY_BUFFER:
1040         m_arrayBuffer_lastEncode = id;
1041         break;
1042     case GL_ELEMENT_ARRAY_BUFFER:
1043         m_currVaoState.iboIdLastEncode() = id;
1044         break;
1045     default:
1046         break;
1047     }
1048 }
1049 
isTexture(GLuint tex_name) const1050 bool GLClientState::isTexture(GLuint tex_name) const {
1051     return getTextureRec(tex_name);
1052 }
1053 
isTextureWithStorage(GLuint tex_name) const1054 bool GLClientState::isTextureWithStorage(GLuint tex_name) const {
1055     TextureRec* rec = getTextureRec(tex_name);
1056     if (!rec) return false;
1057     return rec->hasStorage;
1058 }
1059 
isTextureCubeMap(GLuint tex_name) const1060 bool GLClientState::isTextureCubeMap(GLuint tex_name) const {
1061     TextureRec* texrec = getTextureRec(tex_name);
1062     if (!texrec) return false;
1063     switch (texrec->target) {
1064         case GL_TEXTURE_CUBE_MAP:
1065         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1066         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1067         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1068         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1069         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1070         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1071             return true;
1072         default:
1073             return false;
1074     }
1075 }
1076 
isRenderbuffer(GLuint name) const1077 bool GLClientState::isRenderbuffer(GLuint name) const {
1078     if (!name) return false;
1079 
1080     RenderbufferInfo::ScopedView view(mRboState.rboData);
1081     return view.hasRbo(name);
1082 }
1083 
isRenderbufferThatWasBound(GLuint name) const1084 bool GLClientState::isRenderbufferThatWasBound(GLuint name) const {
1085     if (!name) return true;
1086 
1087     RenderbufferInfo::ScopedView view(mRboState.rboData);
1088     if (!view.hasRbo(name)) return false;
1089 
1090     const RboProps* props = view.get_const(name);
1091     return props->previouslyBound;
1092 }
1093 
getClientStatePointer(GLenum pname,GLvoid ** params)1094 void GLClientState::getClientStatePointer(GLenum pname, GLvoid** params)
1095 {
1096     GLenum which_state = -1;
1097     switch (pname) {
1098     case GL_VERTEX_ARRAY_POINTER: {
1099         which_state = GLClientState::VERTEX_LOCATION;
1100         break;
1101         }
1102     case GL_NORMAL_ARRAY_POINTER: {
1103         which_state = GLClientState::NORMAL_LOCATION;
1104         break;
1105         }
1106     case GL_COLOR_ARRAY_POINTER: {
1107         which_state = GLClientState::COLOR_LOCATION;
1108         break;
1109         }
1110     case GL_TEXTURE_COORD_ARRAY_POINTER: {
1111         which_state = getActiveTexture() + GLClientState::TEXCOORD0_LOCATION;
1112         break;
1113         }
1114     case GL_POINT_SIZE_ARRAY_POINTER_OES: {
1115         which_state = GLClientState::POINTSIZE_LOCATION;
1116         break;
1117         }
1118     case GL_MATRIX_INDEX_ARRAY_POINTER_OES: {
1119         which_state = GLClientState::MATRIXINDEX_LOCATION;
1120         break;
1121         }
1122     case GL_WEIGHT_ARRAY_POINTER_OES: {
1123         which_state = GLClientState::WEIGHT_LOCATION;
1124         break;
1125         }
1126     }
1127     if (which_state != -1)
1128         *params = m_currVaoState[which_state].data;
1129 }
1130 
setPixelStore(GLenum param,GLint value)1131 int GLClientState::setPixelStore(GLenum param, GLint value)
1132 {
1133     int retval = 0;
1134     switch(param) {
1135     case GL_UNPACK_ALIGNMENT:
1136         m_pixelStore.unpack_alignment = value;
1137         break;
1138     case GL_PACK_ALIGNMENT:
1139         m_pixelStore.pack_alignment = value;
1140         break;
1141     case GL_UNPACK_ROW_LENGTH:
1142         m_pixelStore.unpack_row_length = value;
1143         break;
1144     case GL_UNPACK_IMAGE_HEIGHT:
1145         m_pixelStore.unpack_image_height = value;
1146         break;
1147     case GL_UNPACK_SKIP_PIXELS:
1148         m_pixelStore.unpack_skip_pixels = value;
1149         break;
1150     case GL_UNPACK_SKIP_ROWS:
1151         m_pixelStore.unpack_skip_rows = value;
1152         break;
1153     case GL_UNPACK_SKIP_IMAGES:
1154         m_pixelStore.unpack_skip_images = value;
1155         break;
1156     case GL_PACK_ROW_LENGTH:
1157         m_pixelStore.pack_row_length = value;
1158         break;
1159     case GL_PACK_SKIP_PIXELS:
1160         m_pixelStore.pack_skip_pixels = value;
1161         break;
1162     case GL_PACK_SKIP_ROWS:
1163         m_pixelStore.pack_skip_rows = value;
1164         break;
1165     default:
1166         retval = GL_INVALID_ENUM;
1167     }
1168     return retval;
1169 }
1170 
1171 
pixelDataSize(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int pack) const1172 size_t GLClientState::pixelDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const
1173 {
1174     if (width <= 0 || height <= 0 || depth <= 0) return 0;
1175 
1176     ALOGV("%s: pack? %d", __FUNCTION__, pack);
1177     if (pack) {
1178         ALOGV("%s: pack stats", __FUNCTION__);
1179         ALOGV("%s: pack align %d", __FUNCTION__, m_pixelStore.pack_alignment);
1180         ALOGV("%s: pack rowlen %d", __FUNCTION__, m_pixelStore.pack_row_length);
1181         ALOGV("%s: pack skippixels %d", __FUNCTION__, m_pixelStore.pack_skip_pixels);
1182         ALOGV("%s: pack skiprows %d", __FUNCTION__, m_pixelStore.pack_skip_rows);
1183     } else {
1184         ALOGV("%s: unpack stats", __FUNCTION__);
1185         ALOGV("%s: unpack align %d", __FUNCTION__, m_pixelStore.unpack_alignment);
1186         ALOGV("%s: unpack rowlen %d", __FUNCTION__, m_pixelStore.unpack_row_length);
1187         ALOGV("%s: unpack imgheight %d", __FUNCTION__, m_pixelStore.unpack_image_height);
1188         ALOGV("%s: unpack skippixels %d", __FUNCTION__, m_pixelStore.unpack_skip_pixels);
1189         ALOGV("%s: unpack skiprows %d", __FUNCTION__, m_pixelStore.unpack_skip_rows);
1190         ALOGV("%s: unpack skipimages %d", __FUNCTION__, m_pixelStore.unpack_skip_images);
1191     }
1192     return GLESTextureUtils::computeTotalImageSize(
1193             width, height, depth,
1194             format, type,
1195             pack ? m_pixelStore.pack_alignment : m_pixelStore.unpack_alignment,
1196             pack ? m_pixelStore.pack_row_length : m_pixelStore.unpack_row_length,
1197             pack ? 0 : m_pixelStore.unpack_image_height,
1198             pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
1199             pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
1200             pack ? 0 : m_pixelStore.unpack_skip_images);
1201 }
1202 
pboNeededDataSize(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int pack) const1203 size_t GLClientState::pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const
1204 {
1205     if (width <= 0 || height <= 0 || depth <= 0) return 0;
1206 
1207     ALOGV("%s: pack? %d", __FUNCTION__, pack);
1208     if (pack) {
1209         ALOGV("%s: pack stats", __FUNCTION__);
1210         ALOGV("%s: pack align %d", __FUNCTION__, m_pixelStore.pack_alignment);
1211         ALOGV("%s: pack rowlen %d", __FUNCTION__, m_pixelStore.pack_row_length);
1212         ALOGV("%s: pack skippixels %d", __FUNCTION__, m_pixelStore.pack_skip_pixels);
1213         ALOGV("%s: pack skiprows %d", __FUNCTION__, m_pixelStore.pack_skip_rows);
1214     } else {
1215         ALOGV("%s: unpack stats", __FUNCTION__);
1216         ALOGV("%s: unpack align %d", __FUNCTION__, m_pixelStore.unpack_alignment);
1217         ALOGV("%s: unpack rowlen %d", __FUNCTION__, m_pixelStore.unpack_row_length);
1218         ALOGV("%s: unpack imgheight %d", __FUNCTION__, m_pixelStore.unpack_image_height);
1219         ALOGV("%s: unpack skippixels %d", __FUNCTION__, m_pixelStore.unpack_skip_pixels);
1220         ALOGV("%s: unpack skiprows %d", __FUNCTION__, m_pixelStore.unpack_skip_rows);
1221         ALOGV("%s: unpack skipimages %d", __FUNCTION__, m_pixelStore.unpack_skip_images);
1222     }
1223     return GLESTextureUtils::computeNeededBufferSize(
1224             width, height, depth,
1225             format, type,
1226             pack ? m_pixelStore.pack_alignment : m_pixelStore.unpack_alignment,
1227             pack ? m_pixelStore.pack_row_length : m_pixelStore.unpack_row_length,
1228             pack ? 0 : m_pixelStore.unpack_image_height,
1229             pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
1230             pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
1231             pack ? 0 : m_pixelStore.unpack_skip_images);
1232 }
1233 
1234 
clearBufferNumElts(GLenum buffer) const1235 size_t GLClientState::clearBufferNumElts(GLenum buffer) const
1236 {
1237     switch (buffer) {
1238     case GL_COLOR:
1239         return 4;
1240     case GL_DEPTH:
1241     case GL_STENCIL:
1242         return 1;
1243     }
1244     return 1;
1245 }
1246 
getPackingOffsets2D(GLsizei width,GLsizei height,GLenum format,GLenum type,int * bpp,int * startOffset,int * pixelRowSize,int * totalRowSize,int * skipRows) const1247 void GLClientState::getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
1248 {
1249     if (width <= 0 || height <= 0) {
1250         *startOffset = 0;
1251         *pixelRowSize = 0;
1252         *totalRowSize = 0;
1253         return;
1254     }
1255 
1256     GLESTextureUtils::computePackingOffsets2D(
1257             width, height,
1258             format, type,
1259             m_pixelStore.pack_alignment,
1260             m_pixelStore.pack_row_length,
1261             m_pixelStore.pack_skip_pixels,
1262             m_pixelStore.pack_skip_rows,
1263             bpp,
1264             startOffset,
1265             pixelRowSize,
1266             totalRowSize);
1267 
1268     *skipRows = m_pixelStore.pack_skip_rows;
1269 }
1270 
getUnpackingOffsets2D(GLsizei width,GLsizei height,GLenum format,GLenum type,int * bpp,int * startOffset,int * pixelRowSize,int * totalRowSize,int * skipRows) const1271 void GLClientState::getUnpackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
1272 {
1273     if (width <= 0 || height <= 0) {
1274         *startOffset = 0;
1275         *pixelRowSize = 0;
1276         *totalRowSize = 0;
1277         return;
1278     }
1279 
1280     GLESTextureUtils::computePackingOffsets2D(
1281             width, height,
1282             format, type,
1283             m_pixelStore.unpack_alignment,
1284             m_pixelStore.unpack_row_length,
1285             m_pixelStore.unpack_skip_pixels,
1286             m_pixelStore.unpack_skip_rows,
1287             bpp,
1288             startOffset,
1289             pixelRowSize,
1290             totalRowSize);
1291 
1292     *skipRows = m_pixelStore.unpack_skip_rows;
1293 }
1294 
getUnpackingOffsets3D(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int * bpp,int * startOffset,int * pixelRowSize,int * totalRowSize,int * pixelImageSize,int * totalImageSize,int * skipRows,int * skipImages) const1295 void GLClientState::getUnpackingOffsets3D(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* pixelImageSize, int* totalImageSize, int* skipRows, int* skipImages) const
1296 {
1297     if (width <= 0 || height <= 0) {
1298         *startOffset = 0;
1299         *pixelRowSize = 0;
1300         *totalRowSize = 0;
1301         return;
1302     }
1303 
1304     GLESTextureUtils::computePackingOffsets3D(
1305             width, height, depth,
1306             format, type,
1307             m_pixelStore.unpack_alignment,
1308             m_pixelStore.unpack_row_length,
1309             m_pixelStore.unpack_image_height,
1310             m_pixelStore.unpack_skip_pixels,
1311             m_pixelStore.unpack_skip_rows,
1312             m_pixelStore.unpack_skip_images,
1313             bpp,
1314             startOffset,
1315             pixelRowSize,
1316             totalRowSize,
1317             pixelImageSize,
1318             totalImageSize);
1319 
1320     *skipRows = m_pixelStore.unpack_skip_rows;
1321     *skipImages = m_pixelStore.unpack_skip_images;
1322 }
1323 
setNumActiveUniformsInUniformBlock(GLuint program,GLuint uniformBlockIndex,GLint numActiveUniforms)1324 void GLClientState::setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms) {
1325     UniformBlockInfoKey key;
1326     key.program = program;
1327     key.uniformBlockIndex = uniformBlockIndex;
1328 
1329     UniformBlockUniformInfo info;
1330     info.numActiveUniforms = (size_t)numActiveUniforms;
1331 
1332     m_uniformBlockInfoMap[key] = info;
1333 }
1334 
numActiveUniformsInUniformBlock(GLuint program,GLuint uniformBlockIndex) const1335 size_t GLClientState::numActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex) const {
1336     UniformBlockInfoKey key;
1337     key.program = program;
1338     key.uniformBlockIndex = uniformBlockIndex;
1339     UniformBlockInfoMap::const_iterator it =
1340         m_uniformBlockInfoMap.find(key);
1341     if (it == m_uniformBlockInfoMap.end()) return 0;
1342     return it->second.numActiveUniforms;
1343 }
1344 
associateProgramWithPipeline(GLuint program,GLuint pipeline)1345 void GLClientState::associateProgramWithPipeline(GLuint program, GLuint pipeline) {
1346     m_programPipelines[program] = pipeline;
1347 }
1348 
programPipelineBegin()1349 GLClientState::ProgramPipelineIterator GLClientState::programPipelineBegin() {
1350     return m_programPipelines.begin();
1351 }
1352 
programPipelineEnd()1353 GLClientState::ProgramPipelineIterator GLClientState::programPipelineEnd() {
1354     return m_programPipelines.end();
1355 }
1356 
setActiveTextureUnit(GLenum texture)1357 GLenum GLClientState::setActiveTextureUnit(GLenum texture)
1358 {
1359     GLuint unit = texture - GL_TEXTURE0;
1360     if (unit >= MAX_TEXTURE_UNITS) {
1361         return GL_INVALID_ENUM;
1362     }
1363     m_tex.activeUnit = &m_tex.unit[unit];
1364     return GL_NO_ERROR;
1365 }
1366 
getActiveTextureUnit() const1367 GLenum GLClientState::getActiveTextureUnit() const
1368 {
1369     return GL_TEXTURE0 + (m_tex.activeUnit - &m_tex.unit[0]);
1370 }
1371 
enableTextureTarget(GLenum target)1372 void GLClientState::enableTextureTarget(GLenum target)
1373 {
1374     switch (target) {
1375     case GL_TEXTURE_2D:
1376         m_tex.activeUnit->enables |= (1u << TEXTURE_2D);
1377         break;
1378     case GL_TEXTURE_EXTERNAL_OES:
1379         m_tex.activeUnit->enables |= (1u << TEXTURE_EXTERNAL);
1380         break;
1381     }
1382 }
1383 
disableTextureTarget(GLenum target)1384 void GLClientState::disableTextureTarget(GLenum target)
1385 {
1386     switch (target) {
1387     case GL_TEXTURE_2D:
1388         m_tex.activeUnit->enables &= ~(1u << TEXTURE_2D);
1389         break;
1390     case GL_TEXTURE_EXTERNAL_OES:
1391         m_tex.activeUnit->enables &= ~(1u << TEXTURE_EXTERNAL);
1392         break;
1393     }
1394 }
1395 
bindSampler(GLuint unit,GLuint sampler)1396 bool GLClientState::bindSampler(GLuint unit, GLuint sampler) {
1397     SamplerInfo::ScopedView view(mSamplerInfo);
1398     view.ref(sampler);
1399     if (m_tex.unit[unit].boundSampler) {
1400         view.unref(sampler);
1401     }
1402     m_tex.unit[unit].boundSampler = sampler;
1403     return true;
1404 }
1405 
isSamplerBindNoOp(GLuint unit,GLuint sampler)1406 bool GLClientState::isSamplerBindNoOp(GLuint unit, GLuint sampler) {
1407     return m_tex.unit[unit].boundSampler == sampler;
1408 }
1409 
onDeleteSamplers(GLsizei n,const GLuint * samplers)1410 void GLClientState::onDeleteSamplers(GLsizei n, const GLuint* samplers) {
1411     for (uint32_t i = 0; i < n; ++i) {
1412         for (uint32_t j = 0; j < MAX_TEXTURE_UNITS; ++j) {
1413             uint32_t currentSampler = m_tex.unit[j].boundSampler;
1414             if (currentSampler == samplers[i]) {
1415                 m_tex.unit[j].boundSampler = 0;
1416             }
1417         }
1418     }
1419 }
1420 
getPriorityEnabledTarget(GLenum allDisabled) const1421 GLenum GLClientState::getPriorityEnabledTarget(GLenum allDisabled) const
1422 {
1423     unsigned int enables = m_tex.activeUnit->enables;
1424     if (enables & (1u << TEXTURE_EXTERNAL)) {
1425         return GL_TEXTURE_EXTERNAL_OES;
1426     } else if (enables & (1u << TEXTURE_2D)) {
1427         return GL_TEXTURE_2D;
1428     } else {
1429         return allDisabled;
1430     }
1431 }
1432 
compareTexId(const void * pid,const void * prec)1433 int GLClientState::compareTexId(const void* pid, const void* prec)
1434 {
1435     const GLuint* id = (const GLuint*)pid;
1436     const TextureRec* rec = (const TextureRec*)prec;
1437     return (GLint)(*id) - (GLint)rec->id;
1438 }
1439 
bindTexture(GLenum target,GLuint texture,GLboolean * firstUse)1440 GLenum GLClientState::bindTexture(GLenum target, GLuint texture,
1441         GLboolean* firstUse)
1442 {
1443     GLboolean first = GL_FALSE;
1444 
1445     TextureRec* texrec = getTextureRec(texture);
1446     if (!texrec) {
1447         texrec = addTextureRec(texture, target);
1448     }
1449 
1450     if (texture && target != texrec->target &&
1451         (target != GL_TEXTURE_EXTERNAL_OES &&
1452          texrec->target != GL_TEXTURE_EXTERNAL_OES)) {
1453         return GL_INVALID_OPERATION;
1454     }
1455 
1456     switch (target) {
1457     case GL_TEXTURE_2D:
1458         m_tex.activeUnit->texture[TEXTURE_2D] = texture;
1459         break;
1460     case GL_TEXTURE_EXTERNAL_OES:
1461         m_tex.activeUnit->texture[TEXTURE_EXTERNAL] = texture;
1462         break;
1463     case GL_TEXTURE_CUBE_MAP:
1464         m_tex.activeUnit->texture[TEXTURE_CUBE_MAP] = texture;
1465         break;
1466     case GL_TEXTURE_2D_ARRAY:
1467         m_tex.activeUnit->texture[TEXTURE_2D_ARRAY] = texture;
1468         break;
1469     case GL_TEXTURE_3D:
1470         m_tex.activeUnit->texture[TEXTURE_3D] = texture;
1471         break;
1472     case GL_TEXTURE_2D_MULTISAMPLE:
1473         m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE] = texture;
1474         break;
1475     }
1476 
1477     if (firstUse) {
1478         *firstUse = first;
1479     }
1480 
1481     return GL_NO_ERROR;
1482 }
1483 
setBoundEGLImage(GLenum target,GLeglImageOES image,int width,int height)1484 void GLClientState::setBoundEGLImage(GLenum target, GLeglImageOES image, int width, int height) {
1485     (void)image;
1486 
1487     if (target == GL_RENDERBUFFER) {
1488         if (!boundRenderbuffer()) return;
1489         setBoundRenderbufferEGLImageBacked();
1490         setBoundRenderbufferFormat(GL_RGBA);
1491         setBoundRenderbufferSamples(0);
1492         setBoundRenderbufferDimensions(width, height);
1493     } else {
1494         GLuint texture = getBoundTexture(target);
1495         TextureRec* texrec = getTextureRec(texture);
1496         if (!texrec) return;
1497         texrec->boundEGLImage = true;
1498         setBoundTextureInternalFormat(target, GL_RGBA);
1499         setBoundTextureFormat(target, GL_RGBA);
1500         setBoundTextureType(target, GL_UNSIGNED_BYTE);
1501         setBoundTextureSamples(target, 0);
1502         setBoundTextureDims(target, target, 0, width, height, 1);
1503     }
1504 }
1505 
addTextureRec(GLuint id,GLenum target)1506 TextureRec* GLClientState::addTextureRec(GLuint id, GLenum target)
1507 {
1508     TextureRec* tex = new TextureRec;
1509     tex->id = id;
1510     tex->target = target;
1511     tex->format = -1;
1512     tex->multisamples = 0;
1513     tex->immutable = false;
1514     tex->boundEGLImage = false;
1515     tex->hasStorage = false;
1516     tex->dims = new TextureDims[6];
1517     tex->hasCubeNegX = false;
1518     tex->hasCubePosX = false;
1519     tex->hasCubeNegY = false;
1520     tex->hasCubePosY = false;
1521     tex->hasCubeNegZ = false;
1522     tex->hasCubePosZ = false;
1523 
1524     (*(m_tex.textureRecs))[id] = tex;
1525     return tex;
1526 }
1527 
getTextureRec(GLuint id) const1528 TextureRec* GLClientState::getTextureRec(GLuint id) const {
1529     SharedTextureDataMap::const_iterator it =
1530         m_tex.textureRecs->find(id);
1531     if (it == m_tex.textureRecs->end()) {
1532         return NULL;
1533     }
1534     return it->second;
1535 }
1536 
setBoundTextureInternalFormat(GLenum target,GLint internalformat)1537 void GLClientState::setBoundTextureInternalFormat(GLenum target, GLint internalformat) {
1538     GLuint texture = getBoundTexture(target);
1539     TextureRec* texrec = getTextureRec(texture);
1540     if (!texrec) return;
1541     texrec->internalformat = internalformat;
1542 }
1543 
setBoundTextureFormat(GLenum target,GLenum format)1544 void GLClientState::setBoundTextureFormat(GLenum target, GLenum format) {
1545     GLuint texture = getBoundTexture(target);
1546     TextureRec* texrec = getTextureRec(texture);
1547     if (!texrec) return;
1548     texrec->format = format;
1549 }
1550 
setBoundTextureType(GLenum target,GLenum type)1551 void GLClientState::setBoundTextureType(GLenum target, GLenum type) {
1552     GLuint texture = getBoundTexture(target);
1553     TextureRec* texrec = getTextureRec(texture);
1554     if (!texrec) return;
1555     texrec->type = type;
1556 }
1557 
textureDimArrayOfCubeTarget(GLenum cubetarget)1558 static size_t textureDimArrayOfCubeTarget(GLenum cubetarget) {
1559     switch (cubetarget) {
1560         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1561             return 0;
1562         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1563             return 1;
1564         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1565             return 2;
1566         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1567             return 3;
1568         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1569             return 4;
1570         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1571             return 5;
1572     }
1573     return 0;
1574 }
1575 
setBoundTextureDims(GLenum target,GLenum cubetarget,GLsizei level,GLsizei width,GLsizei height,GLsizei depth)1576 void GLClientState::setBoundTextureDims(GLenum target, GLenum cubetarget, GLsizei level, GLsizei width, GLsizei height, GLsizei depth) {
1577     GLuint texture = getBoundTexture(target);
1578     TextureRec* texrec = getTextureRec(texture);
1579     if (!texrec) {
1580         return;
1581     }
1582 
1583     texrec->hasStorage = true;
1584 
1585     size_t indexToSet = 0;
1586 
1587     if (target == GL_TEXTURE_CUBE_MAP) {
1588         if (-1 == cubetarget) {
1589             setBoundTextureDims(target, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, width, height, depth);
1590             setBoundTextureDims(target, GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, width, height, depth);
1591             setBoundTextureDims(target, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, width, height, depth);
1592             setBoundTextureDims(target, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, width, height, depth);
1593             setBoundTextureDims(target, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, width, height, depth);
1594             setBoundTextureDims(target, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, width, height, depth);
1595             return;
1596         }
1597         indexToSet = textureDimArrayOfCubeTarget(cubetarget);
1598     }
1599 
1600 
1601     if (level == -1) {
1602         GLsizei curr_width = width;
1603         GLsizei curr_height = height;
1604         GLsizei curr_depth = depth;
1605         GLsizei curr_level = 0;
1606 
1607         while (true) {
1608             texrec->dims[indexToSet].widths[curr_level] = curr_width;
1609             texrec->dims[indexToSet].heights[curr_level] = curr_height;
1610             texrec->dims[indexToSet].depths[curr_level] = curr_depth;
1611             if (curr_width >> 1 == 0 &&
1612                 curr_height >> 1 == 0 &&
1613                 ((target == GL_TEXTURE_3D && curr_depth == 0) ||
1614                  true)) {
1615                 break;
1616             }
1617             curr_width = (curr_width >> 1) ? (curr_width >> 1) : 1;
1618             curr_height = (curr_height >> 1) ? (curr_height >> 1) : 1;
1619             if (target == GL_TEXTURE_3D) {
1620                 curr_depth = (curr_depth >> 1) ? (curr_depth >> 1) : 1;
1621             }
1622             curr_level++;
1623         }
1624 
1625     } else {
1626         texrec->dims[indexToSet].widths[level] = width;
1627         texrec->dims[indexToSet].heights[level] = height;
1628         texrec->dims[indexToSet].depths[level] = depth;
1629     }
1630 
1631     setFboCompletenessDirtyForTexture(texture);
1632 }
1633 
setBoundTextureSamples(GLenum target,GLsizei samples)1634 void GLClientState::setBoundTextureSamples(GLenum target, GLsizei samples) {
1635     GLuint texture = getBoundTexture(target);
1636     TextureRec* texrec = getTextureRec(texture);
1637     if (!texrec) return;
1638     texrec->multisamples = samples;
1639 }
1640 
addTextureCubeMapImage(GLenum stateTarget,GLenum cubeTarget)1641 void GLClientState::addTextureCubeMapImage(GLenum stateTarget, GLenum cubeTarget) {
1642     if (stateTarget != GL_TEXTURE_CUBE_MAP) return;
1643 
1644     GLuint texture = getBoundTexture(stateTarget);
1645     TextureRec* texrec = getTextureRec(texture);
1646     if (!texrec) return;
1647 
1648     switch (cubeTarget) {
1649         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1650             texrec->hasCubeNegX = true;
1651             return;
1652         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1653             texrec->hasCubePosX = true;
1654             return;
1655         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1656             texrec->hasCubeNegY = true;
1657             return;
1658         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1659             texrec->hasCubePosY = true;
1660             return;
1661         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1662             texrec->hasCubeNegZ = true;
1663             return;
1664         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1665             texrec->hasCubePosZ = true;
1666             return;
1667     }
1668 }
1669 
setBoundTextureImmutableFormat(GLenum target)1670 void GLClientState::setBoundTextureImmutableFormat(GLenum target) {
1671     GLuint texture = getBoundTexture(target);
1672     TextureRec* texrec = getTextureRec(texture);
1673     if (!texrec) return;
1674     texrec->immutable = true;
1675     if (target == GL_TEXTURE_CUBE_MAP) {
1676         texrec->hasCubeNegX = true;
1677         texrec->hasCubePosX = true;
1678         texrec->hasCubeNegY = true;
1679         texrec->hasCubePosY = true;
1680         texrec->hasCubeNegZ = true;
1681         texrec->hasCubePosZ = true;
1682     }
1683 }
1684 
isBoundTextureImmutableFormat(GLenum target) const1685 bool GLClientState::isBoundTextureImmutableFormat(GLenum target) const {
1686     GLuint texture = getBoundTexture(target);
1687     TextureRec* texrec = getTextureRec(texture);
1688     if (!texrec) return false;
1689     return texrec->immutable;
1690 }
1691 
isBoundTextureComplete(GLenum target) const1692 bool GLClientState::isBoundTextureComplete(GLenum target) const {
1693     GLuint texture = getBoundTexture(target);
1694     TextureRec* texrec = getTextureRec(texture);
1695     if (!texrec) return false;
1696 
1697     if (texrec->immutable) return true;
1698     if (!texrec->hasStorage) return true;
1699 
1700     if (target == GL_TEXTURE_CUBE_MAP) {
1701         if (!(texrec->hasCubeNegX &&
1702              texrec->hasCubePosX &&
1703              texrec->hasCubeNegY &&
1704              texrec->hasCubePosY &&
1705              texrec->hasCubeNegZ &&
1706              texrec->hasCubePosZ)) return false;
1707 
1708         size_t currBaseLevel = texrec->dims[0].widths.begin()->first;
1709         size_t currWidth = texrec->dims[0].widths.begin()->second;
1710         size_t currHeight = texrec->dims[0].heights.begin()->second;
1711         for (size_t i = 1; i < 6; ++i) {
1712             size_t nextLevel = texrec->dims[i].widths.begin()->first;
1713             size_t nextWidth = texrec->dims[i].widths.begin()->second;
1714             size_t nextHeight = texrec->dims[i].heights.begin()->second;
1715             if (currBaseLevel != nextLevel) return false;
1716             if (currWidth != nextWidth) return false;
1717             if (currHeight != nextHeight) return false;
1718         }
1719 
1720         return true;
1721     }
1722 
1723     return true;
1724 }
1725 
1726 
getBoundTexture(GLenum target) const1727 GLuint GLClientState::getBoundTexture(GLenum target) const
1728 {
1729     switch (target) {
1730     case GL_TEXTURE_2D:
1731         return m_tex.activeUnit->texture[TEXTURE_2D];
1732     case GL_TEXTURE_EXTERNAL_OES:
1733         return m_tex.activeUnit->texture[TEXTURE_EXTERNAL];
1734     case GL_TEXTURE_CUBE_MAP:
1735         return m_tex.activeUnit->texture[TEXTURE_CUBE_MAP];
1736     case GL_TEXTURE_2D_ARRAY:
1737         return m_tex.activeUnit->texture[TEXTURE_2D_ARRAY];
1738     case GL_TEXTURE_3D:
1739         return m_tex.activeUnit->texture[TEXTURE_3D];
1740     case GL_TEXTURE_2D_MULTISAMPLE:
1741         return m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE];
1742     default:
1743         return 0;
1744     }
1745 }
1746 
getBoundFramebuffer(GLenum target) const1747 GLuint GLClientState::getBoundFramebuffer(GLenum target) const
1748 {
1749     switch (target) {
1750     case GL_FRAMEBUFFER:
1751     case GL_DRAW_FRAMEBUFFER:
1752         return mFboState.boundDrawFramebuffer;
1753     case GL_READ_FRAMEBUFFER:
1754         return mFboState.boundReadFramebuffer;
1755     default:
1756         return 0;
1757     }
1758 }
1759 
checkFramebufferCompleteness(GLenum target)1760 GLenum GLClientState::checkFramebufferCompleteness(GLenum target) {
1761     // Default framebuffer is complete
1762     // TODO: Check the case where the default framebuffer is 0x0
1763     if (0 == boundFramebuffer(target)) {
1764         return GL_FRAMEBUFFER_COMPLETE;
1765     }
1766 
1767     bool hasAttachment = false;
1768     FboProps& props = boundFboProps(target);
1769 
1770     if (!props.completenessDirty) {
1771         return props.cachedCompleteness;
1772     }
1773 
1774     int currentSamples = -1;
1775 
1776     for (int i = 0; i < getMaxColorAttachments(); i++) {
1777         if (!props.colorAttachmenti_hasTex[i] &&
1778             !props.colorAttachmenti_hasRbo[i]) continue;
1779 
1780         GLenum attachmentRes = checkFramebufferAttachmentCompleteness(target, glUtilsColorAttachmentName(i), &currentSamples);
1781         if (attachmentRes != GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) {
1782             hasAttachment = true;
1783         }
1784         if (attachmentRes) {
1785             ALOGD("%s: color attachment %d not complete: 0x%x\n", __func__, i, attachmentRes);
1786             return attachmentRes;
1787         }
1788     }
1789 
1790     bool hasDepth = (props.depthAttachment_hasTexObj || props.depthAttachment_hasRbo || props.depthstencilAttachment_hasTexObj || props.depthstencilAttachment_hasRbo);
1791     bool hasStencil = (props.stencilAttachment_hasTexObj || props.stencilAttachment_hasRbo || props.depthstencilAttachment_hasTexObj || props.depthstencilAttachment_hasRbo);
1792 
1793     if (hasDepth) {
1794         GLenum depthAttachmentRes = checkFramebufferAttachmentCompleteness(target, GL_DEPTH_ATTACHMENT, &currentSamples);
1795         if (depthAttachmentRes != GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) {
1796             hasAttachment = true;
1797         }
1798         if (depthAttachmentRes) {
1799             ALOGD("%s: depth attachment not complete: 0x%x\n", __func__, depthAttachmentRes);
1800             return depthAttachmentRes;
1801         }
1802     }
1803 
1804     if (hasStencil) {
1805         GLenum stencilAttachmentRes = checkFramebufferAttachmentCompleteness(target, GL_STENCIL_ATTACHMENT, &currentSamples);
1806         if (stencilAttachmentRes != GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) {
1807             hasAttachment = true;
1808         }
1809         if (stencilAttachmentRes) {
1810             ALOGD("%s: stencil attachment not complete: 0x%x\n", __func__, stencilAttachmentRes);
1811             return stencilAttachmentRes;
1812         }
1813     }
1814 
1815     if (hasDepth && hasStencil) {
1816         // In gles3, depth/stencil must use the same image.
1817         if (m_glesMajorVersion > 2) {
1818             if ((props.depthAttachment_hasTexObj && props.stencilAttachment_hasRbo) ||
1819                 (props.stencilAttachment_hasTexObj && props.depthAttachment_hasRbo)) {
1820                 ALOGD("%s: GL_FRAMEBUFFER_UNSUPPORTED: using different types of depth/stencil attachment images in GLES 3+\n", __func__);
1821                 return GL_FRAMEBUFFER_UNSUPPORTED;
1822             }
1823             if (props.depthAttachment_hasTexObj) {
1824                 if (props.depthAttachment_texture != props.stencilAttachment_texture) {
1825                     ALOGD("%s: GL_FRAMEBUFFER_UNSUPPORTED: using different texture images for depth and stencil attachments in GLES 3+\n", __func__);
1826                     return GL_FRAMEBUFFER_UNSUPPORTED;
1827                 }
1828             }
1829             if (props.depthAttachment_hasRbo) {
1830                 if (props.depthAttachment_rbo != props.stencilAttachment_rbo) {
1831                     ALOGD("%s: GL_FRAMEBUFFER_UNSUPPORTED: using different renderbuffers for depth and stencil attachments in GLES 3+\n", __func__);
1832                     return GL_FRAMEBUFFER_UNSUPPORTED;
1833                 }
1834             }
1835         }
1836     }
1837 
1838     if (!hasAttachment) {
1839         // Framebuffers may be missing an attachment if they have nonzero
1840         // default width and height
1841         if (props.defaultWidth == 0 || props.defaultHeight == 0) {
1842             return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
1843         }
1844     }
1845 
1846     props.completenessDirty = false;
1847     props.cachedCompleteness = GL_FRAMEBUFFER_COMPLETE;
1848     return GL_FRAMEBUFFER_COMPLETE;
1849 }
1850 
checkFramebufferAttachmentCompleteness(GLenum target,GLenum attachment,int * currentSamples) const1851 GLenum GLClientState::checkFramebufferAttachmentCompleteness(GLenum target, GLenum attachment, int* currentSamples) const {
1852     FboFormatInfo fbo_format_info;
1853     getBoundFramebufferFormat(target, attachment, &fbo_format_info);
1854 
1855     // Check format and renderability
1856     bool renderable = false;
1857     switch (fbo_format_info.type) {
1858         case FBO_ATTACHMENT_RENDERBUFFER:
1859             switch (attachment) {
1860                 case GL_DEPTH_ATTACHMENT:
1861                     renderable = fbo_format_info.rb_external || depthRenderableFormat(fbo_format_info.rb_format);
1862                     break;
1863                 case GL_STENCIL_ATTACHMENT:
1864                     renderable = fbo_format_info.rb_external || stencilRenderableFormat(fbo_format_info.rb_format);
1865                     break;
1866                 default:
1867                     renderable = fbo_format_info.rb_external || colorRenderableFormat(
1868                             fbo_format_info.rb_format,
1869                             GL_UNSIGNED_BYTE,
1870                             m_glesMajorVersion, m_glesMinorVersion,
1871                             m_has_color_buffer_float_extension,
1872                             m_has_color_buffer_half_float_extension);
1873                     if (!renderable) {
1874                         ALOGD("%s: rbo not color renderable. format: 0x%x\n", __func__, fbo_format_info.rb_format); }
1875                     break;
1876             }
1877             break;
1878         case FBO_ATTACHMENT_TEXTURE:
1879             switch (attachment) {
1880                 case GL_DEPTH_ATTACHMENT:
1881                     renderable = fbo_format_info.tex_external || depthRenderableFormat(fbo_format_info.tex_internalformat);
1882                     break;
1883                 case GL_STENCIL_ATTACHMENT:
1884                     renderable = fbo_format_info.tex_external || stencilRenderableFormat(fbo_format_info.tex_internalformat);
1885                     break;
1886                 default:
1887                     renderable = fbo_format_info.tex_external || colorRenderableFormat(
1888                             fbo_format_info.tex_internalformat,
1889                             fbo_format_info.tex_type,
1890                             m_glesMajorVersion, m_glesMinorVersion,
1891                             m_has_color_buffer_float_extension,
1892                             m_has_color_buffer_half_float_extension);
1893                     if (!renderable) {
1894                         ALOGD("%s: tex not color renderable. format: 0x%x type 0x%x maj min %d %d floatext %d hfloatext %d\n", __func__, fbo_format_info.tex_internalformat, fbo_format_info.tex_type, m_glesMajorVersion, m_glesMinorVersion, m_has_color_buffer_float_extension, m_has_color_buffer_half_float_extension);
1895                     }
1896                     break;
1897             }
1898             break;
1899         case FBO_ATTACHMENT_NONE:
1900         default:
1901             return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
1902     }
1903 
1904     if (!renderable) return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1905 
1906     // Check dimensions
1907     GLuint id;
1908     switch (fbo_format_info.type) {
1909     case FBO_ATTACHMENT_RENDERBUFFER:
1910         id = getFboAttachmentRboId(target, attachment);
1911         if (!fbo_format_info.rb_external) {
1912             if (0 == queryRboWidth(id) || 0 == queryRboHeight(id)) {
1913                 ALOGD("%s: rbo has zero dimension\n", __func__);
1914                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1915             }
1916         }
1917         break;
1918     case FBO_ATTACHMENT_TEXTURE:
1919         id = getFboAttachmentTextureId(target, attachment);
1920         if (!fbo_format_info.tex_external) {
1921             if (0 == queryTexWidth(fbo_format_info.tex_level, id) || 0 == queryTexHeight(fbo_format_info.tex_level, id)) {
1922                 ALOGD("%s: texture has zero dimension\n", __func__);
1923                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1924             }
1925             GLsizei depth = queryTexDepth(fbo_format_info.tex_level, id);
1926             if (fbo_format_info.tex_layer >= depth) {
1927                 ALOGD("%s: texture layer/zoffset too high, wanted %d but only have %d layers\n", __func__,
1928                       fbo_format_info.tex_layer, depth);
1929                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1930             }
1931         }
1932         break;
1933     case FBO_ATTACHMENT_NONE:
1934     default:
1935         return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
1936     }
1937 
1938     // Check samples
1939     int currSamplesVal = *currentSamples;
1940     bool firstTime = -1 == currSamplesVal;
1941     int samplesThisAttachment = 0;
1942     switch (fbo_format_info.type) {
1943     case FBO_ATTACHMENT_RENDERBUFFER:
1944         samplesThisAttachment = fbo_format_info.rb_multisamples;
1945         break;
1946     case FBO_ATTACHMENT_TEXTURE:
1947         samplesThisAttachment = fbo_format_info.tex_multisamples;
1948         break;
1949     case FBO_ATTACHMENT_NONE:
1950         break;
1951     default:
1952         return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
1953     }
1954 
1955     if (firstTime) {
1956         *currentSamples = samplesThisAttachment;
1957     } else {
1958         if (samplesThisAttachment != currSamplesVal) {
1959             return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1960         }
1961     }
1962 
1963     return 0;
1964 }
1965 
1966 // BEGIN driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
1967 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
1968 
unreliableInternalFormat(GLenum internalformat)1969 static bool unreliableInternalFormat(GLenum internalformat) {
1970     switch (internalformat) {
1971     case GL_LUMINANCE:
1972         return true;
1973     default:
1974         return false;
1975     }
1976 }
1977 
writeCopyTexImageState(GLenum target,GLint level,GLenum internalformat)1978 void GLClientState::writeCopyTexImageState
1979     (GLenum target, GLint level, GLenum internalformat) {
1980     if (unreliableInternalFormat(internalformat)) {
1981         CubeMapDef entry;
1982         entry.id = getBoundTexture(GL_TEXTURE_2D);
1983         entry.target = target;
1984         entry.level = level;
1985         entry.internalformat = internalformat;
1986         m_cubeMapDefs.insert(entry);
1987     }
1988 }
1989 
identifyPositiveCubeMapComponent(GLenum target)1990 static GLenum identifyPositiveCubeMapComponent(GLenum target) {
1991     switch (target) {
1992     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1993         return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
1994     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1995         return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
1996     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1997         return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
1998     default:
1999         return 0;
2000     }
2001 }
2002 
copyTexImageNeededTarget(GLenum target,GLint level,GLenum internalformat)2003 GLenum GLClientState::copyTexImageNeededTarget
2004     (GLenum target, GLint level, GLenum internalformat) {
2005     if (unreliableInternalFormat(internalformat)) {
2006         GLenum positiveComponent =
2007             identifyPositiveCubeMapComponent(target);
2008         if (positiveComponent) {
2009             CubeMapDef query;
2010             query.id = getBoundTexture(GL_TEXTURE_2D);
2011             query.target = positiveComponent;
2012             query.level = level;
2013             query.internalformat = internalformat;
2014             if (m_cubeMapDefs.find(query) ==
2015                 m_cubeMapDefs.end()) {
2016                 return positiveComponent;
2017             }
2018         }
2019     }
2020     return 0;
2021 }
2022 
copyTexImageLuminanceCubeMapAMDWorkaround(GLenum target,GLint level,GLenum internalformat)2023 GLenum GLClientState::copyTexImageLuminanceCubeMapAMDWorkaround
2024     (GLenum target, GLint level, GLenum internalformat) {
2025     writeCopyTexImageState(target, level, internalformat);
2026     return copyTexImageNeededTarget(target, level, internalformat);
2027 }
2028 
2029 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
2030 // END driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2031 
deleteTextures(GLsizei n,const GLuint * textures)2032 void GLClientState::deleteTextures(GLsizei n, const GLuint* textures)
2033 {
2034     for (const GLuint* texture = textures; texture != textures + n; texture++) {
2035         setFboCompletenessDirtyForTexture(*texture);
2036     }
2037 
2038     // Updating the textures array could be made more efficient when deleting
2039     // several textures:
2040     // - compacting the array could be done in a single pass once the deleted
2041     //   textures are marked, or
2042     // - could swap deleted textures to the end and re-sort.
2043     TextureRec* texrec;
2044     for (const GLuint* texture = textures; texture != textures + n; texture++) {
2045         texrec = getTextureRec(*texture);
2046         if (texrec && texrec->dims) {
2047             delete [] texrec->dims;
2048         }
2049         if (texrec) {
2050             m_tex.textureRecs->erase(*texture);
2051             delete texrec;
2052             for (TextureUnit* unit = m_tex.unit;
2053                  unit != m_tex.unit + MAX_TEXTURE_UNITS;
2054                  unit++)
2055             {
2056                 if (unit->texture[TEXTURE_2D] == *texture) {
2057                     unit->texture[TEXTURE_2D] = 0;
2058                 } else if (unit->texture[TEXTURE_EXTERNAL] == *texture) {
2059                     unit->texture[TEXTURE_EXTERNAL] = 0;
2060                 }
2061             }
2062         }
2063     }
2064 }
2065 
2066 // RBO//////////////////////////////////////////////////////////////////////////
2067 
addFreshRenderbuffer(GLuint name)2068 void GLClientState::addFreshRenderbuffer(GLuint name) {
2069     if (!name) return;
2070 
2071     RenderbufferInfo::ScopedView view(mRboState.rboData);
2072     view.addFresh(name);
2073 }
2074 
addRenderbuffers(GLsizei n,GLuint * renderbuffers)2075 void GLClientState::addRenderbuffers(GLsizei n, GLuint* renderbuffers) {
2076     for (size_t i = 0; i < n; i++) {
2077         addFreshRenderbuffer(renderbuffers[i]);
2078     }
2079 }
2080 
removeRenderbuffers(GLsizei n,const GLuint * renderbuffers)2081 void GLClientState::removeRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
2082     std::vector<GLuint> to_remove;
2083     for (size_t i = 0; i < n; i++) {
2084         if (renderbuffers[i] != 0) { // Never remove the zero rb.
2085             to_remove.push_back(renderbuffers[i]);
2086             setFboCompletenessDirtyForRbo(renderbuffers[i]);
2087         }
2088     }
2089 
2090     bool unbindCurrent = false;
2091     {
2092         RenderbufferInfo::ScopedView view(mRboState.rboData);
2093         for (size_t i = 0; i < to_remove.size(); i++) {
2094             view.unref(to_remove[i]);
2095         }
2096         for (size_t i = 0; i < to_remove.size(); i++) {
2097             if (mRboState.boundRenderbuffer == renderbuffers[i]) {
2098                 unbindCurrent = true;
2099                 break;
2100             }
2101         }
2102     }
2103 
2104     if (unbindCurrent) {
2105         bindRenderbuffer(GL_RENDERBUFFER, 0);
2106     }
2107 }
2108 
usedRenderbufferName(GLuint name) const2109 bool GLClientState::usedRenderbufferName(GLuint name) const {
2110     if (!name) return false;
2111 
2112     RenderbufferInfo::ScopedView view(mRboState.rboData);
2113     return view.get_const(name) != 0;
2114 }
2115 
bindRenderbuffer(GLenum target,GLuint name)2116 void GLClientState::bindRenderbuffer(GLenum target, GLuint name) {
2117 
2118     (void)target; // Must be GL_RENDERBUFFER
2119     RenderbufferInfo::ScopedView view(mRboState.rboData);
2120     if (name != mRboState.boundRenderbuffer) {
2121         view.unref(mRboState.boundRenderbuffer);
2122     }
2123 
2124     mRboState.boundRenderbuffer = name;
2125 
2126     if (!name) return;
2127 
2128     view.bind(name);
2129 }
2130 
boundRenderbuffer() const2131 GLuint GLClientState::boundRenderbuffer() const {
2132     return mRboState.boundRenderbuffer;
2133 }
2134 
setBoundRenderbufferFormat(GLenum format)2135 void GLClientState::setBoundRenderbufferFormat(GLenum format) {
2136     RenderbufferInfo::ScopedView view(mRboState.rboData);
2137     RboProps* props = view.get(mRboState.boundRenderbuffer);
2138     if (!props) return;
2139     props->format = format;
2140 }
2141 
setBoundRenderbufferSamples(GLsizei samples)2142 void GLClientState::setBoundRenderbufferSamples(GLsizei samples) {
2143     RenderbufferInfo::ScopedView view(mRboState.rboData);
2144     RboProps* props = view.get(mRboState.boundRenderbuffer);
2145     if (!props) return;
2146     props->multisamples = samples;
2147 }
2148 
setBoundRenderbufferDimensions(GLsizei width,GLsizei height)2149 void GLClientState::setBoundRenderbufferDimensions(GLsizei width, GLsizei height) {
2150     RenderbufferInfo::ScopedView view(mRboState.rboData);
2151     RboProps* props = view.get(mRboState.boundRenderbuffer);
2152     if (!props) return;
2153     props->width = width;
2154     props->height = height;
2155 }
2156 
setBoundRenderbufferEGLImageBacked()2157 void GLClientState::setBoundRenderbufferEGLImageBacked() {
2158     RenderbufferInfo::ScopedView view(mRboState.rboData);
2159     RboProps* props = view.get(mRboState.boundRenderbuffer);
2160     if (!props) return;
2161     props->boundEGLImage = true;
2162 }
2163 
2164 // FBO//////////////////////////////////////////////////////////////////////////
2165 
2166 // Format querying
2167 
queryRboFormat(GLuint rbo_name) const2168 GLenum GLClientState::queryRboFormat(GLuint rbo_name) const {
2169     RenderbufferInfo::ScopedView view(mRboState.rboData);
2170     const RboProps* props = view.get(rbo_name);
2171     if (!props) return 0;
2172     return props->format;
2173 }
2174 
queryRboSamples(GLuint rbo_name) const2175 GLsizei GLClientState::queryRboSamples(GLuint rbo_name) const {
2176     RenderbufferInfo::ScopedView view(mRboState.rboData);
2177     const RboProps* props = view.get(rbo_name);
2178     if (!props) return 0;
2179     return props->multisamples;
2180 }
2181 
queryRboWidth(GLuint rbo_name) const2182 GLsizei GLClientState::queryRboWidth(GLuint rbo_name) const {
2183     RenderbufferInfo::ScopedView view(mRboState.rboData);
2184     const RboProps* props = view.get(rbo_name);
2185     if (!props) return 0;
2186     return props->width;
2187 }
2188 
queryRboHeight(GLuint rbo_name) const2189 GLsizei GLClientState::queryRboHeight(GLuint rbo_name) const {
2190     RenderbufferInfo::ScopedView view(mRboState.rboData);
2191     const RboProps* props = view.get(rbo_name);
2192     if (!props) return 0;
2193     return props->height;
2194 }
2195 
queryRboEGLImageBacked(GLuint rbo_name) const2196 bool GLClientState::queryRboEGLImageBacked(GLuint rbo_name) const {
2197     RenderbufferInfo::ScopedView view(mRboState.rboData);
2198     const RboProps* props = view.get(rbo_name);
2199     if (!props) return 0;
2200     return props->boundEGLImage;
2201 }
2202 
queryTexInternalFormat(GLuint tex_name) const2203 GLint GLClientState::queryTexInternalFormat(GLuint tex_name) const {
2204     TextureRec* texrec = getTextureRec(tex_name);
2205     if (!texrec) return -1;
2206     return texrec->internalformat;
2207 }
2208 
queryTexWidth(GLsizei level,GLuint tex_name) const2209 GLsizei GLClientState::queryTexWidth(GLsizei level, GLuint tex_name) const {
2210     TextureRec* texrec = getTextureRec(tex_name);
2211     if (!texrec) {
2212         return 0;
2213     }
2214     return texrec->dims->widths[level];
2215 }
2216 
queryTexHeight(GLsizei level,GLuint tex_name) const2217 GLsizei GLClientState::queryTexHeight(GLsizei level, GLuint tex_name) const {
2218     TextureRec* texrec = getTextureRec(tex_name);
2219     if (!texrec) return 0;
2220     return texrec->dims->heights[level];
2221 }
2222 
queryTexDepth(GLsizei level,GLuint tex_name) const2223 GLsizei GLClientState::queryTexDepth(GLsizei level, GLuint tex_name) const {
2224     TextureRec* texrec = getTextureRec(tex_name);
2225     if (!texrec) return 0;
2226     return texrec->dims->depths[level];
2227 }
2228 
queryTexEGLImageBacked(GLuint tex_name) const2229 bool GLClientState::queryTexEGLImageBacked(GLuint tex_name) const {
2230     TextureRec* texrec = getTextureRec(tex_name);
2231     if (!texrec) return false;
2232     return texrec->boundEGLImage;
2233 }
2234 
queryTexFormat(GLuint tex_name) const2235 GLenum GLClientState::queryTexFormat(GLuint tex_name) const {
2236     TextureRec* texrec = getTextureRec(tex_name);
2237     if (!texrec) return -1;
2238     return texrec->format;
2239 }
2240 
queryTexType(GLuint tex_name) const2241 GLenum GLClientState::queryTexType(GLuint tex_name) const {
2242     TextureRec* texrec = getTextureRec(tex_name);
2243     if (!texrec) return -1;
2244     return texrec->type;
2245 }
2246 
queryTexSamples(GLuint tex_name) const2247 GLsizei GLClientState::queryTexSamples(GLuint tex_name) const {
2248     TextureRec* texrec = getTextureRec(tex_name);
2249     if (!texrec) return 0;
2250     return texrec->multisamples;
2251 }
2252 
queryTexLastBoundTarget(GLuint tex_name) const2253 GLenum GLClientState::queryTexLastBoundTarget(GLuint tex_name) const {
2254     TextureRec* texrec = getTextureRec(tex_name);
2255     if (!texrec) return GL_NONE;
2256     return texrec->target;
2257 }
2258 
getBoundFramebufferFormat(GLenum target,GLenum attachment,FboFormatInfo * res_info) const2259 void GLClientState::getBoundFramebufferFormat(
2260         GLenum target,
2261         GLenum attachment, FboFormatInfo* res_info) const {
2262     const FboProps& props = boundFboProps_const(target);
2263 
2264     res_info->type = FBO_ATTACHMENT_NONE;
2265     res_info->rb_format = GL_NONE;
2266     res_info->rb_multisamples = 0;
2267     res_info->rb_external = false;
2268     res_info->tex_internalformat = -1;
2269     res_info->tex_format = GL_NONE;
2270     res_info->tex_type = GL_NONE;
2271     res_info->tex_multisamples = 0;
2272     res_info->tex_external = false;
2273 
2274     int colorAttachmentIndex =
2275         glUtilsColorAttachmentIndex(attachment);
2276 
2277     if (colorAttachmentIndex != -1) {
2278         if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
2279             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
2280             res_info->rb_format =
2281                 queryRboFormat(
2282                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
2283             res_info->rb_multisamples =
2284                 queryRboSamples(
2285                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
2286             res_info->rb_external =
2287                 queryRboEGLImageBacked(
2288                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
2289         } else if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
2290             res_info->type = FBO_ATTACHMENT_TEXTURE;
2291             res_info->tex_external = queryTexEGLImageBacked(
2292                     props.colorAttachmenti_textures[colorAttachmentIndex]);
2293             res_info->tex_internalformat =
2294                 queryTexInternalFormat(
2295                         props.colorAttachmenti_textures[colorAttachmentIndex]);
2296             res_info->tex_format =
2297                 queryTexFormat(
2298                         props.colorAttachmenti_textures[colorAttachmentIndex]);
2299             res_info->tex_type =
2300                 queryTexType(props.colorAttachmenti_textures[colorAttachmentIndex]);
2301             res_info->tex_multisamples =
2302                 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
2303             res_info->tex_level = props.colorAttachmenti_texture_levels[colorAttachmentIndex];
2304             res_info->tex_layer = props.colorAttachmenti_texture_layers[colorAttachmentIndex];
2305         } else {
2306             res_info->type = FBO_ATTACHMENT_NONE;
2307         }
2308     }
2309 
2310     switch (attachment) {
2311     case GL_DEPTH_ATTACHMENT:
2312         if (props.depthAttachment_hasRbo) {
2313             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
2314             res_info->rb_format = queryRboFormat(props.depthAttachment_rbo);
2315             res_info->rb_multisamples =
2316                 queryRboSamples(
2317                         props.depthAttachment_rbo);
2318             res_info->rb_external =
2319                 queryRboEGLImageBacked(
2320                         props.depthAttachment_rbo);
2321         } else if (props.depthAttachment_hasTexObj) {
2322             res_info->type = FBO_ATTACHMENT_TEXTURE;
2323             res_info->tex_external = queryTexEGLImageBacked(props.depthAttachment_texture);
2324             res_info->tex_internalformat = queryTexInternalFormat(props.depthAttachment_texture);
2325             res_info->tex_format = queryTexFormat(props.depthAttachment_texture);
2326             res_info->tex_type = queryTexType(props.depthAttachment_texture);
2327             res_info->tex_multisamples =
2328                 queryTexSamples(props.depthAttachment_texture);
2329             res_info->tex_level = props.depthAttachment_texture_level;
2330             res_info->tex_layer = props.depthAttachment_texture_layer;
2331         } else {
2332             res_info->type = FBO_ATTACHMENT_NONE;
2333         }
2334         break;
2335     case GL_STENCIL_ATTACHMENT:
2336         if (props.stencilAttachment_hasRbo) {
2337             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
2338             res_info->rb_format = queryRboFormat(props.stencilAttachment_rbo);
2339             res_info->rb_multisamples =
2340                 queryRboSamples(
2341                         props.stencilAttachment_rbo);
2342             res_info->rb_external =
2343                 queryRboEGLImageBacked(
2344                         props.stencilAttachment_rbo);
2345         } else if (props.stencilAttachment_hasTexObj) {
2346             res_info->type = FBO_ATTACHMENT_TEXTURE;
2347             res_info->tex_external = queryTexEGLImageBacked(props.stencilAttachment_texture);
2348             res_info->tex_internalformat = queryTexInternalFormat(props.stencilAttachment_texture);
2349             res_info->tex_format = queryTexFormat(props.stencilAttachment_texture);
2350             res_info->tex_type = queryTexType(props.stencilAttachment_texture);
2351             res_info->tex_multisamples =
2352                 queryTexSamples(props.stencilAttachment_texture);
2353             res_info->tex_level = props.depthAttachment_texture_level;
2354             res_info->tex_layer = props.depthAttachment_texture_layer;
2355         } else {
2356             res_info->type = FBO_ATTACHMENT_NONE;
2357         }
2358         break;
2359     case GL_DEPTH_STENCIL_ATTACHMENT:
2360         if (props.depthstencilAttachment_hasRbo) {
2361             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
2362             res_info->rb_format = queryRboFormat(props.depthstencilAttachment_rbo);
2363             res_info->rb_multisamples =
2364                 queryRboSamples(
2365                         props.depthstencilAttachment_rbo);
2366             res_info->rb_external =
2367                 queryRboEGLImageBacked(
2368                         props.depthstencilAttachment_rbo);
2369         } else if (props.depthstencilAttachment_hasTexObj) {
2370             res_info->type = FBO_ATTACHMENT_TEXTURE;
2371             res_info->tex_external = queryTexEGLImageBacked(props.depthstencilAttachment_texture);
2372             res_info->tex_internalformat = queryTexInternalFormat(props.depthstencilAttachment_texture);
2373             res_info->tex_format = queryTexFormat(props.depthstencilAttachment_texture);
2374             res_info->tex_type = queryTexType(props.depthstencilAttachment_texture);
2375             res_info->tex_multisamples =
2376                 queryTexSamples(props.depthstencilAttachment_texture);
2377             res_info->tex_level = props.depthAttachment_texture_level;
2378             res_info->tex_layer = props.depthAttachment_texture_layer;
2379         } else {
2380             res_info->type = FBO_ATTACHMENT_NONE;
2381         }
2382         break;
2383     }
2384 }
2385 
getBoundFramebufferAttachmentType(GLenum target,GLenum attachment) const2386 FboAttachmentType GLClientState::getBoundFramebufferAttachmentType(GLenum target, GLenum attachment) const {
2387     FboFormatInfo info;
2388     getBoundFramebufferFormat(target, attachment, &info);
2389     return info.type;
2390 }
2391 
getMaxColorAttachments() const2392 int GLClientState::getMaxColorAttachments() const {
2393     return m_hostDriverCaps.max_color_attachments;
2394 }
2395 
getMaxDrawBuffers() const2396 int GLClientState::getMaxDrawBuffers() const {
2397     return m_hostDriverCaps.max_draw_buffers;
2398 }
2399 
2400 #define UNIFORM_VALIDATION_ERR_COND(cond, code) if (cond) { *err = code; return; }
2401 
2402 #define UNIFORM_VALIDATION_INFO_VAR_NAME info
2403 
2404 #define UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_FLOATS \
2405     (!(UNIFORM_VALIDATION_INFO_VAR_NAME->isBool) && (UNIFORM_VALIDATION_INFO_VAR_NAME->isInt || UNIFORM_VALIDATION_INFO_VAR_NAME->isSampler))
2406 
2407 #define UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_INTS \
2408     (!(UNIFORM_VALIDATION_INFO_VAR_NAME->isBool) && (!UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_FLOATS || UNIFORM_VALIDATION_INFO_VAR_NAME->isUnsigned))
2409 
2410 #define UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_UNSIGNED_INTS \
2411     (!(UNIFORM_VALIDATION_INFO_VAR_NAME->isBool) && (!UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_FLOATS || !(UNIFORM_VALIDATION_INFO_VAR_NAME->isUnsigned)))
2412 
2413 #define UNIFORM_VALIDATION_INLINING
2414 
validateUniform(bool isFloat,bool isUnsigned,GLint columns,GLint rows,GLint location,GLsizei count,GLenum * err)2415 void GLClientState::validateUniform(bool isFloat, bool isUnsigned, GLint columns, GLint rows, GLint location, GLsizei count, GLenum* err) {
2416     UNIFORM_VALIDATION_ERR_COND(!m_currentProgram && !m_currentShaderProgram, GL_INVALID_OPERATION);
2417     if (-1 == location) return; \
2418     auto info = currentUniformValidationInfo.get_const(location); \
2419     UNIFORM_VALIDATION_ERR_COND(!info || !info->valid, GL_INVALID_OPERATION); \
2420     UNIFORM_VALIDATION_ERR_COND(columns != info->columns || rows != info->rows, GL_INVALID_OPERATION); \
2421     UNIFORM_VALIDATION_ERR_COND(count > 1 && !info->isArray, GL_INVALID_OPERATION);
2422     if (isFloat) {
2423         UNIFORM_VALIDATION_ERR_COND(UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_FLOATS, GL_INVALID_OPERATION);
2424     } else {
2425         if (isUnsigned) {
2426             UNIFORM_VALIDATION_ERR_COND(UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_UNSIGNED_INTS, GL_INVALID_OPERATION);
2427         } else {
2428             UNIFORM_VALIDATION_ERR_COND(UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_INTS, GL_INVALID_OPERATION);
2429         }
2430     }
2431 }
2432 
isAttribIndexUsedByProgram(int index)2433 bool GLClientState::isAttribIndexUsedByProgram(int index) {
2434     auto info = currentAttribValidationInfo.get_const(index);
2435     if (!info) return false;
2436     if (!info->validInProgram) return false;
2437     return true;
2438 }
2439 
addFreshFramebuffer(GLuint name)2440 void GLClientState::addFreshFramebuffer(GLuint name) {
2441     FboProps props;
2442     props.name = name;
2443     props.previouslyBound = false;
2444 
2445     props.completenessDirty = true;
2446 
2447     props.colorAttachmenti_textures.resize(m_hostDriverCaps.max_color_attachments, 0);
2448     props.colorAttachmenti_texture_levels.resize(m_hostDriverCaps.max_color_attachments, 0);
2449     props.colorAttachmenti_texture_layers.resize(m_hostDriverCaps.max_color_attachments, 0);
2450 
2451     props.depthAttachment_texture_level = 0;
2452     props.depthAttachment_texture_layer = 0;
2453     props.stencilAttachment_texture_level = 0;
2454     props.stencilAttachment_texture_layer = 0;
2455 
2456     props.depthAttachment_texture = 0;
2457     props.stencilAttachment_texture = 0;
2458     props.depthstencilAttachment_texture = 0;
2459 
2460     props.colorAttachmenti_hasTex.resize(m_hostDriverCaps.max_color_attachments, false);
2461     props.depthAttachment_hasTexObj = false;
2462     props.stencilAttachment_hasTexObj = false;
2463     props.depthstencilAttachment_hasTexObj = false;
2464 
2465     props.colorAttachmenti_rbos.resize(m_hostDriverCaps.max_color_attachments, 0);
2466     props.depthAttachment_rbo = 0;
2467     props.stencilAttachment_rbo = 0;
2468     props.depthstencilAttachment_rbo = 0;
2469 
2470     props.colorAttachmenti_hasRbo.resize(m_hostDriverCaps.max_color_attachments, false);
2471     props.depthAttachment_hasRbo = false;
2472     props.stencilAttachment_hasRbo = false;
2473     props.depthstencilAttachment_hasRbo = false;
2474 
2475     props.defaultWidth = 0;
2476     props.defaultHeight = 0;
2477 
2478     mFboState.fboData[name] = props;
2479 }
2480 
addFramebuffers(GLsizei n,GLuint * framebuffers)2481 void GLClientState::addFramebuffers(GLsizei n, GLuint* framebuffers) {
2482     for (size_t i = 0; i < n; i++) {
2483         addFreshFramebuffer(framebuffers[i]);
2484     }
2485 }
2486 
removeFramebuffers(GLsizei n,const GLuint * framebuffers)2487 void GLClientState::removeFramebuffers(GLsizei n, const GLuint* framebuffers) {
2488     for (size_t i = 0; i < n; i++) {
2489         if (framebuffers[i] != 0) { // Never remove the zero fb.
2490             if (framebuffers[i] == mFboState.boundDrawFramebuffer) {
2491                 bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
2492             }
2493             if (framebuffers[i] == mFboState.boundReadFramebuffer) {
2494                 bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
2495             }
2496             mFboState.fboData.erase(framebuffers[i]);
2497         }
2498     }
2499 }
2500 
usedFramebufferName(GLuint name) const2501 bool GLClientState::usedFramebufferName(GLuint name) const {
2502     return mFboState.fboData.find(name) != mFboState.fboData.end();
2503 }
2504 
boundFboProps(GLenum target)2505 FboProps& GLClientState::boundFboProps(GLenum target) {
2506     switch (target) {
2507     case GL_DRAW_FRAMEBUFFER:
2508         return mFboState.fboData[mFboState.boundDrawFramebuffer];
2509     case GL_READ_FRAMEBUFFER:
2510         return mFboState.fboData[mFboState.boundReadFramebuffer];
2511     case GL_FRAMEBUFFER:
2512         return mFboState.fboData[mFboState.boundDrawFramebuffer];
2513     }
2514     return mFboState.fboData[mFboState.boundDrawFramebuffer];
2515 }
2516 
boundFboProps_const(GLenum target) const2517 const FboProps& GLClientState::boundFboProps_const(GLenum target) const {
2518     switch (target) {
2519     case GL_DRAW_FRAMEBUFFER:
2520         return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
2521     case GL_READ_FRAMEBUFFER:
2522         return mFboState.fboData.find(mFboState.boundReadFramebuffer)->second;
2523     case GL_FRAMEBUFFER:
2524         return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
2525     }
2526     return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
2527 }
2528 
bindFramebuffer(GLenum target,GLuint name)2529 void GLClientState::bindFramebuffer(GLenum target, GLuint name) {
2530     // If unused, add it.
2531     if (!usedFramebufferName(name)) {
2532         addFreshFramebuffer(name);
2533     }
2534     switch (target) {
2535         case GL_DRAW_FRAMEBUFFER:
2536             mFboState.boundDrawFramebuffer = name;
2537             break;
2538         case GL_READ_FRAMEBUFFER:
2539             mFboState.boundReadFramebuffer = name;
2540             break;
2541         default: // case GL_FRAMEBUFFER:
2542             mFboState.boundDrawFramebuffer = name;
2543             mFboState.boundReadFramebuffer = name;
2544             break;
2545     }
2546     boundFboProps(target).previouslyBound = true;
2547 }
2548 
setCheckFramebufferStatus(GLenum target,GLenum status)2549 void GLClientState::setCheckFramebufferStatus(GLenum target, GLenum status) {
2550     switch (target) {
2551         case GL_DRAW_FRAMEBUFFER:
2552             mFboState.drawFboCheckStatus = status;
2553             break;
2554         case GL_READ_FRAMEBUFFER:
2555             mFboState.readFboCheckStatus = status;
2556             break;
2557         case GL_FRAMEBUFFER:
2558             mFboState.drawFboCheckStatus = status;
2559             break;
2560     }
2561 }
2562 
setFramebufferParameter(GLenum target,GLenum pname,GLint param)2563 void GLClientState::setFramebufferParameter(GLenum target, GLenum pname, GLint param) {
2564     switch (pname) {
2565         case GL_FRAMEBUFFER_DEFAULT_WIDTH:
2566             boundFboProps(target).defaultWidth = param;
2567             boundFboProps(target).completenessDirty = true;
2568             break;
2569         case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
2570             boundFboProps(target).defaultHeight = param;
2571             boundFboProps(target).completenessDirty = true;
2572             break;
2573     }
2574 }
2575 
getCheckFramebufferStatus(GLenum target) const2576 GLenum GLClientState::getCheckFramebufferStatus(GLenum target) const {
2577     switch (target) {
2578     case GL_DRAW_FRAMEBUFFER:
2579         return mFboState.drawFboCheckStatus;
2580     case GL_READ_FRAMEBUFFER:
2581         return mFboState.readFboCheckStatus;
2582     case GL_FRAMEBUFFER:
2583         return mFboState.drawFboCheckStatus;
2584     }
2585     return mFboState.drawFboCheckStatus;
2586 }
2587 
boundFramebuffer(GLenum target) const2588 GLuint GLClientState::boundFramebuffer(GLenum target) const {
2589     return boundFboProps_const(target).name;
2590 }
2591 
2592 // Texture objects for FBOs/////////////////////////////////////////////////////
2593 
attachTextureObject(GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer)2594 void GLClientState::attachTextureObject(
2595         GLenum target,
2596         GLenum attachment, GLuint texture, GLint level, GLint layer) {
2597 
2598     bool attach = texture != 0;
2599 
2600     int colorAttachmentIndex =
2601         glUtilsColorAttachmentIndex(attachment);
2602 
2603     boundFboProps(target).completenessDirty = true;
2604 
2605     if (colorAttachmentIndex != -1) {
2606         boundFboProps(target).colorAttachmenti_textures[colorAttachmentIndex] = texture;
2607         boundFboProps(target).colorAttachmenti_texture_levels[colorAttachmentIndex] = level;
2608         boundFboProps(target).colorAttachmenti_texture_layers[colorAttachmentIndex] = layer;
2609         boundFboProps(target).colorAttachmenti_hasTex[colorAttachmentIndex] = attach;
2610     }
2611 
2612     switch (attachment) {
2613     case GL_DEPTH_ATTACHMENT:
2614         boundFboProps(target).depthAttachment_texture = texture;
2615         boundFboProps(target).depthAttachment_texture_level = level;
2616         boundFboProps(target).depthAttachment_texture_layer = layer;
2617         boundFboProps(target).depthAttachment_hasTexObj = attach;
2618         break;
2619     case GL_STENCIL_ATTACHMENT:
2620         boundFboProps(target).stencilAttachment_texture = texture;
2621         boundFboProps(target).stencilAttachment_texture_level = level;
2622         boundFboProps(target).stencilAttachment_texture_layer = layer;
2623         boundFboProps(target).stencilAttachment_hasTexObj = attach;
2624         break;
2625     case GL_DEPTH_STENCIL_ATTACHMENT:
2626         boundFboProps(target).depthstencilAttachment_texture = texture;
2627         boundFboProps(target).depthstencilAttachment_hasTexObj = attach;
2628         boundFboProps(target).stencilAttachment_texture = texture;
2629         boundFboProps(target).stencilAttachment_hasTexObj = attach;
2630         boundFboProps(target).depthAttachment_texture = texture;
2631         boundFboProps(target).depthAttachment_hasTexObj = attach;
2632         boundFboProps(target).depthAttachment_texture_level = level;
2633         boundFboProps(target).depthAttachment_texture_layer = layer;
2634         boundFboProps(target).stencilAttachment_texture_level = level;
2635         boundFboProps(target).stencilAttachment_texture_layer = layer;
2636         break;
2637     }
2638 }
2639 
getFboAttachmentTextureId(GLenum target,GLenum attachment) const2640 GLuint GLClientState::getFboAttachmentTextureId(GLenum target, GLenum attachment) const {
2641     GLuint res = 0; // conservative
2642 
2643     int colorAttachmentIndex =
2644         glUtilsColorAttachmentIndex(attachment);
2645 
2646     if (colorAttachmentIndex != -1) {
2647         res = boundFboProps_const(target).colorAttachmenti_textures[colorAttachmentIndex];
2648     }
2649 
2650     switch (attachment) {
2651     case GL_DEPTH_ATTACHMENT:
2652         res = boundFboProps_const(target).depthAttachment_texture;
2653         break;
2654     case GL_STENCIL_ATTACHMENT:
2655         res = boundFboProps_const(target).stencilAttachment_texture;
2656         break;
2657     case GL_DEPTH_STENCIL_ATTACHMENT:
2658         res = boundFboProps_const(target).depthstencilAttachment_texture;
2659         break;
2660     }
2661     return res;
2662 }
2663 
2664 // RBOs for FBOs////////////////////////////////////////////////////////////////
2665 
detachRbo(GLuint renderbuffer)2666 void GLClientState::detachRbo(GLuint renderbuffer) {
2667     for (int i = 0; i < m_hostDriverCaps.max_color_attachments; i++) {
2668         detachRboFromFbo(GL_DRAW_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
2669         detachRboFromFbo(GL_READ_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
2670     }
2671 
2672     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
2673     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
2674 
2675     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
2676     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
2677 
2678     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
2679     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
2680 }
2681 
detachRboFromFbo(GLenum target,GLenum attachment,GLuint renderbuffer)2682 void GLClientState::detachRboFromFbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
2683     int colorAttachmentIndex =
2684         glUtilsColorAttachmentIndex(attachment);
2685 
2686     boundFboProps(target).completenessDirty = true;
2687 
2688     if (colorAttachmentIndex != -1) {
2689         if (boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] &&
2690             boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] == renderbuffer) {
2691             boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = 0;
2692             boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = false;
2693         }
2694     }
2695 
2696     switch (attachment) {
2697     case GL_DEPTH_ATTACHMENT:
2698         if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
2699             boundFboProps(target).depthAttachment_hasRbo) {
2700             boundFboProps(target).depthAttachment_rbo = 0;
2701             boundFboProps(target).depthAttachment_hasRbo = false;
2702         }
2703         break;
2704     case GL_STENCIL_ATTACHMENT:
2705         if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
2706             boundFboProps(target).stencilAttachment_hasRbo) {
2707             boundFboProps(target).stencilAttachment_rbo = 0;
2708             boundFboProps(target).stencilAttachment_hasRbo = false;
2709         }
2710         break;
2711     case GL_DEPTH_STENCIL_ATTACHMENT:
2712         if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
2713             boundFboProps(target).depthAttachment_hasRbo) {
2714             boundFboProps(target).depthAttachment_rbo = 0;
2715             boundFboProps(target).depthAttachment_hasRbo = false;
2716         }
2717         if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
2718             boundFboProps(target).stencilAttachment_hasRbo) {
2719             boundFboProps(target).stencilAttachment_rbo = 0;
2720             boundFboProps(target).stencilAttachment_hasRbo = false;
2721         }
2722         if (boundFboProps(target).depthstencilAttachment_rbo == renderbuffer &&
2723             boundFboProps(target).depthstencilAttachment_hasRbo) {
2724             boundFboProps(target).depthstencilAttachment_rbo = 0;
2725             boundFboProps(target).depthstencilAttachment_hasRbo = false;
2726         }
2727         break;
2728     }
2729 }
2730 
attachRbo(GLenum target,GLenum attachment,GLuint renderbuffer)2731 void GLClientState::attachRbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
2732 
2733     bool attach = 0 != renderbuffer;
2734 
2735     int colorAttachmentIndex =
2736         glUtilsColorAttachmentIndex(attachment);
2737 
2738     boundFboProps(target).completenessDirty = true;
2739 
2740     if (colorAttachmentIndex != -1) {
2741         boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = renderbuffer;
2742         boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = attach;
2743     }
2744 
2745     switch (attachment) {
2746     case GL_DEPTH_ATTACHMENT:
2747         boundFboProps(target).depthAttachment_rbo = renderbuffer;
2748         boundFboProps(target).depthAttachment_hasRbo = attach;
2749         break;
2750     case GL_STENCIL_ATTACHMENT:
2751         boundFboProps(target).stencilAttachment_rbo = renderbuffer;
2752         boundFboProps(target).stencilAttachment_hasRbo = attach;
2753         break;
2754     case GL_DEPTH_STENCIL_ATTACHMENT:
2755         boundFboProps(target).depthAttachment_rbo = renderbuffer;
2756         boundFboProps(target).depthAttachment_hasRbo = attach;
2757         boundFboProps(target).stencilAttachment_rbo = renderbuffer;
2758         boundFboProps(target).stencilAttachment_hasRbo = attach;
2759         boundFboProps(target).depthstencilAttachment_rbo = renderbuffer;
2760         boundFboProps(target).depthstencilAttachment_hasRbo = attach;
2761         break;
2762     }
2763 }
2764 
getFboAttachmentRboId(GLenum target,GLenum attachment) const2765 GLuint GLClientState::getFboAttachmentRboId(GLenum target, GLenum attachment) const {
2766     GLuint res = 0; // conservative
2767 
2768     int colorAttachmentIndex =
2769         glUtilsColorAttachmentIndex(attachment);
2770 
2771     if (colorAttachmentIndex != -1) {
2772         res = boundFboProps_const(target).colorAttachmenti_rbos[colorAttachmentIndex];
2773     }
2774 
2775     switch (attachment) {
2776     case GL_DEPTH_ATTACHMENT:
2777         res = boundFboProps_const(target).depthAttachment_rbo;
2778         break;
2779     case GL_STENCIL_ATTACHMENT:
2780         res = boundFboProps_const(target).stencilAttachment_rbo;
2781         break;
2782     case GL_DEPTH_STENCIL_ATTACHMENT:
2783         res = boundFboProps_const(target).depthstencilAttachment_rbo;
2784         break;
2785     }
2786     return res;
2787 }
2788 
setFboCompletenessDirtyForTexture(GLuint texture)2789 void GLClientState::setFboCompletenessDirtyForTexture(GLuint texture) {
2790     std::map<GLuint, FboProps>::iterator it = mFboState.fboData.begin();
2791     while (it != mFboState.fboData.end()) {
2792         FboProps& props = it->second;
2793         for (int i = 0; i < m_hostDriverCaps.max_color_attachments; ++i) {
2794             if (props.colorAttachmenti_hasTex[i]) {
2795                 if (texture == props.colorAttachmenti_textures[i]) {
2796                     props.completenessDirty = true;
2797                     return;
2798                 }
2799             }
2800         }
2801 
2802         if (props.depthAttachment_hasTexObj) {
2803             if (texture == props.depthAttachment_texture) {
2804                     props.completenessDirty = true;
2805                     return;
2806             }
2807         }
2808 
2809         if (props.stencilAttachment_hasTexObj) {
2810             if (texture == props.stencilAttachment_texture) {
2811                 props.completenessDirty = true;
2812                 return;
2813             }
2814         }
2815 
2816         if (props.depthstencilAttachment_hasTexObj) {
2817             if (texture == props.depthstencilAttachment_texture) {
2818                 props.completenessDirty = true;
2819                 return;
2820             }
2821         }
2822         ++it;
2823     }
2824 }
2825 
setFboCompletenessDirtyForRbo(GLuint rbo)2826 void GLClientState::setFboCompletenessDirtyForRbo(GLuint rbo) {
2827     std::map<GLuint, FboProps>::iterator it = mFboState.fboData.begin();
2828     while (it != mFboState.fboData.end()) {
2829         FboProps& props = it->second;
2830         for (int i = 0; i < m_hostDriverCaps.max_color_attachments; ++i) {
2831             if (props.colorAttachmenti_hasTex[i]) {
2832                 if (rbo == props.colorAttachmenti_rbos[i]) {
2833                     props.completenessDirty = true;
2834                     return;
2835                 }
2836             }
2837         }
2838 
2839         if (props.depthAttachment_hasTexObj) {
2840             if (rbo == props.depthAttachment_rbo) {
2841                     props.completenessDirty = true;
2842                     return;
2843             }
2844         }
2845 
2846         if (props.stencilAttachment_hasTexObj) {
2847             if (rbo == props.stencilAttachment_rbo) {
2848                 props.completenessDirty = true;
2849                 return;
2850             }
2851         }
2852 
2853         if (props.depthstencilAttachment_hasRbo) {
2854             if (rbo == props.depthstencilAttachment_rbo) {
2855                 props.completenessDirty = true;
2856                 return;
2857             }
2858         }
2859         ++it;
2860     }
2861 }
2862 
attachmentHasObject(GLenum target,GLenum attachment) const2863 bool GLClientState::attachmentHasObject(GLenum target, GLenum attachment) const {
2864     bool res = true; // liberal
2865 
2866     int colorAttachmentIndex =
2867         glUtilsColorAttachmentIndex(attachment);
2868 
2869     if (colorAttachmentIndex != -1) {
2870         res = boundFboProps_const(target).colorAttachmenti_hasTex[colorAttachmentIndex] ||
2871               boundFboProps_const(target).colorAttachmenti_hasRbo[colorAttachmentIndex];
2872     }
2873 
2874     switch (attachment) {
2875     case GL_DEPTH_ATTACHMENT:
2876         res = (boundFboProps_const(target).depthAttachment_hasTexObj) ||
2877               (boundFboProps_const(target).depthAttachment_hasRbo);
2878         break;
2879     case GL_STENCIL_ATTACHMENT:
2880         res = (boundFboProps_const(target).stencilAttachment_hasTexObj) ||
2881               (boundFboProps_const(target).stencilAttachment_hasRbo);
2882         break;
2883     case GL_DEPTH_STENCIL_ATTACHMENT:
2884         res = (boundFboProps_const(target).depthstencilAttachment_hasTexObj) ||
2885               (boundFboProps_const(target).depthstencilAttachment_hasRbo);
2886         break;
2887     }
2888     return res;
2889 }
2890 
objectOfAttachment(GLenum target,GLenum attachment) const2891 GLuint GLClientState::objectOfAttachment(GLenum target, GLenum attachment) const {
2892     const FboProps& props = boundFboProps_const(target);
2893 
2894     int colorAttachmentIndex =
2895         glUtilsColorAttachmentIndex(attachment);
2896 
2897     if (colorAttachmentIndex != -1) {
2898         if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
2899             return props.colorAttachmenti_textures[colorAttachmentIndex];
2900         } else if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
2901             return props.colorAttachmenti_rbos[colorAttachmentIndex];
2902         } else {
2903             return 0;
2904         }
2905     }
2906 
2907     switch (attachment) {
2908     case GL_DEPTH_ATTACHMENT:
2909         if (props.depthAttachment_hasTexObj) {
2910             return props.depthAttachment_texture;
2911         } else if (props.depthAttachment_hasRbo) {
2912             return props.depthAttachment_rbo;
2913         } else {
2914             return 0;
2915         }
2916         break;
2917     case GL_STENCIL_ATTACHMENT:
2918         if (props.stencilAttachment_hasTexObj) {
2919             return props.stencilAttachment_texture;
2920         } else if (props.stencilAttachment_hasRbo) {
2921             return props.stencilAttachment_rbo;
2922         } else {
2923             return 0;
2924         }
2925     case GL_DEPTH_STENCIL_ATTACHMENT:
2926         if (props.depthstencilAttachment_hasTexObj) {
2927             return props.depthstencilAttachment_texture;
2928         } else if (props.depthstencilAttachment_hasRbo) {
2929             return props.depthstencilAttachment_rbo;
2930         } else {
2931             return 0;
2932         }
2933         break;
2934     }
2935     return 0;
2936 }
2937 
setTransformFeedbackActive(bool active)2938 void GLClientState::setTransformFeedbackActive(bool active) {
2939     m_transformFeedbackActive = active;
2940 }
2941 
setTransformFeedbackUnpaused(bool unpaused)2942 void GLClientState::setTransformFeedbackUnpaused(bool unpaused) {
2943     m_transformFeedbackUnpaused = unpaused;
2944 }
2945 
setTransformFeedbackVaryingsCountForLinking(uint32_t count)2946 void GLClientState::setTransformFeedbackVaryingsCountForLinking(uint32_t count) {
2947     m_transformFeedbackVaryingsCountForLinking = count;
2948 }
2949 
getTransformFeedbackActive() const2950 bool GLClientState::getTransformFeedbackActive() const {
2951     return m_transformFeedbackActive;
2952 }
2953 
getTransformFeedbackUnpaused() const2954 bool GLClientState::getTransformFeedbackUnpaused() const {
2955     return m_transformFeedbackUnpaused;
2956 }
2957 
getTransformFeedbackActiveUnpaused() const2958 bool GLClientState::getTransformFeedbackActiveUnpaused() const {
2959     return m_transformFeedbackActive && m_transformFeedbackUnpaused;
2960 }
2961 
getTransformFeedbackVaryingsCountForLinking() const2962 uint32_t GLClientState::getTransformFeedbackVaryingsCountForLinking() const {
2963     return m_transformFeedbackVaryingsCountForLinking;
2964 }
2965 
stencilFuncSeparate(GLenum face,GLenum func,GLint ref,GLuint mask)2966 void GLClientState::stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) {
2967     if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
2968         state_GL_STENCIL_FUNC = func;
2969         state_GL_STENCIL_REF = ref;
2970         state_GL_STENCIL_VALUE_MASK = mask;
2971     }
2972 
2973     if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
2974         state_GL_STENCIL_BACK_FUNC = func;
2975         state_GL_STENCIL_BACK_REF = ref;
2976         state_GL_STENCIL_BACK_VALUE_MASK = mask;
2977     }
2978 }
2979 
stencilMaskSeparate(GLenum face,GLuint mask)2980 void GLClientState::stencilMaskSeparate(GLenum face, GLuint mask) {
2981     if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
2982         state_GL_STENCIL_WRITEMASK = mask;
2983     }
2984 
2985     if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
2986         state_GL_STENCIL_BACK_WRITEMASK = mask;
2987     }
2988 }
2989 
stencilOpSeparate(GLenum face,GLenum fail,GLenum zfail,GLenum zpass)2990 void GLClientState::stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
2991     if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
2992         state_GL_STENCIL_FAIL = fail;
2993         state_GL_STENCIL_PASS_DEPTH_FAIL = zfail;
2994         state_GL_STENCIL_PASS_DEPTH_PASS = zpass;
2995     }
2996 
2997     if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
2998         state_GL_STENCIL_BACK_FAIL = fail;
2999         state_GL_STENCIL_BACK_PASS_DEPTH_FAIL = zfail;
3000         state_GL_STENCIL_BACK_PASS_DEPTH_PASS = zpass;
3001     }
3002 }
3003 
setTextureData(SharedTextureDataMap * sharedTexData)3004 void GLClientState::setTextureData(SharedTextureDataMap* sharedTexData) {
3005     m_tex.textureRecs = sharedTexData;
3006 }
3007 
setRenderbufferInfo(RenderbufferInfo * rbInfo)3008 void GLClientState::setRenderbufferInfo(RenderbufferInfo* rbInfo) {
3009     mRboState.rboData = rbInfo;
3010 }
3011 
setSamplerInfo(SamplerInfo * samplerInfo)3012 void GLClientState::setSamplerInfo(SamplerInfo* samplerInfo) {
3013     mSamplerInfo = samplerInfo;
3014 }
3015 
compressedTexImageSizeCompatible(GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLsizei imageSize)3016 bool GLClientState::compressedTexImageSizeCompatible(GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize) {
3017     bool error = false;
3018     GLsizei compressedSize = GLESTextureUtils::getCompressedImageSize(internalformat, width, height, depth, &error);
3019     if (error) return false;
3020     return imageSize == compressedSize;
3021 }
3022 
fromMakeCurrent()3023 void GLClientState::fromMakeCurrent() {
3024     if (mFboState.fboData.find(0) == mFboState.fboData.end()) {
3025         addFreshFramebuffer(0);
3026     }
3027 
3028     if (!samplerExists(0)) {
3029         GLuint id = 0;
3030         setExistence(ObjectType::Sampler, true, 1, &id);
3031     }
3032 
3033     FboProps& default_fb_props = mFboState.fboData[0];
3034     default_fb_props.colorAttachmenti_hasRbo[0] = true;
3035     default_fb_props.depthAttachment_hasRbo = true;
3036     default_fb_props.stencilAttachment_hasRbo = true;
3037     default_fb_props.depthstencilAttachment_hasRbo = true;
3038 }
3039 
initFromCaps(const HostDriverCaps & caps)3040 void GLClientState::initFromCaps(
3041     const HostDriverCaps& caps) {
3042     m_hostDriverCaps = caps;
3043 
3044     // Override some of them
3045     m_hostDriverCaps.max_vertex_attribs = CODEC_MAX_VERTEX_ATTRIBUTES;
3046     m_hostDriverCaps.max_vertex_attrib_bindings = m_hostDriverCaps.max_vertex_attribs;
3047 
3048     // Derive some other settings
3049     m_log2MaxTextureSize = 0;
3050     uint32_t current = 1;
3051     while (current < m_hostDriverCaps.max_texture_size) {
3052         current = current << 1;
3053         ++m_log2MaxTextureSize;
3054     }
3055 
3056     if (m_glesMajorVersion >= 3) {
3057         if (m_hostDriverCaps.max_transform_feedback_separate_attribs)
3058             m_indexedTransformFeedbackBuffers.resize(m_hostDriverCaps.max_transform_feedback_separate_attribs);
3059         if (m_hostDriverCaps.max_uniform_buffer_bindings)
3060             m_indexedUniformBuffers.resize(m_hostDriverCaps.max_uniform_buffer_bindings);
3061         if (m_hostDriverCaps.max_atomic_counter_buffer_bindings)
3062             m_indexedAtomicCounterBuffers.resize(m_hostDriverCaps.max_atomic_counter_buffer_bindings);
3063         if (m_hostDriverCaps.max_shader_storage_buffer_bindings)
3064             m_indexedShaderStorageBuffers.resize(m_hostDriverCaps.max_shader_storage_buffer_bindings);
3065 
3066         BufferBinding buf0Binding;
3067         buf0Binding.buffer = 0;
3068         buf0Binding.offset = 0;
3069         buf0Binding.size = 0;
3070         buf0Binding.stride = 0;
3071         buf0Binding.effectiveStride = 0;
3072 
3073         for (size_t i = 0; i < m_indexedTransformFeedbackBuffers.size(); ++i)
3074             m_indexedTransformFeedbackBuffers[i] = buf0Binding;
3075         for (size_t i = 0; i < m_indexedUniformBuffers.size(); ++i)
3076             m_indexedUniformBuffers[i] = buf0Binding;
3077         for (size_t i = 0; i < m_indexedAtomicCounterBuffers.size(); ++i)
3078             m_indexedAtomicCounterBuffers[i] = buf0Binding;
3079         for (size_t i = 0; i < m_indexedShaderStorageBuffers.size(); ++i)
3080             m_indexedShaderStorageBuffers[i] = buf0Binding;
3081     }
3082 
3083     addFreshFramebuffer(0);
3084 
3085     m_initialized = true;
3086 }
3087 
needsInitFromCaps() const3088 bool GLClientState::needsInitFromCaps() const {
3089     return !m_initialized;
3090 }
3091 
setExtensions(const std::string & extensions)3092 void GLClientState::setExtensions(const std::string& extensions) {
3093     if (!m_extensions_set) m_extensions = extensions;
3094 
3095     m_has_color_buffer_float_extension =
3096         hasExtension("GL_EXT_color_buffer_float");
3097     m_has_color_buffer_half_float_extension =
3098         hasExtension("GL_EXT_color_buffer_half_float");
3099     m_extensions_set = true;
3100 }
3101 
hasExtension(const char * ext) const3102 bool GLClientState::hasExtension(const char* ext) const {
3103     return m_extensions.find(ext) != std::string::npos;
3104 }
3105 
3106 using android::base::guest::AutoLock;
3107 using android::base::guest::Lock;
3108 
3109 // A process-wide fence registry (because we can use fence sync objects across multiple contexts)
3110 struct FenceRegistry {
3111     Lock lock;
3112     PredicateMap<uint64_t, false> existence;
3113 
onFenceCreatedFenceRegistry3114     void onFenceCreated(GLsync sync) {
3115         AutoLock scopedLock(lock);
3116         uint64_t asUint64 = (uint64_t)(uintptr_t)(sync);
3117         existence.add(asUint64);
3118         existence.set(asUint64, true);
3119     }
3120 
onFenceDestroyedFenceRegistry3121     void onFenceDestroyed(GLsync sync) {
3122         AutoLock scopedLock(lock);
3123         uint64_t asUint64 = (uint64_t)(uintptr_t)(sync);
3124         existence.remove(asUint64);
3125     }
3126 
existsFenceRegistry3127     bool exists(GLsync sync) {
3128         AutoLock scopedLock(lock);
3129         uint64_t asUint64 = (uint64_t)(uintptr_t)(sync);
3130         return existence.get(asUint64);
3131     }
3132 };
3133 
3134 static FenceRegistry sFenceRegistry;
3135 
onFenceCreated(GLsync sync)3136 void GLClientState::onFenceCreated(GLsync sync) {
3137     sFenceRegistry.onFenceCreated(sync);
3138 }
3139 
onFenceDestroyed(GLsync sync)3140 void GLClientState::onFenceDestroyed(GLsync sync) {
3141     sFenceRegistry.onFenceDestroyed(sync);
3142 }
3143 
fenceExists(GLsync sync)3144 bool GLClientState::fenceExists(GLsync sync) {
3145     return sFenceRegistry.exists(sync);
3146 }
3147 
3148