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