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