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