1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "GLClientState.h"
17 #include "GLESTextureUtils.h"
18 #include "ErrorLog.h"
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "glUtils.h"
23 
24 #if PLATFORM_SDK_VERSION < 26
25 #include <cutils/log.h>
26 #else
27 #include <log/log.h>
28 #endif
29 
30 #ifndef MAX
31 #define MAX(a, b) ((a) < (b) ? (b) : (a))
32 #endif
33 
34 // Don't include these in the .h file, or we get weird compile errors.
35 #include <GLES3/gl3.h>
36 #include <GLES3/gl31.h>
37 
init()38 void GLClientState::init() {
39     m_initialized = false;
40     m_nLocations = CODEC_MAX_VERTEX_ATTRIBUTES;
41 
42     m_arrayBuffer = 0;
43     m_arrayBuffer_lastEncode = 0;
44 
45     m_attribEnableCache = 0;
46     m_vaoAttribBindingCacheInvalid = 0xffff;
47     m_vaoAttribBindingHasClientArrayCache = 0;
48     m_vaoAttribBindingHasVboCache = 0;
49     m_noClientArraysCache = 0;
50 
51     m_max_vertex_attrib_bindings = m_nLocations;
52     addVertexArrayObject(0);
53     setVertexArrayObject(0);
54     // init gl constans;
55     m_currVaoState[VERTEX_LOCATION].glConst = GL_VERTEX_ARRAY;
56     m_currVaoState[NORMAL_LOCATION].glConst = GL_NORMAL_ARRAY;
57     m_currVaoState[COLOR_LOCATION].glConst = GL_COLOR_ARRAY;
58     m_currVaoState[POINTSIZE_LOCATION].glConst = GL_POINT_SIZE_ARRAY_OES;
59     m_currVaoState[TEXCOORD0_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
60     m_currVaoState[TEXCOORD1_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
61     m_currVaoState[TEXCOORD2_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
62     m_currVaoState[TEXCOORD3_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
63     m_currVaoState[TEXCOORD4_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
64     m_currVaoState[TEXCOORD5_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
65     m_currVaoState[TEXCOORD6_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
66     m_currVaoState[TEXCOORD7_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
67     m_currVaoState[MATRIXINDEX_LOCATION].glConst = GL_MATRIX_INDEX_ARRAY_OES;
68     m_currVaoState[WEIGHT_LOCATION].glConst = GL_WEIGHT_ARRAY_OES;
69 
70     m_copyReadBuffer = 0;
71     m_copyWriteBuffer = 0;
72     m_pixelPackBuffer = 0;
73     m_pixelUnpackBuffer = 0;
74     m_transformFeedbackBuffer = 0;
75     m_uniformBuffer = 0;
76     m_atomicCounterBuffer = 0;
77     m_dispatchIndirectBuffer = 0;
78     m_drawIndirectBuffer = 0;
79     m_shaderStorageBuffer = 0;
80 
81     m_transformFeedbackActiveUnpaused = false;
82 
83     // to be modified later when these are queried from host.
84     m_max_transform_feedback_separate_attribs = 0;
85     m_max_uniform_buffer_bindings = 0;
86     m_max_atomic_counter_buffer_bindings = 0;
87     m_max_shader_storage_buffer_bindings = 0;
88 
89     m_activeTexture = 0;
90     m_currentProgram = 0;
91     m_currentShaderProgram = 0;
92 
93     m_pixelStore.unpack_alignment = 4;
94     m_pixelStore.pack_alignment = 4;
95 
96     m_pixelStore.unpack_row_length = 0;
97     m_pixelStore.unpack_image_height = 0;
98     m_pixelStore.unpack_skip_pixels = 0;
99     m_pixelStore.unpack_skip_rows = 0;
100     m_pixelStore.unpack_skip_images = 0;
101 
102     m_pixelStore.pack_row_length = 0;
103     m_pixelStore.pack_skip_pixels = 0;
104     m_pixelStore.pack_skip_rows = 0;
105 
106     memset(m_tex.unit, 0, sizeof(m_tex.unit));
107     m_tex.activeUnit = &m_tex.unit[0];
108     m_tex.textureRecs = NULL;
109 
110     mRboState.boundRenderbuffer = 0;
111     mRboState.boundRenderbufferIndex = 0;
112 
113     mFboState.boundDrawFramebuffer = 0;
114     mFboState.boundReadFramebuffer = 0;
115     mFboState.drawFboCheckStatus = GL_NONE;
116     mFboState.readFboCheckStatus = GL_NONE;
117 
118     m_maxVertexAttribsDirty = true;
119 }
120 
GLClientState()121 GLClientState::GLClientState()
122 {
123     init();
124 }
125 
GLClientState(int majorVersion,int minorVersion)126 GLClientState::GLClientState(int majorVersion, int minorVersion) :
127     m_glesMajorVersion(majorVersion),
128     m_glesMinorVersion(minorVersion) {
129     init();
130 }
131 
~GLClientState()132 GLClientState::~GLClientState()
133 {
134 }
135 
enable(int location,int state)136 void GLClientState::enable(int location, int state)
137 {
138     m_currVaoState[location].enableDirty |= (state != m_currVaoState[location].enabled);
139     m_currVaoState[location].enabled = state;
140     if (state) {
141         m_attribEnableCache |= (1 << location);
142         m_noClientArraysCache = 0;
143     } else {
144         m_attribEnableCache &= ~(1 << location);
145     }
146 }
147 
setVertexAttribState(int location,int size,GLenum type,GLboolean normalized,GLsizei stride,const void * data,bool isInt)148 void GLClientState::setVertexAttribState(int location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data, bool isInt)
149 {
150     m_currVaoState[location].size = size;
151     m_currVaoState[location].type = type;
152     m_currVaoState[location].stride = stride;
153     m_currVaoState[location].data = (void*)data;
154     m_currVaoState[location].bufferObject = m_arrayBuffer;
155     m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
156     switch (type) {
157         case GL_INT_2_10_10_10_REV:
158         case GL_UNSIGNED_INT_2_10_10_10_REV:
159             m_currVaoState[location].elementSize =
160                 m_currVaoState[location].elementSize / 4;
161             break;
162         default:
163             break;
164     }
165     m_currVaoState[location].normalized = normalized;
166     m_currVaoState[location].isInt = isInt;
167 }
168 
setVertexBindingDivisor(int bindingindex,GLuint divisor)169 void GLClientState::setVertexBindingDivisor(int bindingindex, GLuint divisor) {
170     m_currVaoState.bufferBinding(bindingindex).divisor = divisor;
171 }
172 
getCurrAttributeBindingInfo(int attribindex)173 const GLClientState::BufferBinding& GLClientState::getCurrAttributeBindingInfo(int attribindex) {
174     return m_currVaoState.bufferBindings_const()[m_currVaoState[attribindex].bindingindex];
175 }
176 
setVertexAttribBinding(int attribindex,int bindingindex)177 void GLClientState::setVertexAttribBinding(int attribindex, int bindingindex) {
178     m_currVaoState[attribindex].bindingindex = bindingindex;
179     m_currVaoState.bufferBinding(bindingindex).vertexAttribLoc = attribindex;
180     m_vaoAttribBindingCacheInvalid |= (1 << attribindex);
181     m_noClientArraysCache = 0;
182 }
183 
setVertexAttribFormat(int location,int size,GLenum type,GLboolean normalized,GLuint reloffset,bool isInt)184 void GLClientState::setVertexAttribFormat(int location, int size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt) {
185     m_currVaoState[location].size = size;
186     m_currVaoState[location].type = type;
187     m_currVaoState[location].normalized = normalized;
188     m_currVaoState[location].reloffset = reloffset;
189     m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
190     switch (type) {
191         case GL_INT_2_10_10_10_REV:
192         case GL_UNSIGNED_INT_2_10_10_10_REV:
193             m_currVaoState[location].elementSize =
194                 m_currVaoState[location].elementSize / 4;
195             break;
196         default:
197             break;
198     }
199     m_currVaoState[location].isInt = isInt;
200 }
201 
addVertexArrayObjects(GLsizei n,GLuint * arrays)202 void GLClientState::addVertexArrayObjects(GLsizei n, GLuint* arrays) {
203     for (GLsizei i = 0; i < n; i++) {
204         addVertexArrayObject(arrays[i]);
205     }
206 }
207 
removeVertexArrayObjects(GLsizei n,const GLuint * arrays)208 void GLClientState::removeVertexArrayObjects(GLsizei n, const GLuint* arrays) {
209     for (GLsizei i = 0; i < n; i++) {
210         if (arrays[i] && m_currVaoState.vaoId() == arrays[i]) {
211             setVertexArrayObject(0);
212         }
213         removeVertexArrayObject(arrays[i]);
214     }
215 }
216 
addVertexArrayObject(GLuint name)217 void GLClientState::addVertexArrayObject(GLuint name) {
218     if (m_vaoMap.find(name) !=
219         m_vaoMap.end()) {
220         ALOGE("%s: ERROR: %u already part of current VAO state!",
221               __FUNCTION__, name);
222         return;
223     }
224 
225     m_vaoMap.insert(
226             VAOStateMap::value_type(
227                 name,
228                 VAOState(0, m_nLocations, std::max(m_nLocations, m_max_vertex_attrib_bindings))));
229     VertexAttribStateVector& attribState =
230         m_vaoMap.find(name)->second.attribState;
231     for (int i = 0; i < m_nLocations; i++) {
232         attribState[i].enabled = 0;
233         attribState[i].enableDirty = false;
234         attribState[i].data = 0;
235         attribState[i].reloffset = 0;
236         attribState[i].bindingindex = i;
237         attribState[i].divisor = 0;
238         attribState[i].size = 4; // 4 is the default size
239         attribState[i].type = GL_FLOAT; // GL_FLOAT is the default type
240     }
241 
242     VertexAttribBindingVector& bindingState =
243         m_vaoMap.find(name)->second.bindingState;
244     for (int i = 0; i < bindingState.size(); i++) {
245         bindingState[i].effectiveStride = 16;
246     }
247 }
248 
removeVertexArrayObject(GLuint name)249 void GLClientState::removeVertexArrayObject(GLuint name) {
250     if (name == 0) {
251         ALOGE("%s: ERROR: cannot delete VAO 0!",
252               __FUNCTION__);
253         return;
254     }
255     if (m_vaoMap.find(name) ==
256         m_vaoMap.end()) {
257         ALOGE("%s: ERROR: %u not found in VAO state!",
258               __FUNCTION__, name);
259         return;
260     }
261     m_vaoMap.erase(name);
262 }
263 
setVertexArrayObject(GLuint name)264 void GLClientState::setVertexArrayObject(GLuint name) {
265     if (m_vaoMap.find(name) ==
266         m_vaoMap.end()) {
267         ALOGE("%s: ERROR: %u not found in VAO state!",
268               __FUNCTION__, name);
269         return;
270     }
271 
272     if (name && m_currVaoState.vaoId() == name) {
273         ALOGV("%s: set vao to self, no-op (%u)",
274               __FUNCTION__, name);
275         return;
276     }
277 
278     m_currVaoState =
279         VAOStateRef(m_vaoMap.find(name));
280 }
281 
isVertexArrayObject(GLuint vao) const282 bool GLClientState::isVertexArrayObject(GLuint vao) const {
283     return m_vaoMap.find(vao) != m_vaoMap.end();
284 }
285 
getVBOUsage(bool * hasClientArrays,bool * hasVBOs)286 void GLClientState::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) {
287     uint8_t todo_count = 0;
288     uint8_t todo[CODEC_MAX_VERTEX_ATTRIBUTES];
289 
290     if (m_noClientArraysCache) {
291         *hasClientArrays = false;
292         *hasVBOs = true;
293         return;
294     }
295 
296     for (int i = 0; i < CODEC_MAX_VERTEX_ATTRIBUTES; i++) {
297         if ((1 << i) & (m_attribEnableCache)) {
298             if (!((1 << i) & m_vaoAttribBindingCacheInvalid)) {
299                 if ((1 << i) & m_vaoAttribBindingHasClientArrayCache) {
300                     *hasClientArrays = true;
301                 }
302                 if ((1 << i) & m_vaoAttribBindingHasVboCache) {
303                     *hasVBOs = true;
304                 }
305                 if (*hasClientArrays && *hasVBOs) return;
306             } else {
307                 todo[todo_count] = i;
308                 ++todo_count;
309             }
310         }
311     }
312 
313     if (todo_count == 0 &&
314         !(*hasClientArrays) &&
315         *hasVBOs) {
316         m_noClientArraysCache = 1;
317     }
318 
319     for (int k = 0; k < todo_count; ++k) {
320         int i = todo[k];
321         const GLClientState::BufferBinding& curr_binding =
322             m_currVaoState.bufferBindings_const()[
323                 m_currVaoState[i].bindingindex];
324         GLuint bufferObject = curr_binding.buffer;
325         if (bufferObject == 0 && curr_binding.offset && hasClientArrays) {
326             *hasClientArrays = true;
327             m_vaoAttribBindingHasClientArrayCache |= (1 << i);
328         } else {
329             m_vaoAttribBindingHasClientArrayCache &= ~(1 << i);
330         }
331         if (bufferObject != 0 && hasVBOs) {
332             *hasVBOs = true;
333             m_vaoAttribBindingHasVboCache |= (1 << i);
334         } else {
335             m_vaoAttribBindingHasVboCache &= ~(1 << i);
336         }
337         m_vaoAttribBindingCacheInvalid &= ~(1 << i);
338         if (*hasClientArrays && *hasVBOs) return;
339     }
340 
341     if (!(*hasClientArrays) &&
342         *hasVBOs) {
343         m_noClientArraysCache = 1;
344     }
345 }
346 
getState(int location)347 const GLClientState::VertexAttribState& GLClientState::getState(int location) {
348     return m_currVaoState[location];
349 }
350 
getStateAndEnableDirty(int location,bool * enableChanged)351 const GLClientState::VertexAttribState& GLClientState::getStateAndEnableDirty(int location, bool *enableChanged)
352 {
353     if (enableChanged) {
354         *enableChanged = m_currVaoState[location].enableDirty;
355     }
356 
357     m_currVaoState[location].enableDirty = false;
358     return m_currVaoState[location];
359 }
360 
updateEnableDirtyArrayForDraw()361 void GLClientState::updateEnableDirtyArrayForDraw() {
362     bool enableChanged;
363     VAOState& vaoState = m_currVaoState.vaoState();
364 
365     int k = 0;
366     for (int i = 0; i < CODEC_MAX_VERTEX_ATTRIBUTES; ++i) {
367         const VertexAttribState &state = getStateAndEnableDirty(i, &enableChanged);
368         if (enableChanged || state.enabled) {
369             vaoState.attributesNeedingUpdateForDraw[k] = i;
370             ++k;
371         }
372     }
373     vaoState.numAttributesNeedingUpdateForDraw = k;
374 }
375 
currentVaoState()376 GLClientState::VAOState& GLClientState::currentVaoState() {
377     return m_currVaoState.vaoState();
378 }
379 
getLocation(GLenum loc)380 int GLClientState::getLocation(GLenum loc)
381 {
382     int retval;
383 
384     switch(loc) {
385     case GL_VERTEX_ARRAY:
386         retval = int(VERTEX_LOCATION);
387         break;
388     case GL_NORMAL_ARRAY:
389         retval = int(NORMAL_LOCATION);
390         break;
391     case GL_COLOR_ARRAY:
392         retval = int(COLOR_LOCATION);
393         break;
394     case GL_POINT_SIZE_ARRAY_OES:
395         retval = int(POINTSIZE_LOCATION);
396         break;
397     case GL_TEXTURE_COORD_ARRAY:
398         retval = int (TEXCOORD0_LOCATION + m_activeTexture);
399         break;
400     case GL_MATRIX_INDEX_ARRAY_OES:
401         retval = int (MATRIXINDEX_LOCATION);
402         break;
403     case GL_WEIGHT_ARRAY_OES:
404         retval = int (WEIGHT_LOCATION);
405         break;
406     default:
407         retval = loc;
408     }
409     return retval;
410 }
411 
sClearIndexedBufferBinding(GLuint id,std::vector<GLClientState::BufferBinding> & bindings)412 static void sClearIndexedBufferBinding(GLuint id, std::vector<GLClientState::BufferBinding>& bindings) {
413     for (size_t i = 0; i < bindings.size(); i++) {
414         if (bindings[i].buffer == id) {
415             bindings[i].offset = 0;
416             bindings[i].stride = 0;
417             bindings[i].effectiveStride = 16;
418             bindings[i].size = 0;
419             bindings[i].buffer = 0;
420         }
421     }
422 }
423 
addBuffer(GLuint id)424 void GLClientState::addBuffer(GLuint id) {
425     mBufferIds.insert(id);
426 }
427 
removeBuffer(GLuint id)428 void GLClientState::removeBuffer(GLuint id) {
429     mBufferIds.erase(id);
430 }
431 
bufferIdExists(GLuint id) const432 bool GLClientState::bufferIdExists(GLuint id) const {
433     return mBufferIds.find(id) != mBufferIds.end();
434 }
435 
unBindBuffer(GLuint id)436 void GLClientState::unBindBuffer(GLuint id) {
437     if (m_arrayBuffer == id) {
438         m_arrayBuffer = 0;
439         m_arrayBuffer_lastEncode = 0;
440     }
441 
442     if (m_currVaoState.iboId() == id) {
443         m_currVaoState.iboId() = 0;
444         m_currVaoState.iboIdLastEncode() = 0;
445     }
446 
447     if (m_copyReadBuffer == id)
448         m_copyReadBuffer = 0;
449     if (m_copyWriteBuffer == id)
450         m_copyWriteBuffer = 0;
451     if (m_pixelPackBuffer == id)
452         m_pixelPackBuffer = 0;
453     if (m_pixelUnpackBuffer == id)
454         m_pixelUnpackBuffer = 0;
455     if (m_transformFeedbackBuffer == id)
456         m_transformFeedbackBuffer = 0;
457     if (m_uniformBuffer == id)
458         m_uniformBuffer = 0;
459     if (m_atomicCounterBuffer == id)
460         m_atomicCounterBuffer = 0;
461     if (m_dispatchIndirectBuffer == id)
462         m_dispatchIndirectBuffer = 0;
463     if (m_drawIndirectBuffer == id)
464         m_drawIndirectBuffer = 0;
465     if (m_shaderStorageBuffer == id)
466         m_shaderStorageBuffer = 0;
467 
468     sClearIndexedBufferBinding(id, m_indexedTransformFeedbackBuffers);
469     sClearIndexedBufferBinding(id, m_indexedUniformBuffers);
470     sClearIndexedBufferBinding(id, m_indexedAtomicCounterBuffers);
471     sClearIndexedBufferBinding(id, m_indexedShaderStorageBuffers);
472     sClearIndexedBufferBinding(id, m_currVaoState.bufferBindings());
473     m_vaoAttribBindingCacheInvalid = 0xffff;
474     m_noClientArraysCache = 0;
475 }
476 
bindBuffer(GLenum target,GLuint id)477 int GLClientState::bindBuffer(GLenum target, GLuint id)
478 {
479     int err = 0;
480     switch(target) {
481     case GL_ARRAY_BUFFER:
482         m_arrayBuffer = id;
483         break;
484     case GL_ELEMENT_ARRAY_BUFFER:
485         m_currVaoState.iboId() = id;
486         break;
487     case GL_COPY_READ_BUFFER:
488         m_copyReadBuffer = id;
489         break;
490     case GL_COPY_WRITE_BUFFER:
491         m_copyWriteBuffer = id;
492         break;
493     case GL_PIXEL_PACK_BUFFER:
494         m_pixelPackBuffer = id;
495         break;
496     case GL_PIXEL_UNPACK_BUFFER:
497         m_pixelUnpackBuffer = id;
498         break;
499     case GL_TRANSFORM_FEEDBACK_BUFFER:
500         m_transformFeedbackBuffer = id;
501         break;
502     case GL_UNIFORM_BUFFER:
503         m_uniformBuffer = id;
504         break;
505     case GL_ATOMIC_COUNTER_BUFFER:
506         m_atomicCounterBuffer = id;
507         break;
508     case GL_DISPATCH_INDIRECT_BUFFER:
509         m_dispatchIndirectBuffer = id;
510         break;
511     case GL_DRAW_INDIRECT_BUFFER:
512         m_drawIndirectBuffer = id;
513         break;
514     case GL_SHADER_STORAGE_BUFFER:
515         m_shaderStorageBuffer = id;
516         break;
517     default:
518         err = -1;
519     }
520     return err;
521 }
522 
bindIndexedBuffer(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size,GLintptr stride,GLintptr effectiveStride)523 void GLClientState::bindIndexedBuffer(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride) {
524     switch (target) {
525     case GL_TRANSFORM_FEEDBACK_BUFFER:
526         m_indexedTransformFeedbackBuffers[index].buffer = buffer;
527         m_indexedTransformFeedbackBuffers[index].offset = offset;
528         m_indexedTransformFeedbackBuffers[index].size = size;
529         m_indexedTransformFeedbackBuffers[index].stride = stride;
530         break;
531     case GL_UNIFORM_BUFFER:
532         m_indexedUniformBuffers[index].buffer = buffer;
533         m_indexedUniformBuffers[index].offset = offset;
534         m_indexedUniformBuffers[index].size = size;
535         m_indexedUniformBuffers[index].stride = stride;
536         break;
537     case GL_ATOMIC_COUNTER_BUFFER:
538         m_indexedAtomicCounterBuffers[index].buffer = buffer;
539         m_indexedAtomicCounterBuffers[index].offset = offset;
540         m_indexedAtomicCounterBuffers[index].size = size;
541         m_indexedAtomicCounterBuffers[index].stride = stride;
542         break;
543     case GL_SHADER_STORAGE_BUFFER:
544         m_indexedShaderStorageBuffers[index].buffer = buffer;
545         m_indexedShaderStorageBuffers[index].offset = offset;
546         m_indexedShaderStorageBuffers[index].size = size;
547         m_indexedShaderStorageBuffers[index].stride = stride;
548         break;
549     default:
550         m_currVaoState.bufferBinding(index).buffer = buffer;
551         m_currVaoState.bufferBinding(index).offset = offset;
552         m_currVaoState.bufferBinding(index).size = size;
553         m_currVaoState.bufferBinding(index).stride = stride;
554         m_currVaoState.bufferBinding(index).effectiveStride = effectiveStride;
555         m_vaoAttribBindingCacheInvalid |= (1 << m_currVaoState.bufferBinding(index).vertexAttribLoc);
556         return;
557     }
558 }
559 
getMaxIndexedBufferBindings(GLenum target) const560 int GLClientState::getMaxIndexedBufferBindings(GLenum target) const {
561     switch (target) {
562     case GL_TRANSFORM_FEEDBACK_BUFFER:
563         return m_indexedTransformFeedbackBuffers.size();
564     case GL_UNIFORM_BUFFER:
565         return m_indexedUniformBuffers.size();
566     case GL_ATOMIC_COUNTER_BUFFER:
567         return m_indexedAtomicCounterBuffers.size();
568     case GL_SHADER_STORAGE_BUFFER:
569         return m_indexedShaderStorageBuffers.size();
570     default:
571         return m_currVaoState.bufferBindings_const().size();
572     }
573 }
574 
isNonIndexedBindNoOp(GLenum target,GLuint buffer)575 bool GLClientState::isNonIndexedBindNoOp(GLenum target, GLuint buffer) {
576     if (buffer != !getLastEncodedBufferBind(target)) return false;
577 
578     int idOrError = getBuffer(target);
579     if (idOrError < 0) {
580         return false;
581     } else {
582         return buffer == (GLuint)idOrError;
583     }
584 }
585 
isIndexedBindNoOp(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size,GLintptr stride,GLintptr effectiveStride)586 bool GLClientState::isIndexedBindNoOp(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride) {
587 
588     if (target == GL_TRANSFORM_FEEDBACK_BUFFER) return false;
589 
590     if (buffer != getLastEncodedBufferBind(target)) return false;
591 
592     switch (target) {
593     case GL_TRANSFORM_FEEDBACK_BUFFER:
594         return m_indexedTransformFeedbackBuffers[index].buffer == buffer &&
595                m_indexedTransformFeedbackBuffers[index].offset == offset &&
596                m_indexedTransformFeedbackBuffers[index].size == size &&
597                m_indexedTransformFeedbackBuffers[index].stride == stride;
598     case GL_UNIFORM_BUFFER:
599         return m_indexedUniformBuffers[index].buffer == buffer &&
600                m_indexedUniformBuffers[index].offset == offset &&
601                m_indexedUniformBuffers[index].size == size &&
602                m_indexedUniformBuffers[index].stride == stride;
603     case GL_ATOMIC_COUNTER_BUFFER:
604         return m_indexedAtomicCounterBuffers[index].buffer == buffer &&
605                m_indexedAtomicCounterBuffers[index].offset == offset &&
606                m_indexedAtomicCounterBuffers[index].size == size &&
607                m_indexedAtomicCounterBuffers[index].stride == stride;
608     case GL_SHADER_STORAGE_BUFFER:
609         return m_indexedShaderStorageBuffers[index].buffer == buffer &&
610                m_indexedShaderStorageBuffers[index].offset == offset &&
611                m_indexedShaderStorageBuffers[index].size == size &&
612                m_indexedShaderStorageBuffers[index].stride == stride;
613     default:
614         return m_currVaoState.bufferBinding(index).buffer == buffer &&
615                m_currVaoState.bufferBinding(index).offset == offset &&
616                m_currVaoState.bufferBinding(index).size == size &&
617                m_currVaoState.bufferBinding(index).stride == stride &&
618                m_currVaoState.bufferBinding(index).effectiveStride == effectiveStride;
619     }
620 }
621 
getBuffer(GLenum target)622 int GLClientState::getBuffer(GLenum target) {
623     int ret=0;
624     switch (target) {
625         case GL_ARRAY_BUFFER:
626             ret = m_arrayBuffer;
627             break;
628         case GL_ELEMENT_ARRAY_BUFFER:
629             ret = m_currVaoState.iboId();
630             break;
631         case GL_COPY_READ_BUFFER:
632             ret = m_copyReadBuffer;
633             break;
634         case GL_COPY_WRITE_BUFFER:
635             ret = m_copyWriteBuffer;
636             break;
637         case GL_PIXEL_PACK_BUFFER:
638             ret = m_pixelPackBuffer;
639             break;
640         case GL_PIXEL_UNPACK_BUFFER:
641             ret = m_pixelUnpackBuffer;
642             break;
643         case GL_TRANSFORM_FEEDBACK_BUFFER:
644             ret = m_transformFeedbackBuffer;
645             break;
646         case GL_UNIFORM_BUFFER:
647             ret = m_uniformBuffer;
648             break;
649         case GL_ATOMIC_COUNTER_BUFFER:
650             ret = m_atomicCounterBuffer;
651             break;
652         case GL_DISPATCH_INDIRECT_BUFFER:
653             ret = m_dispatchIndirectBuffer;
654             break;
655         case GL_DRAW_INDIRECT_BUFFER:
656             ret = m_drawIndirectBuffer;
657             break;
658         case GL_SHADER_STORAGE_BUFFER:
659             ret = m_shaderStorageBuffer;
660             break;
661         default:
662             ret = -1;
663     }
664     return ret;
665 }
666 
getLastEncodedBufferBind(GLenum target)667 GLuint GLClientState::getLastEncodedBufferBind(GLenum target) {
668     GLuint ret;
669     switch (target)
670     {
671     case GL_ARRAY_BUFFER:
672         ret = m_arrayBuffer_lastEncode;
673         break;
674     case GL_ELEMENT_ARRAY_BUFFER:
675         ret = m_currVaoState.iboIdLastEncode();
676         break;
677     default:
678     {
679         int idOrError = getBuffer(target);
680         ret = (idOrError < 0) ? 0 : (GLuint)idOrError;
681     }
682     }
683 
684     return ret;
685 }
686 
setLastEncodedBufferBind(GLenum target,GLuint id)687 void GLClientState::setLastEncodedBufferBind(GLenum target, GLuint id)
688 {
689     switch (target)
690     {
691     case GL_ARRAY_BUFFER:
692         m_arrayBuffer_lastEncode = id;
693         break;
694     case GL_ELEMENT_ARRAY_BUFFER:
695         m_currVaoState.iboIdLastEncode() = id;
696         break;
697     default:
698         break;
699     }
700 }
701 
getClientStatePointer(GLenum pname,GLvoid ** params)702 void GLClientState::getClientStatePointer(GLenum pname, GLvoid** params)
703 {
704     GLenum which_state = -1;
705     switch (pname) {
706     case GL_VERTEX_ARRAY_POINTER: {
707         which_state = GLClientState::VERTEX_LOCATION;
708         break;
709         }
710     case GL_NORMAL_ARRAY_POINTER: {
711         which_state = GLClientState::NORMAL_LOCATION;
712         break;
713         }
714     case GL_COLOR_ARRAY_POINTER: {
715         which_state = GLClientState::COLOR_LOCATION;
716         break;
717         }
718     case GL_TEXTURE_COORD_ARRAY_POINTER: {
719         which_state = getActiveTexture() + GLClientState::TEXCOORD0_LOCATION;
720         break;
721         }
722     case GL_POINT_SIZE_ARRAY_POINTER_OES: {
723         which_state = GLClientState::POINTSIZE_LOCATION;
724         break;
725         }
726     case GL_MATRIX_INDEX_ARRAY_POINTER_OES: {
727         which_state = GLClientState::MATRIXINDEX_LOCATION;
728         break;
729         }
730     case GL_WEIGHT_ARRAY_POINTER_OES: {
731         which_state = GLClientState::WEIGHT_LOCATION;
732         break;
733         }
734     }
735     if (which_state != -1)
736         *params = m_currVaoState[which_state].data;
737 }
738 
setPixelStore(GLenum param,GLint value)739 int GLClientState::setPixelStore(GLenum param, GLint value)
740 {
741     int retval = 0;
742     switch(param) {
743     case GL_UNPACK_ALIGNMENT:
744         m_pixelStore.unpack_alignment = value;
745         break;
746     case GL_PACK_ALIGNMENT:
747         m_pixelStore.pack_alignment = value;
748         break;
749     case GL_UNPACK_ROW_LENGTH:
750         m_pixelStore.unpack_row_length = value;
751         break;
752     case GL_UNPACK_IMAGE_HEIGHT:
753         m_pixelStore.unpack_image_height = value;
754         break;
755     case GL_UNPACK_SKIP_PIXELS:
756         m_pixelStore.unpack_skip_pixels = value;
757         break;
758     case GL_UNPACK_SKIP_ROWS:
759         m_pixelStore.unpack_skip_rows = value;
760         break;
761     case GL_UNPACK_SKIP_IMAGES:
762         m_pixelStore.unpack_skip_images = value;
763         break;
764     case GL_PACK_ROW_LENGTH:
765         m_pixelStore.pack_row_length = value;
766         break;
767     case GL_PACK_SKIP_PIXELS:
768         m_pixelStore.pack_skip_pixels = value;
769         break;
770     case GL_PACK_SKIP_ROWS:
771         m_pixelStore.pack_skip_rows = value;
772         break;
773     default:
774         retval = GL_INVALID_ENUM;
775     }
776     return retval;
777 }
778 
779 
pixelDataSize(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int pack) const780 size_t GLClientState::pixelDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const
781 {
782     if (width <= 0 || height <= 0 || depth <= 0) return 0;
783 
784     ALOGV("%s: pack? %d", __FUNCTION__, pack);
785     if (pack) {
786         ALOGV("%s: pack stats", __FUNCTION__);
787         ALOGV("%s: pack align %d", __FUNCTION__, m_pixelStore.pack_alignment);
788         ALOGV("%s: pack rowlen %d", __FUNCTION__, m_pixelStore.pack_row_length);
789         ALOGV("%s: pack skippixels %d", __FUNCTION__, m_pixelStore.pack_skip_pixels);
790         ALOGV("%s: pack skiprows %d", __FUNCTION__, m_pixelStore.pack_skip_rows);
791     } else {
792         ALOGV("%s: unpack stats", __FUNCTION__);
793         ALOGV("%s: unpack align %d", __FUNCTION__, m_pixelStore.unpack_alignment);
794         ALOGV("%s: unpack rowlen %d", __FUNCTION__, m_pixelStore.unpack_row_length);
795         ALOGV("%s: unpack imgheight %d", __FUNCTION__, m_pixelStore.unpack_image_height);
796         ALOGV("%s: unpack skippixels %d", __FUNCTION__, m_pixelStore.unpack_skip_pixels);
797         ALOGV("%s: unpack skiprows %d", __FUNCTION__, m_pixelStore.unpack_skip_rows);
798         ALOGV("%s: unpack skipimages %d", __FUNCTION__, m_pixelStore.unpack_skip_images);
799     }
800     return GLESTextureUtils::computeTotalImageSize(
801             width, height, depth,
802             format, type,
803             pack ? m_pixelStore.pack_alignment : m_pixelStore.unpack_alignment,
804             pack ? m_pixelStore.pack_row_length : m_pixelStore.unpack_row_length,
805             pack ? 0 : m_pixelStore.unpack_image_height,
806             pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
807             pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
808             pack ? 0 : m_pixelStore.unpack_skip_images);
809 }
810 
pboNeededDataSize(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int pack) const811 size_t GLClientState::pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const
812 {
813     if (width <= 0 || height <= 0 || depth <= 0) return 0;
814 
815     ALOGV("%s: pack? %d", __FUNCTION__, pack);
816     if (pack) {
817         ALOGV("%s: pack stats", __FUNCTION__);
818         ALOGV("%s: pack align %d", __FUNCTION__, m_pixelStore.pack_alignment);
819         ALOGV("%s: pack rowlen %d", __FUNCTION__, m_pixelStore.pack_row_length);
820         ALOGV("%s: pack skippixels %d", __FUNCTION__, m_pixelStore.pack_skip_pixels);
821         ALOGV("%s: pack skiprows %d", __FUNCTION__, m_pixelStore.pack_skip_rows);
822     } else {
823         ALOGV("%s: unpack stats", __FUNCTION__);
824         ALOGV("%s: unpack align %d", __FUNCTION__, m_pixelStore.unpack_alignment);
825         ALOGV("%s: unpack rowlen %d", __FUNCTION__, m_pixelStore.unpack_row_length);
826         ALOGV("%s: unpack imgheight %d", __FUNCTION__, m_pixelStore.unpack_image_height);
827         ALOGV("%s: unpack skippixels %d", __FUNCTION__, m_pixelStore.unpack_skip_pixels);
828         ALOGV("%s: unpack skiprows %d", __FUNCTION__, m_pixelStore.unpack_skip_rows);
829         ALOGV("%s: unpack skipimages %d", __FUNCTION__, m_pixelStore.unpack_skip_images);
830     }
831     return GLESTextureUtils::computeNeededBufferSize(
832             width, height, depth,
833             format, type,
834             pack ? m_pixelStore.pack_alignment : m_pixelStore.unpack_alignment,
835             pack ? m_pixelStore.pack_row_length : m_pixelStore.unpack_row_length,
836             pack ? 0 : m_pixelStore.unpack_image_height,
837             pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
838             pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
839             pack ? 0 : m_pixelStore.unpack_skip_images);
840 }
841 
842 
clearBufferNumElts(GLenum buffer) const843 size_t GLClientState::clearBufferNumElts(GLenum buffer) const
844 {
845     switch (buffer) {
846     case GL_COLOR:
847         return 4;
848     case GL_DEPTH:
849     case GL_STENCIL:
850         return 1;
851     }
852     return 1;
853 }
854 
getPackingOffsets2D(GLsizei width,GLsizei height,GLenum format,GLenum type,int * bpp,int * startOffset,int * pixelRowSize,int * totalRowSize,int * skipRows) const855 void GLClientState::getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
856 {
857     if (width <= 0 || height <= 0) {
858         *startOffset = 0;
859         *pixelRowSize = 0;
860         *totalRowSize = 0;
861         return;
862     }
863 
864     GLESTextureUtils::computePackingOffsets2D(
865             width, height,
866             format, type,
867             m_pixelStore.pack_alignment,
868             m_pixelStore.pack_row_length,
869             m_pixelStore.pack_skip_pixels,
870             m_pixelStore.pack_skip_rows,
871             bpp,
872             startOffset,
873             pixelRowSize,
874             totalRowSize);
875 
876     *skipRows = m_pixelStore.pack_skip_rows;
877 }
878 
getUnpackingOffsets2D(GLsizei width,GLsizei height,GLenum format,GLenum type,int * bpp,int * startOffset,int * pixelRowSize,int * totalRowSize,int * skipRows) const879 void GLClientState::getUnpackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
880 {
881     if (width <= 0 || height <= 0) {
882         *startOffset = 0;
883         *pixelRowSize = 0;
884         *totalRowSize = 0;
885         return;
886     }
887 
888     GLESTextureUtils::computePackingOffsets2D(
889             width, height,
890             format, type,
891             m_pixelStore.unpack_alignment,
892             m_pixelStore.unpack_row_length,
893             m_pixelStore.unpack_skip_pixels,
894             m_pixelStore.unpack_skip_rows,
895             bpp,
896             startOffset,
897             pixelRowSize,
898             totalRowSize);
899 
900     *skipRows = m_pixelStore.unpack_skip_rows;
901 }
902 
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) const903 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
904 {
905     if (width <= 0 || height <= 0) {
906         *startOffset = 0;
907         *pixelRowSize = 0;
908         *totalRowSize = 0;
909         return;
910     }
911 
912     GLESTextureUtils::computePackingOffsets3D(
913             width, height, depth,
914             format, type,
915             m_pixelStore.unpack_alignment,
916             m_pixelStore.unpack_row_length,
917             m_pixelStore.unpack_image_height,
918             m_pixelStore.unpack_skip_pixels,
919             m_pixelStore.unpack_skip_rows,
920             m_pixelStore.unpack_skip_images,
921             bpp,
922             startOffset,
923             pixelRowSize,
924             totalRowSize,
925             pixelImageSize,
926             totalImageSize);
927 
928     *skipRows = m_pixelStore.unpack_skip_rows;
929     *skipImages = m_pixelStore.unpack_skip_images;
930 }
931 
setNumActiveUniformsInUniformBlock(GLuint program,GLuint uniformBlockIndex,GLint numActiveUniforms)932 void GLClientState::setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms) {
933     UniformBlockInfoKey key;
934     key.program = program;
935     key.uniformBlockIndex = uniformBlockIndex;
936 
937     UniformBlockUniformInfo info;
938     info.numActiveUniforms = (size_t)numActiveUniforms;
939 
940     m_uniformBlockInfoMap[key] = info;
941 }
942 
numActiveUniformsInUniformBlock(GLuint program,GLuint uniformBlockIndex) const943 size_t GLClientState::numActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex) const {
944     UniformBlockInfoKey key;
945     key.program = program;
946     key.uniformBlockIndex = uniformBlockIndex;
947     UniformBlockInfoMap::const_iterator it =
948         m_uniformBlockInfoMap.find(key);
949     if (it == m_uniformBlockInfoMap.end()) return 0;
950     return it->second.numActiveUniforms;
951 }
952 
associateProgramWithPipeline(GLuint program,GLuint pipeline)953 void GLClientState::associateProgramWithPipeline(GLuint program, GLuint pipeline) {
954     m_programPipelines[program] = pipeline;
955 }
956 
programPipelineBegin()957 GLClientState::ProgramPipelineIterator GLClientState::programPipelineBegin() {
958     return m_programPipelines.begin();
959 }
960 
programPipelineEnd()961 GLClientState::ProgramPipelineIterator GLClientState::programPipelineEnd() {
962     return m_programPipelines.end();
963 }
964 
setActiveTextureUnit(GLenum texture)965 GLenum GLClientState::setActiveTextureUnit(GLenum texture)
966 {
967     GLuint unit = texture - GL_TEXTURE0;
968     if (unit >= MAX_TEXTURE_UNITS) {
969         return GL_INVALID_ENUM;
970     }
971     m_tex.activeUnit = &m_tex.unit[unit];
972     return GL_NO_ERROR;
973 }
974 
getActiveTextureUnit() const975 GLenum GLClientState::getActiveTextureUnit() const
976 {
977     return GL_TEXTURE0 + (m_tex.activeUnit - &m_tex.unit[0]);
978 }
979 
enableTextureTarget(GLenum target)980 void GLClientState::enableTextureTarget(GLenum target)
981 {
982     switch (target) {
983     case GL_TEXTURE_2D:
984         m_tex.activeUnit->enables |= (1u << TEXTURE_2D);
985         break;
986     case GL_TEXTURE_EXTERNAL_OES:
987         m_tex.activeUnit->enables |= (1u << TEXTURE_EXTERNAL);
988         break;
989     }
990 }
991 
disableTextureTarget(GLenum target)992 void GLClientState::disableTextureTarget(GLenum target)
993 {
994     switch (target) {
995     case GL_TEXTURE_2D:
996         m_tex.activeUnit->enables &= ~(1u << TEXTURE_2D);
997         break;
998     case GL_TEXTURE_EXTERNAL_OES:
999         m_tex.activeUnit->enables &= ~(1u << TEXTURE_EXTERNAL);
1000         break;
1001     }
1002 }
1003 
bindSampler(GLuint unit,GLuint sampler)1004 void GLClientState::bindSampler(GLuint unit, GLuint sampler) {
1005     m_tex.unit[unit].boundSampler = sampler;
1006 }
1007 
isSamplerBindNoOp(GLuint unit,GLuint sampler)1008 bool GLClientState::isSamplerBindNoOp(GLuint unit, GLuint sampler) {
1009     return m_tex.unit[unit].boundSampler == sampler;
1010 }
1011 
onDeleteSamplers(GLsizei n,const GLuint * samplers)1012 void GLClientState::onDeleteSamplers(GLsizei n, const GLuint* samplers) {
1013     for (uint32_t i = 0; i < n; ++i) {
1014         for (uint32_t j = 0; j < MAX_TEXTURE_UNITS; ++j) {
1015             uint32_t currentSampler = m_tex.unit[j].boundSampler;
1016             if (currentSampler == samplers[i]) {
1017                 m_tex.unit[j].boundSampler = 0;
1018             }
1019         }
1020     }
1021 }
1022 
getPriorityEnabledTarget(GLenum allDisabled) const1023 GLenum GLClientState::getPriorityEnabledTarget(GLenum allDisabled) const
1024 {
1025     unsigned int enables = m_tex.activeUnit->enables;
1026     if (enables & (1u << TEXTURE_EXTERNAL)) {
1027         return GL_TEXTURE_EXTERNAL_OES;
1028     } else if (enables & (1u << TEXTURE_2D)) {
1029         return GL_TEXTURE_2D;
1030     } else {
1031         return allDisabled;
1032     }
1033 }
1034 
compareTexId(const void * pid,const void * prec)1035 int GLClientState::compareTexId(const void* pid, const void* prec)
1036 {
1037     const GLuint* id = (const GLuint*)pid;
1038     const TextureRec* rec = (const TextureRec*)prec;
1039     return (GLint)(*id) - (GLint)rec->id;
1040 }
1041 
bindTexture(GLenum target,GLuint texture,GLboolean * firstUse)1042 GLenum GLClientState::bindTexture(GLenum target, GLuint texture,
1043         GLboolean* firstUse)
1044 {
1045     GLboolean first = GL_FALSE;
1046 
1047     TextureRec* texrec = getTextureRec(texture);
1048     if (!texrec) {
1049         texrec = addTextureRec(texture, target);
1050     }
1051 
1052     if (texture && target != texrec->target &&
1053         (target != GL_TEXTURE_EXTERNAL_OES &&
1054          texrec->target != GL_TEXTURE_EXTERNAL_OES)) {
1055         ALOGD("%s: issue GL_INVALID_OPERATION: target 0x%x texrectarget 0x%x texture %u", __FUNCTION__, target, texrec->target, texture);
1056     }
1057 
1058     switch (target) {
1059     case GL_TEXTURE_2D:
1060         m_tex.activeUnit->texture[TEXTURE_2D] = texture;
1061         break;
1062     case GL_TEXTURE_EXTERNAL_OES:
1063         m_tex.activeUnit->texture[TEXTURE_EXTERNAL] = texture;
1064         break;
1065     case GL_TEXTURE_CUBE_MAP:
1066         m_tex.activeUnit->texture[TEXTURE_CUBE_MAP] = texture;
1067         break;
1068     case GL_TEXTURE_2D_ARRAY:
1069         m_tex.activeUnit->texture[TEXTURE_2D_ARRAY] = texture;
1070         break;
1071     case GL_TEXTURE_3D:
1072         m_tex.activeUnit->texture[TEXTURE_3D] = texture;
1073         break;
1074     case GL_TEXTURE_2D_MULTISAMPLE:
1075         m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE] = texture;
1076         break;
1077     }
1078 
1079     if (firstUse) {
1080         *firstUse = first;
1081     }
1082 
1083     return GL_NO_ERROR;
1084 }
1085 
setBoundEGLImage(GLenum target,GLeglImageOES image)1086 void GLClientState::setBoundEGLImage(GLenum target, GLeglImageOES image) {
1087     (void)image;
1088 
1089     GLuint texture = getBoundTexture(target);
1090     TextureRec* texrec = getTextureRec(texture);
1091     if (!texrec) return;
1092     texrec->boundEGLImage = true;
1093 }
1094 
addTextureRec(GLuint id,GLenum target)1095 TextureRec* GLClientState::addTextureRec(GLuint id, GLenum target)
1096 {
1097     TextureRec* tex = new TextureRec;
1098     tex->id = id;
1099     tex->target = target;
1100     tex->format = -1;
1101     tex->multisamples = 0;
1102     tex->immutable = false;
1103     tex->boundEGLImage = false;
1104     tex->dims = new TextureDims;
1105 
1106     (*(m_tex.textureRecs))[id] = tex;
1107     return tex;
1108 }
1109 
getTextureRec(GLuint id) const1110 TextureRec* GLClientState::getTextureRec(GLuint id) const {
1111     SharedTextureDataMap::const_iterator it =
1112         m_tex.textureRecs->find(id);
1113     if (it == m_tex.textureRecs->end()) {
1114         return NULL;
1115     }
1116     return it->second;
1117 }
1118 
setBoundTextureInternalFormat(GLenum target,GLint internalformat)1119 void GLClientState::setBoundTextureInternalFormat(GLenum target, GLint internalformat) {
1120     GLuint texture = getBoundTexture(target);
1121     TextureRec* texrec = getTextureRec(texture);
1122     if (!texrec) return;
1123     texrec->internalformat = internalformat;
1124 }
1125 
setBoundTextureFormat(GLenum target,GLenum format)1126 void GLClientState::setBoundTextureFormat(GLenum target, GLenum format) {
1127     GLuint texture = getBoundTexture(target);
1128     TextureRec* texrec = getTextureRec(texture);
1129     if (!texrec) return;
1130     texrec->format = format;
1131 }
1132 
setBoundTextureType(GLenum target,GLenum type)1133 void GLClientState::setBoundTextureType(GLenum target, GLenum type) {
1134     GLuint texture = getBoundTexture(target);
1135     TextureRec* texrec = getTextureRec(texture);
1136     if (!texrec) return;
1137     texrec->type = type;
1138 }
1139 
setBoundTextureDims(GLenum target,GLsizei level,GLsizei width,GLsizei height,GLsizei depth)1140 void GLClientState::setBoundTextureDims(GLenum target, GLsizei level, GLsizei width, GLsizei height, GLsizei depth) {
1141     GLuint texture = getBoundTexture(target);
1142     TextureRec* texrec = getTextureRec(texture);
1143     if (!texrec) {
1144         return;
1145     }
1146 
1147     if (level == -1) {
1148         GLsizei curr_width = width;
1149         GLsizei curr_height = height;
1150         GLsizei curr_depth = depth;
1151         GLsizei curr_level = 0;
1152 
1153         while (true) {
1154             texrec->dims->widths[curr_level] = curr_width;
1155             texrec->dims->heights[curr_level] = curr_height;
1156             texrec->dims->depths[curr_level] = curr_depth;
1157             if (curr_width >> 1 == 0 &&
1158                 curr_height >> 1 == 0 &&
1159                 ((target == GL_TEXTURE_3D && curr_depth == 0) ||
1160                  true)) {
1161                 break;
1162             }
1163             curr_width = (curr_width >> 1) ? (curr_width >> 1) : 1;
1164             curr_height = (curr_height >> 1) ? (curr_height >> 1) : 1;
1165             if (target == GL_TEXTURE_3D) {
1166                 curr_depth = (curr_depth >> 1) ? (curr_depth >> 1) : 1;
1167             }
1168             curr_level++;
1169         }
1170 
1171     } else {
1172         texrec->dims->widths[level] = width;
1173         texrec->dims->heights[level] = height;
1174         texrec->dims->depths[level] = depth;
1175     }
1176 }
1177 
setBoundTextureSamples(GLenum target,GLsizei samples)1178 void GLClientState::setBoundTextureSamples(GLenum target, GLsizei samples) {
1179     GLuint texture = getBoundTexture(target);
1180     TextureRec* texrec = getTextureRec(texture);
1181     if (!texrec) return;
1182     texrec->multisamples = samples;
1183 }
1184 
setBoundTextureImmutableFormat(GLenum target)1185 void GLClientState::setBoundTextureImmutableFormat(GLenum target) {
1186     GLuint texture = getBoundTexture(target);
1187     TextureRec* texrec = getTextureRec(texture);
1188     if (!texrec) return;
1189     texrec->immutable = true;
1190 }
1191 
isBoundTextureImmutableFormat(GLenum target) const1192 bool GLClientState::isBoundTextureImmutableFormat(GLenum target) const {
1193     GLuint texture = getBoundTexture(target);
1194     TextureRec* texrec = getTextureRec(texture);
1195     if (!texrec) return false;
1196     return texrec->immutable;
1197 }
1198 
getBoundTexture(GLenum target) const1199 GLuint GLClientState::getBoundTexture(GLenum target) const
1200 {
1201     switch (target) {
1202     case GL_TEXTURE_2D:
1203         return m_tex.activeUnit->texture[TEXTURE_2D];
1204     case GL_TEXTURE_EXTERNAL_OES:
1205         return m_tex.activeUnit->texture[TEXTURE_EXTERNAL];
1206     case GL_TEXTURE_CUBE_MAP:
1207         return m_tex.activeUnit->texture[TEXTURE_CUBE_MAP];
1208     case GL_TEXTURE_2D_ARRAY:
1209         return m_tex.activeUnit->texture[TEXTURE_2D_ARRAY];
1210     case GL_TEXTURE_3D:
1211         return m_tex.activeUnit->texture[TEXTURE_3D];
1212     case GL_TEXTURE_2D_MULTISAMPLE:
1213         return m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE];
1214     default:
1215         return 0;
1216     }
1217 }
1218 
1219 // BEGIN driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
1220 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
1221 
unreliableInternalFormat(GLenum internalformat)1222 static bool unreliableInternalFormat(GLenum internalformat) {
1223     switch (internalformat) {
1224     case GL_LUMINANCE:
1225         return true;
1226     default:
1227         return false;
1228     }
1229 }
1230 
writeCopyTexImageState(GLenum target,GLint level,GLenum internalformat)1231 void GLClientState::writeCopyTexImageState
1232     (GLenum target, GLint level, GLenum internalformat) {
1233     if (unreliableInternalFormat(internalformat)) {
1234         CubeMapDef entry;
1235         entry.id = getBoundTexture(GL_TEXTURE_2D);
1236         entry.target = target;
1237         entry.level = level;
1238         entry.internalformat = internalformat;
1239         m_cubeMapDefs.insert(entry);
1240     }
1241 }
1242 
identifyPositiveCubeMapComponent(GLenum target)1243 static GLenum identifyPositiveCubeMapComponent(GLenum target) {
1244     switch (target) {
1245     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1246         return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
1247     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1248         return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
1249     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1250         return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
1251     default:
1252         return 0;
1253     }
1254 }
1255 
copyTexImageNeededTarget(GLenum target,GLint level,GLenum internalformat)1256 GLenum GLClientState::copyTexImageNeededTarget
1257     (GLenum target, GLint level, GLenum internalformat) {
1258     if (unreliableInternalFormat(internalformat)) {
1259         GLenum positiveComponent =
1260             identifyPositiveCubeMapComponent(target);
1261         if (positiveComponent) {
1262             CubeMapDef query;
1263             query.id = getBoundTexture(GL_TEXTURE_2D);
1264             query.target = positiveComponent;
1265             query.level = level;
1266             query.internalformat = internalformat;
1267             if (m_cubeMapDefs.find(query) ==
1268                 m_cubeMapDefs.end()) {
1269                 return positiveComponent;
1270             }
1271         }
1272     }
1273     return 0;
1274 }
1275 
copyTexImageLuminanceCubeMapAMDWorkaround(GLenum target,GLint level,GLenum internalformat)1276 GLenum GLClientState::copyTexImageLuminanceCubeMapAMDWorkaround
1277     (GLenum target, GLint level, GLenum internalformat) {
1278     writeCopyTexImageState(target, level, internalformat);
1279     return copyTexImageNeededTarget(target, level, internalformat);
1280 }
1281 
1282 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
1283 // END driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
1284 
deleteTextures(GLsizei n,const GLuint * textures)1285 void GLClientState::deleteTextures(GLsizei n, const GLuint* textures)
1286 {
1287     // Updating the textures array could be made more efficient when deleting
1288     // several textures:
1289     // - compacting the array could be done in a single pass once the deleted
1290     //   textures are marked, or
1291     // - could swap deleted textures to the end and re-sort.
1292     TextureRec* texrec;
1293     for (const GLuint* texture = textures; texture != textures + n; texture++) {
1294         texrec = getTextureRec(*texture);
1295         if (texrec && texrec->dims) {
1296             delete texrec->dims;
1297         }
1298         if (texrec) {
1299             m_tex.textureRecs->erase(*texture);
1300             delete texrec;
1301             for (TextureUnit* unit = m_tex.unit;
1302                  unit != m_tex.unit + MAX_TEXTURE_UNITS;
1303                  unit++)
1304             {
1305                 if (unit->texture[TEXTURE_2D] == *texture) {
1306                     unit->texture[TEXTURE_2D] = 0;
1307                 } else if (unit->texture[TEXTURE_EXTERNAL] == *texture) {
1308                     unit->texture[TEXTURE_EXTERNAL] = 0;
1309                 }
1310             }
1311         }
1312     }
1313 }
1314 
1315 // RBO//////////////////////////////////////////////////////////////////////////
1316 
addFreshRenderbuffer(GLuint name)1317 void GLClientState::addFreshRenderbuffer(GLuint name) {
1318     // if underlying opengl says these are fresh names,
1319     // but we are keeping a stale one, reset it.
1320     RboProps props;
1321     props.target = GL_RENDERBUFFER;
1322     props.name = name;
1323     props.format = GL_NONE;
1324     props.multisamples = 0;
1325     props.previouslyBound = false;
1326 
1327     if (usedRenderbufferName(name)) {
1328         mRboState.rboData[getRboIndex(name)] = props;
1329     } else {
1330         mRboState.rboData.push_back(props);
1331     }
1332 }
1333 
addRenderbuffers(GLsizei n,GLuint * renderbuffers)1334 void GLClientState::addRenderbuffers(GLsizei n, GLuint* renderbuffers) {
1335     for (size_t i = 0; i < n; i++) {
1336         addFreshRenderbuffer(renderbuffers[i]);
1337     }
1338 }
1339 
getRboIndex(GLuint name) const1340 size_t GLClientState::getRboIndex(GLuint name) const {
1341     for (size_t i = 0; i < mRboState.rboData.size(); i++) {
1342         if (mRboState.rboData[i].name == name) {
1343             return i;
1344         }
1345     }
1346     return -1;
1347 }
1348 
removeRenderbuffers(GLsizei n,const GLuint * renderbuffers)1349 void GLClientState::removeRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
1350     size_t bound_rbo_idx = getRboIndex(boundRboProps_const().name);
1351 
1352     std::vector<GLuint> to_remove;
1353     for (size_t i = 0; i < n; i++) {
1354         if (renderbuffers[i] != 0) { // Never remove the zero rb.
1355             to_remove.push_back(getRboIndex(renderbuffers[i]));
1356         }
1357     }
1358 
1359     for (size_t i = 0; i < to_remove.size(); i++) {
1360         mRboState.rboData[to_remove[i]] = mRboState.rboData.back();
1361         mRboState.rboData.pop_back();
1362     }
1363 
1364     // If we just deleted the currently bound rb,
1365     // bind the zero rb
1366     if (getRboIndex(boundRboProps_const().name) != bound_rbo_idx) {
1367         bindRenderbuffer(GL_RENDERBUFFER, 0);
1368     }
1369 }
1370 
usedRenderbufferName(GLuint name) const1371 bool GLClientState::usedRenderbufferName(GLuint name) const {
1372     for (size_t i = 0; i < mRboState.rboData.size(); i++) {
1373         if (mRboState.rboData[i].name == name) {
1374             return true;
1375         }
1376     }
1377     return false;
1378 }
1379 
setBoundRenderbufferIndex()1380 void GLClientState::setBoundRenderbufferIndex() {
1381     for (size_t i = 0; i < mRboState.rboData.size(); i++) {
1382         if (mRboState.rboData[i].name == mRboState.boundRenderbuffer) {
1383             mRboState.boundRenderbufferIndex = i;
1384             break;
1385         }
1386     }
1387 }
1388 
boundRboProps()1389 RboProps& GLClientState::boundRboProps() {
1390     return mRboState.rboData[mRboState.boundRenderbufferIndex];
1391 }
1392 
boundRboProps_const() const1393 const RboProps& GLClientState::boundRboProps_const() const {
1394     return mRboState.rboData[mRboState.boundRenderbufferIndex];
1395 }
1396 
bindRenderbuffer(GLenum target,GLuint name)1397 void GLClientState::bindRenderbuffer(GLenum target, GLuint name) {
1398     // If unused, add it.
1399     if (!usedRenderbufferName(name)) {
1400         addFreshRenderbuffer(name);
1401     }
1402     mRboState.boundRenderbuffer = name;
1403     setBoundRenderbufferIndex();
1404     boundRboProps().target = target;
1405     boundRboProps().previouslyBound = true;
1406 }
1407 
boundRenderbuffer() const1408 GLuint GLClientState::boundRenderbuffer() const {
1409     return boundRboProps_const().name;
1410 }
1411 
setBoundRenderbufferFormat(GLenum format)1412 void GLClientState::setBoundRenderbufferFormat(GLenum format) {
1413     boundRboProps().format = format;
1414 }
1415 
setBoundRenderbufferSamples(GLsizei samples)1416 void GLClientState::setBoundRenderbufferSamples(GLsizei samples) {
1417     boundRboProps().multisamples = samples;
1418 }
1419 
1420 // FBO//////////////////////////////////////////////////////////////////////////
1421 
1422 // Format querying
1423 
queryRboFormat(GLuint rbo_name) const1424 GLenum GLClientState::queryRboFormat(GLuint rbo_name) const {
1425     return mRboState.rboData[getRboIndex(rbo_name)].format;
1426 }
1427 
queryRboSamples(GLuint rbo_name) const1428 GLsizei GLClientState::queryRboSamples(GLuint rbo_name) const {
1429     return mRboState.rboData[getRboIndex(rbo_name)].multisamples;
1430 }
1431 
queryTexInternalFormat(GLuint tex_name) const1432 GLint GLClientState::queryTexInternalFormat(GLuint tex_name) const {
1433     TextureRec* texrec = getTextureRec(tex_name);
1434     if (!texrec) return -1;
1435     return texrec->internalformat;
1436 }
1437 
queryTexWidth(GLsizei level,GLuint tex_name) const1438 GLsizei GLClientState::queryTexWidth(GLsizei level, GLuint tex_name) const {
1439     TextureRec* texrec = getTextureRec(tex_name);
1440     if (!texrec) {
1441         return 0;
1442     }
1443     return texrec->dims->widths[level];
1444 }
1445 
queryTexHeight(GLsizei level,GLuint tex_name) const1446 GLsizei GLClientState::queryTexHeight(GLsizei level, GLuint tex_name) const {
1447     TextureRec* texrec = getTextureRec(tex_name);
1448     if (!texrec) return 0;
1449     return texrec->dims->heights[level];
1450 }
1451 
queryTexDepth(GLsizei level,GLuint tex_name) const1452 GLsizei GLClientState::queryTexDepth(GLsizei level, GLuint tex_name) const {
1453     TextureRec* texrec = getTextureRec(tex_name);
1454     if (!texrec) return 0;
1455     return texrec->dims->depths[level];
1456 }
1457 
queryTexEGLImageBacked(GLuint tex_name) const1458 bool GLClientState::queryTexEGLImageBacked(GLuint tex_name) const {
1459     TextureRec* texrec = getTextureRec(tex_name);
1460     if (!texrec) return false;
1461     return texrec->boundEGLImage;
1462 }
1463 
queryTexFormat(GLuint tex_name) const1464 GLenum GLClientState::queryTexFormat(GLuint tex_name) const {
1465     TextureRec* texrec = getTextureRec(tex_name);
1466     if (!texrec) return -1;
1467     return texrec->format;
1468 }
1469 
queryTexType(GLuint tex_name) const1470 GLenum GLClientState::queryTexType(GLuint tex_name) const {
1471     TextureRec* texrec = getTextureRec(tex_name);
1472     if (!texrec) return -1;
1473     return texrec->type;
1474 }
1475 
queryTexSamples(GLuint tex_name) const1476 GLsizei GLClientState::queryTexSamples(GLuint tex_name) const {
1477     TextureRec* texrec = getTextureRec(tex_name);
1478     if (!texrec) return 0;
1479     return texrec->multisamples;
1480 }
1481 
queryTexLastBoundTarget(GLuint tex_name) const1482 GLenum GLClientState::queryTexLastBoundTarget(GLuint tex_name) const {
1483     TextureRec* texrec = getTextureRec(tex_name);
1484     if (!texrec) return GL_NONE;
1485     return texrec->target;
1486 }
1487 
getBoundFramebufferFormat(GLenum target,GLenum attachment,FboFormatInfo * res_info) const1488 void GLClientState::getBoundFramebufferFormat(
1489         GLenum target,
1490         GLenum attachment, FboFormatInfo* res_info) const {
1491     const FboProps& props = boundFboProps_const(target);
1492 
1493     res_info->type = FBO_ATTACHMENT_NONE;
1494     res_info->rb_format = GL_NONE;
1495     res_info->rb_multisamples = 0;
1496     res_info->tex_internalformat = -1;
1497     res_info->tex_format = GL_NONE;
1498     res_info->tex_type = GL_NONE;
1499     res_info->tex_multisamples = 0;
1500 
1501     int colorAttachmentIndex =
1502         glUtilsColorAttachmentIndex(attachment);
1503 
1504     if (colorAttachmentIndex != -1) {
1505         if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
1506             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1507             res_info->rb_format =
1508                 queryRboFormat(
1509                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
1510             res_info->rb_multisamples =
1511                 queryRboSamples(
1512                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
1513         } else if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
1514             res_info->type = FBO_ATTACHMENT_TEXTURE;
1515             res_info->tex_internalformat =
1516                 queryTexInternalFormat(
1517                         props.colorAttachmenti_textures[colorAttachmentIndex]);
1518             res_info->tex_format =
1519                 queryTexFormat(
1520                         props.colorAttachmenti_textures[colorAttachmentIndex]);
1521             res_info->tex_type =
1522                 queryTexType(props.colorAttachmenti_textures[colorAttachmentIndex]);
1523             res_info->tex_multisamples =
1524                 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
1525         } else {
1526             res_info->type = FBO_ATTACHMENT_NONE;
1527         }
1528     }
1529 
1530     switch (attachment) {
1531     case GL_DEPTH_ATTACHMENT:
1532         if (props.depthAttachment_hasRbo) {
1533             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1534             res_info->rb_format = queryRboFormat(props.depthAttachment_rbo);
1535             res_info->rb_multisamples =
1536                 queryRboSamples(
1537                         props.depthAttachment_rbo);
1538         } else if (props.depthAttachment_hasTexObj) {
1539             res_info->type = FBO_ATTACHMENT_TEXTURE;
1540             res_info->tex_internalformat = queryTexInternalFormat(props.depthAttachment_texture);
1541             res_info->tex_format = queryTexFormat(props.depthAttachment_texture);
1542             res_info->tex_type = queryTexType(props.depthAttachment_texture);
1543             res_info->tex_multisamples =
1544                 queryTexSamples(props.depthAttachment_texture);
1545         } else {
1546             res_info->type = FBO_ATTACHMENT_NONE;
1547         }
1548         break;
1549     case GL_STENCIL_ATTACHMENT:
1550         if (props.stencilAttachment_hasRbo) {
1551             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1552             res_info->rb_format = queryRboFormat(props.stencilAttachment_rbo);
1553             res_info->rb_multisamples =
1554                 queryRboSamples(
1555                         props.stencilAttachment_rbo);
1556         } else if (props.stencilAttachment_hasTexObj) {
1557             res_info->type = FBO_ATTACHMENT_TEXTURE;
1558             res_info->tex_internalformat = queryTexInternalFormat(props.stencilAttachment_texture);
1559             res_info->tex_format = queryTexFormat(props.stencilAttachment_texture);
1560             res_info->tex_type = queryTexType(props.stencilAttachment_texture);
1561             res_info->tex_multisamples =
1562                 queryTexSamples(props.stencilAttachment_texture);
1563         } else {
1564             res_info->type = FBO_ATTACHMENT_NONE;
1565         }
1566         break;
1567     case GL_DEPTH_STENCIL_ATTACHMENT:
1568         if (props.depthstencilAttachment_hasRbo) {
1569             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1570             res_info->rb_format = queryRboFormat(props.depthstencilAttachment_rbo);
1571             res_info->rb_multisamples =
1572                 queryRboSamples(
1573                         props.depthstencilAttachment_rbo);
1574         } else if (props.depthstencilAttachment_hasTexObj) {
1575             res_info->type = FBO_ATTACHMENT_TEXTURE;
1576             res_info->tex_internalformat = queryTexInternalFormat(props.depthstencilAttachment_texture);
1577             res_info->tex_format = queryTexFormat(props.depthstencilAttachment_texture);
1578             res_info->tex_type = queryTexType(props.depthstencilAttachment_texture);
1579             res_info->tex_multisamples =
1580                 queryTexSamples(props.depthstencilAttachment_texture);
1581         } else {
1582             res_info->type = FBO_ATTACHMENT_NONE;
1583         }
1584         break;
1585     }
1586 }
1587 
getBoundFramebufferAttachmentType(GLenum target,GLenum attachment) const1588 FboAttachmentType GLClientState::getBoundFramebufferAttachmentType(GLenum target, GLenum attachment) const {
1589     FboFormatInfo info;
1590     getBoundFramebufferFormat(target, attachment, &info);
1591     return info.type;
1592 }
1593 
1594 
getMaxColorAttachments() const1595 int GLClientState::getMaxColorAttachments() const {
1596     return m_max_color_attachments;
1597 }
1598 
getMaxDrawBuffers() const1599 int GLClientState::getMaxDrawBuffers() const {
1600     return m_max_draw_buffers;
1601 }
1602 
addFreshFramebuffer(GLuint name)1603 void GLClientState::addFreshFramebuffer(GLuint name) {
1604     FboProps props;
1605     props.name = name;
1606     props.previouslyBound = false;
1607 
1608     props.colorAttachmenti_textures.resize(m_max_color_attachments, 0);
1609     props.depthAttachment_texture = 0;
1610     props.stencilAttachment_texture = 0;
1611     props.depthstencilAttachment_texture = 0;
1612 
1613     props.colorAttachmenti_hasTex.resize(m_max_color_attachments, false);
1614     props.depthAttachment_hasTexObj = false;
1615     props.stencilAttachment_hasTexObj = false;
1616     props.depthstencilAttachment_hasTexObj = false;
1617 
1618     props.colorAttachmenti_rbos.resize(m_max_color_attachments, 0);
1619     props.depthAttachment_rbo = 0;
1620     props.stencilAttachment_rbo = 0;
1621     props.depthstencilAttachment_rbo = 0;
1622 
1623     props.colorAttachmenti_hasRbo.resize(m_max_color_attachments, false);
1624     props.depthAttachment_hasRbo = false;
1625     props.stencilAttachment_hasRbo = false;
1626     props.depthstencilAttachment_hasRbo = false;
1627     mFboState.fboData[name] = props;
1628 }
1629 
addFramebuffers(GLsizei n,GLuint * framebuffers)1630 void GLClientState::addFramebuffers(GLsizei n, GLuint* framebuffers) {
1631     for (size_t i = 0; i < n; i++) {
1632         addFreshFramebuffer(framebuffers[i]);
1633     }
1634 }
1635 
removeFramebuffers(GLsizei n,const GLuint * framebuffers)1636 void GLClientState::removeFramebuffers(GLsizei n, const GLuint* framebuffers) {
1637     for (size_t i = 0; i < n; i++) {
1638         if (framebuffers[i] != 0) { // Never remove the zero fb.
1639             if (framebuffers[i] == mFboState.boundDrawFramebuffer) {
1640                 bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1641             }
1642             if (framebuffers[i] == mFboState.boundReadFramebuffer) {
1643                 bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1644             }
1645             mFboState.fboData.erase(framebuffers[i]);
1646         }
1647     }
1648 }
1649 
usedFramebufferName(GLuint name) const1650 bool GLClientState::usedFramebufferName(GLuint name) const {
1651     return mFboState.fboData.find(name) != mFboState.fboData.end();
1652 }
1653 
boundFboProps(GLenum target)1654 FboProps& GLClientState::boundFboProps(GLenum target) {
1655     switch (target) {
1656     case GL_DRAW_FRAMEBUFFER:
1657         return mFboState.fboData[mFboState.boundDrawFramebuffer];
1658     case GL_READ_FRAMEBUFFER:
1659         return mFboState.fboData[mFboState.boundReadFramebuffer];
1660     case GL_FRAMEBUFFER:
1661         return mFboState.fboData[mFboState.boundDrawFramebuffer];
1662     }
1663     return mFboState.fboData[mFboState.boundDrawFramebuffer];
1664 }
1665 
boundFboProps_const(GLenum target) const1666 const FboProps& GLClientState::boundFboProps_const(GLenum target) const {
1667     switch (target) {
1668     case GL_DRAW_FRAMEBUFFER:
1669         return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
1670     case GL_READ_FRAMEBUFFER:
1671         return mFboState.fboData.find(mFboState.boundReadFramebuffer)->second;
1672     case GL_FRAMEBUFFER:
1673         return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
1674     }
1675     return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
1676 }
1677 
bindFramebuffer(GLenum target,GLuint name)1678 void GLClientState::bindFramebuffer(GLenum target, GLuint name) {
1679     // If unused, add it.
1680     if (!usedFramebufferName(name)) {
1681         addFreshFramebuffer(name);
1682     }
1683     switch (target) {
1684         case GL_DRAW_FRAMEBUFFER:
1685             mFboState.boundDrawFramebuffer = name;
1686             break;
1687         case GL_READ_FRAMEBUFFER:
1688             mFboState.boundReadFramebuffer = name;
1689             break;
1690         default: // case GL_FRAMEBUFFER:
1691             mFboState.boundDrawFramebuffer = name;
1692             mFboState.boundReadFramebuffer = name;
1693             break;
1694     }
1695     boundFboProps(target).previouslyBound = true;
1696 }
1697 
setCheckFramebufferStatus(GLenum target,GLenum status)1698 void GLClientState::setCheckFramebufferStatus(GLenum target, GLenum status) {
1699     switch (target) {
1700         case GL_DRAW_FRAMEBUFFER:
1701             mFboState.drawFboCheckStatus = status;
1702             break;
1703         case GL_READ_FRAMEBUFFER:
1704             mFboState.readFboCheckStatus = status;
1705             break;
1706         case GL_FRAMEBUFFER:
1707             mFboState.drawFboCheckStatus = status;
1708             break;
1709     }
1710 }
1711 
getCheckFramebufferStatus(GLenum target) const1712 GLenum GLClientState::getCheckFramebufferStatus(GLenum target) const {
1713     switch (target) {
1714     case GL_DRAW_FRAMEBUFFER:
1715         return mFboState.drawFboCheckStatus;
1716     case GL_READ_FRAMEBUFFER:
1717         return mFboState.readFboCheckStatus;
1718     case GL_FRAMEBUFFER:
1719         return mFboState.drawFboCheckStatus;
1720     }
1721     return mFboState.drawFboCheckStatus;
1722 }
1723 
boundFramebuffer(GLenum target) const1724 GLuint GLClientState::boundFramebuffer(GLenum target) const {
1725     return boundFboProps_const(target).name;
1726 }
1727 
1728 // Texture objects for FBOs/////////////////////////////////////////////////////
1729 
attachTextureObject(GLenum target,GLenum attachment,GLuint texture)1730 void GLClientState::attachTextureObject(
1731         GLenum target,
1732         GLenum attachment, GLuint texture) {
1733 
1734     int colorAttachmentIndex =
1735         glUtilsColorAttachmentIndex(attachment);
1736 
1737     if (colorAttachmentIndex != -1) {
1738         boundFboProps(target).colorAttachmenti_textures[colorAttachmentIndex] = texture;
1739         boundFboProps(target).colorAttachmenti_hasTex[colorAttachmentIndex] = true;
1740     }
1741 
1742     switch (attachment) {
1743     case GL_DEPTH_ATTACHMENT:
1744         boundFboProps(target).depthAttachment_texture = texture;
1745         boundFboProps(target).depthAttachment_hasTexObj = true;
1746         break;
1747     case GL_STENCIL_ATTACHMENT:
1748         boundFboProps(target).stencilAttachment_texture = texture;
1749         boundFboProps(target).stencilAttachment_hasTexObj = true;
1750         break;
1751     case GL_DEPTH_STENCIL_ATTACHMENT:
1752         boundFboProps(target).depthstencilAttachment_texture = texture;
1753         boundFboProps(target).depthstencilAttachment_hasTexObj = true;
1754         boundFboProps(target).stencilAttachment_texture = texture;
1755         boundFboProps(target).stencilAttachment_hasTexObj = true;
1756         boundFboProps(target).depthAttachment_texture = texture;
1757         boundFboProps(target).depthAttachment_hasTexObj = true;
1758         break;
1759     }
1760 }
1761 
getFboAttachmentTextureId(GLenum target,GLenum attachment) const1762 GLuint GLClientState::getFboAttachmentTextureId(GLenum target, GLenum attachment) const {
1763     GLuint res = 0; // conservative
1764 
1765     int colorAttachmentIndex =
1766         glUtilsColorAttachmentIndex(attachment);
1767 
1768     if (colorAttachmentIndex != -1) {
1769         res = boundFboProps_const(target).colorAttachmenti_textures[colorAttachmentIndex];
1770     }
1771 
1772     switch (attachment) {
1773     case GL_DEPTH_ATTACHMENT:
1774         res = boundFboProps_const(target).depthAttachment_texture;
1775         break;
1776     case GL_STENCIL_ATTACHMENT:
1777         res = boundFboProps_const(target).stencilAttachment_texture;
1778         break;
1779     case GL_DEPTH_STENCIL_ATTACHMENT:
1780         res = boundFboProps_const(target).depthstencilAttachment_texture;
1781         break;
1782     }
1783     return res;
1784 }
1785 
1786 // RBOs for FBOs////////////////////////////////////////////////////////////////
1787 
detachRbo(GLuint renderbuffer)1788 void GLClientState::detachRbo(GLuint renderbuffer) {
1789     for (int i = 0; i < m_max_color_attachments; i++) {
1790         detachRboFromFbo(GL_DRAW_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
1791         detachRboFromFbo(GL_READ_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
1792     }
1793 
1794     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
1795     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
1796 
1797     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
1798     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
1799 
1800     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
1801     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
1802 }
1803 
detachRboFromFbo(GLenum target,GLenum attachment,GLuint renderbuffer)1804 void GLClientState::detachRboFromFbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
1805     int colorAttachmentIndex =
1806         glUtilsColorAttachmentIndex(attachment);
1807 
1808     if (colorAttachmentIndex != -1) {
1809         if (boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] &&
1810             boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] == renderbuffer) {
1811             boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = 0;
1812             boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = false;
1813         }
1814     }
1815 
1816     switch (attachment) {
1817     case GL_DEPTH_ATTACHMENT:
1818         if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
1819             boundFboProps(target).depthAttachment_hasRbo) {
1820             boundFboProps(target).depthAttachment_rbo = 0;
1821             boundFboProps(target).depthAttachment_hasRbo = false;
1822         }
1823         break;
1824     case GL_STENCIL_ATTACHMENT:
1825         if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
1826             boundFboProps(target).stencilAttachment_hasRbo) {
1827             boundFboProps(target).stencilAttachment_rbo = 0;
1828             boundFboProps(target).stencilAttachment_hasRbo = false;
1829         }
1830         break;
1831     case GL_DEPTH_STENCIL_ATTACHMENT:
1832         if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
1833             boundFboProps(target).depthAttachment_hasRbo) {
1834             boundFboProps(target).depthAttachment_rbo = 0;
1835             boundFboProps(target).depthAttachment_hasRbo = false;
1836         }
1837         if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
1838             boundFboProps(target).stencilAttachment_hasRbo) {
1839             boundFboProps(target).stencilAttachment_rbo = 0;
1840             boundFboProps(target).stencilAttachment_hasRbo = false;
1841         }
1842         if (boundFboProps(target).depthstencilAttachment_rbo == renderbuffer &&
1843             boundFboProps(target).depthstencilAttachment_hasRbo) {
1844             boundFboProps(target).depthstencilAttachment_rbo = 0;
1845             boundFboProps(target).depthstencilAttachment_hasRbo = false;
1846         }
1847         break;
1848     }
1849 }
1850 
attachRbo(GLenum target,GLenum attachment,GLuint renderbuffer)1851 void GLClientState::attachRbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
1852 
1853     int colorAttachmentIndex =
1854         glUtilsColorAttachmentIndex(attachment);
1855 
1856     if (colorAttachmentIndex != -1) {
1857         boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = renderbuffer;
1858         boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = true;
1859     }
1860 
1861     switch (attachment) {
1862     case GL_DEPTH_ATTACHMENT:
1863         boundFboProps(target).depthAttachment_rbo = renderbuffer;
1864         boundFboProps(target).depthAttachment_hasRbo = true;
1865         break;
1866     case GL_STENCIL_ATTACHMENT:
1867         boundFboProps(target).stencilAttachment_rbo = renderbuffer;
1868         boundFboProps(target).stencilAttachment_hasRbo = true;
1869         break;
1870     case GL_DEPTH_STENCIL_ATTACHMENT:
1871         boundFboProps(target).depthAttachment_rbo = renderbuffer;
1872         boundFboProps(target).depthAttachment_hasRbo = true;
1873         boundFboProps(target).stencilAttachment_rbo = renderbuffer;
1874         boundFboProps(target).stencilAttachment_hasRbo = true;
1875         boundFboProps(target).depthstencilAttachment_rbo = renderbuffer;
1876         boundFboProps(target).depthstencilAttachment_hasRbo = true;
1877         break;
1878     }
1879 }
1880 
getFboAttachmentRboId(GLenum target,GLenum attachment) const1881 GLuint GLClientState::getFboAttachmentRboId(GLenum target, GLenum attachment) const {
1882     GLuint res = 0; // conservative
1883 
1884     int colorAttachmentIndex =
1885         glUtilsColorAttachmentIndex(attachment);
1886 
1887     if (colorAttachmentIndex != -1) {
1888         res = boundFboProps_const(target).colorAttachmenti_rbos[colorAttachmentIndex];
1889     }
1890 
1891     switch (attachment) {
1892     case GL_DEPTH_ATTACHMENT:
1893         res = boundFboProps_const(target).depthAttachment_rbo;
1894         break;
1895     case GL_STENCIL_ATTACHMENT:
1896         res = boundFboProps_const(target).stencilAttachment_rbo;
1897         break;
1898     case GL_DEPTH_STENCIL_ATTACHMENT:
1899         res = boundFboProps_const(target).depthstencilAttachment_rbo;
1900         break;
1901     }
1902     return res;
1903 }
1904 
attachmentHasObject(GLenum target,GLenum attachment) const1905 bool GLClientState::attachmentHasObject(GLenum target, GLenum attachment) const {
1906     bool res = true; // liberal
1907 
1908     int colorAttachmentIndex =
1909         glUtilsColorAttachmentIndex(attachment);
1910 
1911     if (colorAttachmentIndex != -1) {
1912         res = boundFboProps_const(target).colorAttachmenti_hasTex[colorAttachmentIndex] ||
1913               boundFboProps_const(target).colorAttachmenti_hasRbo[colorAttachmentIndex];
1914     }
1915 
1916     switch (attachment) {
1917     case GL_DEPTH_ATTACHMENT:
1918         res = (boundFboProps_const(target).depthAttachment_hasTexObj) ||
1919               (boundFboProps_const(target).depthAttachment_hasRbo);
1920         break;
1921     case GL_STENCIL_ATTACHMENT:
1922         res = (boundFboProps_const(target).stencilAttachment_hasTexObj) ||
1923               (boundFboProps_const(target).stencilAttachment_hasRbo);
1924         break;
1925     case GL_DEPTH_STENCIL_ATTACHMENT:
1926         res = (boundFboProps_const(target).depthstencilAttachment_hasTexObj) ||
1927               (boundFboProps_const(target).depthstencilAttachment_hasRbo);
1928         break;
1929     }
1930     return res;
1931 }
1932 
objectOfAttachment(GLenum target,GLenum attachment) const1933 GLuint GLClientState::objectOfAttachment(GLenum target, GLenum attachment) const {
1934     const FboProps& props = boundFboProps_const(target);
1935 
1936     int colorAttachmentIndex =
1937         glUtilsColorAttachmentIndex(attachment);
1938 
1939     if (colorAttachmentIndex != -1) {
1940         if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
1941             return props.colorAttachmenti_textures[colorAttachmentIndex];
1942         } else if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
1943             return props.colorAttachmenti_rbos[colorAttachmentIndex];
1944         } else {
1945             return 0;
1946         }
1947     }
1948 
1949     switch (attachment) {
1950     case GL_DEPTH_ATTACHMENT:
1951         if (props.depthAttachment_hasTexObj) {
1952             return props.depthAttachment_texture;
1953         } else if (props.depthAttachment_hasRbo) {
1954             return props.depthAttachment_rbo;
1955         } else {
1956             return 0;
1957         }
1958         break;
1959     case GL_STENCIL_ATTACHMENT:
1960         if (props.stencilAttachment_hasTexObj) {
1961             return props.stencilAttachment_texture;
1962         } else if (props.stencilAttachment_hasRbo) {
1963             return props.stencilAttachment_rbo;
1964         } else {
1965             return 0;
1966         }
1967     case GL_DEPTH_STENCIL_ATTACHMENT:
1968         if (props.depthstencilAttachment_hasTexObj) {
1969             return props.depthstencilAttachment_texture;
1970         } else if (props.depthstencilAttachment_hasRbo) {
1971             return props.depthstencilAttachment_rbo;
1972         } else {
1973             return 0;
1974         }
1975         break;
1976     }
1977     return 0;
1978 }
1979 
setTransformFeedbackActiveUnpaused(bool activeUnpaused)1980 void GLClientState::setTransformFeedbackActiveUnpaused(bool activeUnpaused) {
1981     m_transformFeedbackActiveUnpaused = activeUnpaused;
1982 }
1983 
getTransformFeedbackActiveUnpaused() const1984 bool GLClientState::getTransformFeedbackActiveUnpaused() const {
1985     return m_transformFeedbackActiveUnpaused;
1986 }
1987 
setTextureData(SharedTextureDataMap * sharedTexData)1988 void GLClientState::setTextureData(SharedTextureDataMap* sharedTexData) {
1989     m_tex.textureRecs = sharedTexData;
1990 }
1991 
fromMakeCurrent()1992 void GLClientState::fromMakeCurrent() {
1993     if (mFboState.fboData.find(0) == mFboState.fboData.end()) {
1994         addFreshFramebuffer(0);
1995     }
1996     FboProps& default_fb_props = mFboState.fboData[0];
1997     default_fb_props.colorAttachmenti_hasRbo[0] = true;
1998     default_fb_props.depthAttachment_hasRbo = true;
1999     default_fb_props.stencilAttachment_hasRbo = true;
2000     default_fb_props.depthstencilAttachment_hasRbo = true;
2001 }
2002 
initFromCaps(int max_transform_feedback_separate_attribs,int max_uniform_buffer_bindings,int max_atomic_counter_buffer_bindings,int max_shader_storage_buffer_bindings,int max_vertex_attrib_bindings,int max_color_attachments,int max_draw_buffers)2003 void GLClientState::initFromCaps(
2004     int max_transform_feedback_separate_attribs,
2005     int max_uniform_buffer_bindings,
2006     int max_atomic_counter_buffer_bindings,
2007     int max_shader_storage_buffer_bindings,
2008     int max_vertex_attrib_bindings,
2009     int max_color_attachments,
2010     int max_draw_buffers) {
2011 
2012     m_max_vertex_attrib_bindings = max_vertex_attrib_bindings;
2013 
2014     if (m_glesMajorVersion >= 3) {
2015         m_max_transform_feedback_separate_attribs = max_transform_feedback_separate_attribs;
2016         m_max_uniform_buffer_bindings = max_uniform_buffer_bindings;
2017         m_max_atomic_counter_buffer_bindings = max_atomic_counter_buffer_bindings;
2018         m_max_shader_storage_buffer_bindings = max_shader_storage_buffer_bindings;
2019 
2020         if (m_max_transform_feedback_separate_attribs)
2021             m_indexedTransformFeedbackBuffers.resize(m_max_transform_feedback_separate_attribs);
2022         if (m_max_uniform_buffer_bindings)
2023             m_indexedUniformBuffers.resize(m_max_uniform_buffer_bindings);
2024         if (m_max_atomic_counter_buffer_bindings)
2025             m_indexedAtomicCounterBuffers.resize(m_max_atomic_counter_buffer_bindings);
2026         if (m_max_shader_storage_buffer_bindings)
2027             m_indexedShaderStorageBuffers.resize(m_max_shader_storage_buffer_bindings);
2028 
2029         BufferBinding buf0Binding;
2030         buf0Binding.buffer = 0;
2031         buf0Binding.offset = 0;
2032         buf0Binding.size = 0;
2033         buf0Binding.stride = 0;
2034         buf0Binding.effectiveStride = 0;
2035 
2036         for (size_t i = 0; i < m_indexedTransformFeedbackBuffers.size(); ++i)
2037             m_indexedTransformFeedbackBuffers[i] = buf0Binding;
2038         for (size_t i = 0; i < m_indexedUniformBuffers.size(); ++i)
2039             m_indexedUniformBuffers[i] = buf0Binding;
2040         for (size_t i = 0; i < m_indexedAtomicCounterBuffers.size(); ++i)
2041             m_indexedAtomicCounterBuffers[i] = buf0Binding;
2042         for (size_t i = 0; i < m_indexedShaderStorageBuffers.size(); ++i)
2043             m_indexedShaderStorageBuffers[i] = buf0Binding;
2044     }
2045 
2046     m_max_color_attachments = max_color_attachments;
2047     m_max_draw_buffers = max_draw_buffers;
2048 
2049     addFreshRenderbuffer(0);
2050     addFreshFramebuffer(0);
2051 
2052     m_initialized = true;
2053 }
2054 
needsInitFromCaps() const2055 bool GLClientState::needsInitFromCaps() const {
2056     return !m_initialized;
2057 }
2058