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
33void 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
108GLClientState::GLClientState()
109{
110    init();
111}
112
113GLClientState::GLClientState(int majorVersion, int minorVersion) :
114    m_glesMajorVersion(majorVersion),
115    m_glesMinorVersion(minorVersion) {
116    init();
117}
118
119GLClientState::~GLClientState()
120{
121}
122
123void 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
129void 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
150void GLClientState::setVertexBindingDivisor(int bindingindex, GLuint divisor) {
151    m_currVaoState.bufferBinding(bindingindex).divisor = divisor;
152}
153
154const GLClientState::BufferBinding& GLClientState::getCurrAttributeBindingInfo(int attribindex) {
155    return m_currVaoState.bufferBindings_const()[m_currVaoState[attribindex].bindingindex];
156}
157
158void GLClientState::setVertexAttribBinding(int attribindex, int bindingindex) {
159    m_currVaoState[attribindex].bindingindex = bindingindex;
160}
161
162void 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
180void GLClientState::addVertexArrayObjects(GLsizei n, GLuint* arrays) {
181    for (GLsizei i = 0; i < n; i++) {
182        addVertexArrayObject(arrays[i]);
183    }
184}
185
186void 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
195void 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
227void 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
242void 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
265bool GLClientState::isVertexArrayObject(GLuint vao) const {
266    return m_vaoMap.find(vao) != m_vaoMap.end();
267}
268
269const GLClientState::VertexAttribState& GLClientState::getState(int location)
270{
271    return m_currVaoState[location];
272}
273
274const 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
284int 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
316static 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
329void GLClientState::addBuffer(GLuint id) {
330    mBufferIds.insert(id);
331}
332
333void GLClientState::removeBuffer(GLuint id) {
334    mBufferIds.erase(id);
335}
336
337bool GLClientState::bufferIdExists(GLuint id) const {
338    return mBufferIds.find(id) != mBufferIds.end();
339}
340
341void 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
372int 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
418void 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
454int 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
469int 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
514void 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
551int 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
592size_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
623size_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
655size_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
667void GLClientState::getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
668{
669    if (width <= 0 || height <= 0) {
670        *startOffset = 0;
671        *pixelRowSize = 0;
672        *totalRowSize = 0;
673        return;
674    }
675
676    GLESTextureUtils::computePackingOffsets2D(
677            width, height,
678            format, type,
679            m_pixelStore.pack_alignment,
680            m_pixelStore.pack_row_length,
681            m_pixelStore.pack_skip_pixels,
682            m_pixelStore.pack_skip_rows,
683            startOffset,
684            pixelRowSize,
685            totalRowSize);
686
687    *skipRows = m_pixelStore.pack_skip_rows;
688}
689
690void GLClientState::setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms) {
691    UniformBlockInfoKey key;
692    key.program = program;
693    key.uniformBlockIndex = uniformBlockIndex;
694
695    UniformBlockUniformInfo info;
696    info.numActiveUniforms = (size_t)numActiveUniforms;
697
698    m_uniformBlockInfoMap[key] = info;
699}
700
701size_t GLClientState::numActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex) const {
702    UniformBlockInfoKey key;
703    key.program = program;
704    key.uniformBlockIndex = uniformBlockIndex;
705    UniformBlockInfoMap::const_iterator it =
706        m_uniformBlockInfoMap.find(key);
707    if (it == m_uniformBlockInfoMap.end()) return 0;
708    return it->second.numActiveUniforms;
709}
710
711void GLClientState::associateProgramWithPipeline(GLuint program, GLuint pipeline) {
712    m_programPipelines[program] = pipeline;
713}
714
715GLClientState::ProgramPipelineIterator GLClientState::programPipelineBegin() {
716    return m_programPipelines.begin();
717}
718
719GLClientState::ProgramPipelineIterator GLClientState::programPipelineEnd() {
720    return m_programPipelines.end();
721}
722
723GLenum GLClientState::setActiveTextureUnit(GLenum texture)
724{
725    GLuint unit = texture - GL_TEXTURE0;
726    if (unit >= MAX_TEXTURE_UNITS) {
727        return GL_INVALID_ENUM;
728    }
729    m_tex.activeUnit = &m_tex.unit[unit];
730    return GL_NO_ERROR;
731}
732
733GLenum GLClientState::getActiveTextureUnit() const
734{
735    return GL_TEXTURE0 + (m_tex.activeUnit - &m_tex.unit[0]);
736}
737
738void GLClientState::enableTextureTarget(GLenum target)
739{
740    switch (target) {
741    case GL_TEXTURE_2D:
742        m_tex.activeUnit->enables |= (1u << TEXTURE_2D);
743        break;
744    case GL_TEXTURE_EXTERNAL_OES:
745        m_tex.activeUnit->enables |= (1u << TEXTURE_EXTERNAL);
746        break;
747    }
748}
749
750void GLClientState::disableTextureTarget(GLenum target)
751{
752    switch (target) {
753    case GL_TEXTURE_2D:
754        m_tex.activeUnit->enables &= ~(1u << TEXTURE_2D);
755        break;
756    case GL_TEXTURE_EXTERNAL_OES:
757        m_tex.activeUnit->enables &= ~(1u << TEXTURE_EXTERNAL);
758        break;
759    }
760}
761
762GLenum GLClientState::getPriorityEnabledTarget(GLenum allDisabled) const
763{
764    unsigned int enables = m_tex.activeUnit->enables;
765    if (enables & (1u << TEXTURE_EXTERNAL)) {
766        return GL_TEXTURE_EXTERNAL_OES;
767    } else if (enables & (1u << TEXTURE_2D)) {
768        return GL_TEXTURE_2D;
769    } else {
770        return allDisabled;
771    }
772}
773
774int GLClientState::compareTexId(const void* pid, const void* prec)
775{
776    const GLuint* id = (const GLuint*)pid;
777    const TextureRec* rec = (const TextureRec*)prec;
778    return (GLint)(*id) - (GLint)rec->id;
779}
780
781GLenum GLClientState::bindTexture(GLenum target, GLuint texture,
782        GLboolean* firstUse)
783{
784    GLboolean first = GL_FALSE;
785
786    TextureRec* texrec = getTextureRec(texture);
787    if (!texrec) {
788        texrec = addTextureRec(texture, target);
789    }
790
791    if (texture && target != texrec->target &&
792        (target != GL_TEXTURE_EXTERNAL_OES &&
793         texrec->target != GL_TEXTURE_EXTERNAL_OES)) {
794        ALOGD("%s: issue GL_INVALID_OPERATION: target 0x%x texrectarget 0x%x texture %u", __FUNCTION__, target, texrec->target, texture);
795    }
796
797    switch (target) {
798    case GL_TEXTURE_2D:
799        m_tex.activeUnit->texture[TEXTURE_2D] = texture;
800        break;
801    case GL_TEXTURE_EXTERNAL_OES:
802        m_tex.activeUnit->texture[TEXTURE_EXTERNAL] = texture;
803        break;
804    case GL_TEXTURE_CUBE_MAP:
805        m_tex.activeUnit->texture[TEXTURE_CUBE_MAP] = texture;
806        break;
807    case GL_TEXTURE_2D_ARRAY:
808        m_tex.activeUnit->texture[TEXTURE_2D_ARRAY] = texture;
809        break;
810    case GL_TEXTURE_3D:
811        m_tex.activeUnit->texture[TEXTURE_3D] = texture;
812        break;
813    case GL_TEXTURE_2D_MULTISAMPLE:
814        m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE] = texture;
815        break;
816    }
817
818    if (firstUse) {
819        *firstUse = first;
820    }
821
822    return GL_NO_ERROR;
823}
824
825void GLClientState::setBoundEGLImage(GLenum target, GLeglImageOES image) {
826    GLuint texture = getBoundTexture(target);
827    TextureRec* texrec = getTextureRec(texture);
828    if (!texrec) return;
829    texrec->boundEGLImage = true;
830}
831
832TextureRec* GLClientState::addTextureRec(GLuint id, GLenum target)
833{
834    TextureRec* tex = new TextureRec;
835    tex->id = id;
836    tex->target = target;
837    tex->format = -1;
838    tex->multisamples = 0;
839    tex->immutable = false;
840    tex->boundEGLImage = false;
841    tex->dims = new TextureDims;
842
843    (*(m_tex.textureRecs))[id] = tex;
844    return tex;
845}
846
847TextureRec* GLClientState::getTextureRec(GLuint id) const {
848    SharedTextureDataMap::const_iterator it =
849        m_tex.textureRecs->find(id);
850    if (it == m_tex.textureRecs->end()) {
851        return NULL;
852    }
853    return it->second;
854}
855
856void GLClientState::setBoundTextureInternalFormat(GLenum target, GLint internalformat) {
857    GLuint texture = getBoundTexture(target);
858    TextureRec* texrec = getTextureRec(texture);
859    if (!texrec) return;
860    texrec->internalformat = internalformat;
861}
862
863void GLClientState::setBoundTextureFormat(GLenum target, GLenum format) {
864    GLuint texture = getBoundTexture(target);
865    TextureRec* texrec = getTextureRec(texture);
866    if (!texrec) return;
867    texrec->format = format;
868}
869
870void GLClientState::setBoundTextureType(GLenum target, GLenum type) {
871    GLuint texture = getBoundTexture(target);
872    TextureRec* texrec = getTextureRec(texture);
873    if (!texrec) return;
874    texrec->type = type;
875}
876
877void GLClientState::setBoundTextureDims(GLenum target, GLsizei level, GLsizei width, GLsizei height, GLsizei depth) {
878    GLuint texture = getBoundTexture(target);
879    TextureRec* texrec = getTextureRec(texture);
880    if (!texrec) {
881        return;
882    }
883
884    if (level == -1) {
885        GLsizei curr_width = width;
886        GLsizei curr_height = height;
887        GLsizei curr_depth = depth;
888        GLsizei curr_level = 0;
889
890        while (true) {
891            texrec->dims->widths[curr_level] = curr_width;
892            texrec->dims->heights[curr_level] = curr_height;
893            texrec->dims->depths[curr_level] = curr_depth;
894            if (curr_width >> 1 == 0 &&
895                curr_height >> 1 == 0 &&
896                ((target == GL_TEXTURE_3D && curr_depth == 0) ||
897                 true)) {
898                break;
899            }
900            curr_width = (curr_width >> 1) ? (curr_width >> 1) : 1;
901            curr_height = (curr_height >> 1) ? (curr_height >> 1) : 1;
902            if (target == GL_TEXTURE_3D) {
903                curr_depth = (curr_depth >> 1) ? (curr_depth >> 1) : 1;
904            }
905            curr_level++;
906        }
907
908    } else {
909        texrec->dims->widths[level] = width;
910        texrec->dims->heights[level] = height;
911        texrec->dims->depths[level] = depth;
912    }
913}
914
915void GLClientState::setBoundTextureSamples(GLenum target, GLsizei samples) {
916    GLuint texture = getBoundTexture(target);
917    TextureRec* texrec = getTextureRec(texture);
918    if (!texrec) return;
919    texrec->multisamples = samples;
920}
921
922void GLClientState::setBoundTextureImmutableFormat(GLenum target) {
923    GLuint texture = getBoundTexture(target);
924    TextureRec* texrec = getTextureRec(texture);
925    if (!texrec) return;
926    texrec->immutable = true;
927}
928
929bool GLClientState::isBoundTextureImmutableFormat(GLenum target) const {
930    GLuint texture = getBoundTexture(target);
931    TextureRec* texrec = getTextureRec(texture);
932    if (!texrec) return false;
933    return texrec->immutable;
934}
935
936GLuint GLClientState::getBoundTexture(GLenum target) const
937{
938    switch (target) {
939    case GL_TEXTURE_2D:
940        return m_tex.activeUnit->texture[TEXTURE_2D];
941    case GL_TEXTURE_EXTERNAL_OES:
942        return m_tex.activeUnit->texture[TEXTURE_EXTERNAL];
943    case GL_TEXTURE_CUBE_MAP:
944        return m_tex.activeUnit->texture[TEXTURE_CUBE_MAP];
945    case GL_TEXTURE_2D_ARRAY:
946        return m_tex.activeUnit->texture[TEXTURE_2D_ARRAY];
947    case GL_TEXTURE_3D:
948        return m_tex.activeUnit->texture[TEXTURE_3D];
949    case GL_TEXTURE_2D_MULTISAMPLE:
950        return m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE];
951    default:
952        return 0;
953    }
954}
955
956// BEGIN driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
957// (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
958
959static bool unreliableInternalFormat(GLenum internalformat) {
960    switch (internalformat) {
961    case GL_LUMINANCE:
962        return true;
963    default:
964        return false;
965    }
966}
967
968void GLClientState::writeCopyTexImageState
969    (GLenum target, GLint level, GLenum internalformat) {
970    if (unreliableInternalFormat(internalformat)) {
971        CubeMapDef entry;
972        entry.id = getBoundTexture(GL_TEXTURE_2D);
973        entry.target = target;
974        entry.level = level;
975        entry.internalformat = internalformat;
976        m_cubeMapDefs.insert(entry);
977    }
978}
979
980static GLenum identifyPositiveCubeMapComponent(GLenum target) {
981    switch (target) {
982    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
983        return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
984    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
985        return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
986    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
987        return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
988    default:
989        return 0;
990    }
991}
992
993GLenum GLClientState::copyTexImageNeededTarget
994    (GLenum target, GLint level, GLenum internalformat) {
995    if (unreliableInternalFormat(internalformat)) {
996        GLenum positiveComponent =
997            identifyPositiveCubeMapComponent(target);
998        if (positiveComponent) {
999            CubeMapDef query;
1000            query.id = getBoundTexture(GL_TEXTURE_2D);
1001            query.target = positiveComponent;
1002            query.level = level;
1003            query.internalformat = internalformat;
1004            if (m_cubeMapDefs.find(query) ==
1005                m_cubeMapDefs.end()) {
1006                return positiveComponent;
1007            }
1008        }
1009    }
1010    return 0;
1011}
1012
1013GLenum GLClientState::copyTexImageLuminanceCubeMapAMDWorkaround
1014    (GLenum target, GLint level, GLenum internalformat) {
1015    writeCopyTexImageState(target, level, internalformat);
1016    return copyTexImageNeededTarget(target, level, internalformat);
1017}
1018
1019// (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
1020// END driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
1021
1022void GLClientState::deleteTextures(GLsizei n, const GLuint* textures)
1023{
1024    // Updating the textures array could be made more efficient when deleting
1025    // several textures:
1026    // - compacting the array could be done in a single pass once the deleted
1027    //   textures are marked, or
1028    // - could swap deleted textures to the end and re-sort.
1029    TextureRec* texrec;
1030    for (const GLuint* texture = textures; texture != textures + n; texture++) {
1031        texrec = getTextureRec(*texture);
1032        if (texrec && texrec->dims) {
1033            delete texrec->dims;
1034        }
1035        if (texrec) {
1036            m_tex.textureRecs->erase(*texture);
1037            delete texrec;
1038            for (TextureUnit* unit = m_tex.unit;
1039                 unit != m_tex.unit + MAX_TEXTURE_UNITS;
1040                 unit++)
1041            {
1042                if (unit->texture[TEXTURE_2D] == *texture) {
1043                    unit->texture[TEXTURE_2D] = 0;
1044                } else if (unit->texture[TEXTURE_EXTERNAL] == *texture) {
1045                    unit->texture[TEXTURE_EXTERNAL] = 0;
1046                }
1047            }
1048        }
1049    }
1050}
1051
1052// RBO//////////////////////////////////////////////////////////////////////////
1053
1054void GLClientState::addFreshRenderbuffer(GLuint name) {
1055    // if underlying opengl says these are fresh names,
1056    // but we are keeping a stale one, reset it.
1057    RboProps props;
1058    props.target = GL_RENDERBUFFER;
1059    props.name = name;
1060    props.format = GL_NONE;
1061    props.multisamples = 0;
1062    props.previouslyBound = false;
1063
1064    if (usedRenderbufferName(name)) {
1065        mRboState.rboData[getRboIndex(name)] = props;
1066    } else {
1067        mRboState.rboData.push_back(props);
1068    }
1069}
1070
1071void GLClientState::addRenderbuffers(GLsizei n, GLuint* renderbuffers) {
1072    for (size_t i = 0; i < n; i++) {
1073        addFreshRenderbuffer(renderbuffers[i]);
1074    }
1075}
1076
1077size_t GLClientState::getRboIndex(GLuint name) const {
1078    for (size_t i = 0; i < mRboState.rboData.size(); i++) {
1079        if (mRboState.rboData[i].name == name) {
1080            return i;
1081        }
1082    }
1083    return -1;
1084}
1085
1086void GLClientState::removeRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
1087    size_t bound_rbo_idx = getRboIndex(boundRboProps_const().name);
1088
1089    std::vector<GLuint> to_remove;
1090    for (size_t i = 0; i < n; i++) {
1091        if (renderbuffers[i] != 0) { // Never remove the zero rb.
1092            to_remove.push_back(getRboIndex(renderbuffers[i]));
1093        }
1094    }
1095
1096    for (size_t i = 0; i < to_remove.size(); i++) {
1097        mRboState.rboData[to_remove[i]] = mRboState.rboData.back();
1098        mRboState.rboData.pop_back();
1099    }
1100
1101    // If we just deleted the currently bound rb,
1102    // bind the zero rb
1103    if (getRboIndex(boundRboProps_const().name) != bound_rbo_idx) {
1104        bindRenderbuffer(GL_RENDERBUFFER, 0);
1105    }
1106}
1107
1108bool GLClientState::usedRenderbufferName(GLuint name) const {
1109    for (size_t i = 0; i < mRboState.rboData.size(); i++) {
1110        if (mRboState.rboData[i].name == name) {
1111            return true;
1112        }
1113    }
1114    return false;
1115}
1116
1117void GLClientState::setBoundRenderbufferIndex() {
1118    for (size_t i = 0; i < mRboState.rboData.size(); i++) {
1119        if (mRboState.rboData[i].name == mRboState.boundRenderbuffer) {
1120            mRboState.boundRenderbufferIndex = i;
1121            break;
1122        }
1123    }
1124}
1125
1126RboProps& GLClientState::boundRboProps() {
1127    return mRboState.rboData[mRboState.boundRenderbufferIndex];
1128}
1129
1130const RboProps& GLClientState::boundRboProps_const() const {
1131    return mRboState.rboData[mRboState.boundRenderbufferIndex];
1132}
1133
1134void GLClientState::bindRenderbuffer(GLenum target, GLuint name) {
1135    // If unused, add it.
1136    if (!usedRenderbufferName(name)) {
1137        addFreshRenderbuffer(name);
1138    }
1139    mRboState.boundRenderbuffer = name;
1140    setBoundRenderbufferIndex();
1141    boundRboProps().target = target;
1142    boundRboProps().previouslyBound = true;
1143}
1144
1145GLuint GLClientState::boundRenderbuffer() const {
1146    return boundRboProps_const().name;
1147}
1148
1149void GLClientState::setBoundRenderbufferFormat(GLenum format) {
1150    boundRboProps().format = format;
1151}
1152
1153void GLClientState::setBoundRenderbufferSamples(GLsizei samples) {
1154    boundRboProps().multisamples = samples;
1155}
1156
1157// FBO//////////////////////////////////////////////////////////////////////////
1158
1159// Format querying
1160
1161GLenum GLClientState::queryRboFormat(GLuint rbo_name) const {
1162    return mRboState.rboData[getRboIndex(rbo_name)].format;
1163}
1164
1165GLsizei GLClientState::queryRboSamples(GLuint rbo_name) const {
1166    return mRboState.rboData[getRboIndex(rbo_name)].multisamples;
1167}
1168
1169GLint GLClientState::queryTexInternalFormat(GLuint tex_name) const {
1170    TextureRec* texrec = getTextureRec(tex_name);
1171    if (!texrec) return -1;
1172    return texrec->internalformat;
1173}
1174
1175GLsizei GLClientState::queryTexWidth(GLsizei level, GLuint tex_name) const {
1176    TextureRec* texrec = getTextureRec(tex_name);
1177    if (!texrec) {
1178        return 0;
1179    }
1180    return texrec->dims->widths[level];
1181}
1182
1183GLsizei GLClientState::queryTexHeight(GLsizei level, GLuint tex_name) const {
1184    TextureRec* texrec = getTextureRec(tex_name);
1185    if (!texrec) return 0;
1186    return texrec->dims->heights[level];
1187}
1188
1189GLsizei GLClientState::queryTexDepth(GLsizei level, GLuint tex_name) const {
1190    TextureRec* texrec = getTextureRec(tex_name);
1191    if (!texrec) return 0;
1192    return texrec->dims->depths[level];
1193}
1194
1195bool GLClientState::queryTexEGLImageBacked(GLuint tex_name) const {
1196    TextureRec* texrec = getTextureRec(tex_name);
1197    if (!texrec) return false;
1198    return texrec->boundEGLImage;
1199}
1200
1201GLenum GLClientState::queryTexFormat(GLuint tex_name) const {
1202    TextureRec* texrec = getTextureRec(tex_name);
1203    if (!texrec) return -1;
1204    return texrec->format;
1205}
1206
1207GLenum GLClientState::queryTexType(GLuint tex_name) const {
1208    TextureRec* texrec = getTextureRec(tex_name);
1209    if (!texrec) return -1;
1210    return texrec->type;
1211}
1212
1213GLsizei GLClientState::queryTexSamples(GLuint tex_name) const {
1214    TextureRec* texrec = getTextureRec(tex_name);
1215    if (!texrec) return 0;
1216    return texrec->multisamples;
1217}
1218
1219GLenum GLClientState::queryTexLastBoundTarget(GLuint tex_name) const {
1220    TextureRec* texrec = getTextureRec(tex_name);
1221    if (!texrec) return GL_NONE;
1222    return texrec->target;
1223}
1224
1225void GLClientState::getBoundFramebufferFormat(
1226        GLenum target,
1227        GLenum attachment, FboFormatInfo* res_info) const {
1228    const FboProps& props = boundFboProps_const(target);
1229
1230    res_info->type = FBO_ATTACHMENT_NONE;
1231    res_info->rb_format = GL_NONE;
1232    res_info->rb_multisamples = 0;
1233    res_info->tex_internalformat = -1;
1234    res_info->tex_format = GL_NONE;
1235    res_info->tex_type = GL_NONE;
1236    res_info->tex_multisamples = 0;
1237
1238    int colorAttachmentIndex =
1239        glUtilsColorAttachmentIndex(attachment);
1240
1241    if (colorAttachmentIndex != -1) {
1242        if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
1243            res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1244            res_info->rb_format =
1245                queryRboFormat(
1246                        props.colorAttachmenti_rbos[colorAttachmentIndex]);
1247            res_info->rb_multisamples =
1248                queryRboSamples(
1249                        props.colorAttachmenti_rbos[colorAttachmentIndex]);
1250        } else if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
1251            res_info->type = FBO_ATTACHMENT_TEXTURE;
1252            res_info->tex_internalformat =
1253                queryTexInternalFormat(
1254                        props.colorAttachmenti_textures[colorAttachmentIndex]);
1255            res_info->tex_format =
1256                queryTexFormat(
1257                        props.colorAttachmenti_textures[colorAttachmentIndex]);
1258            res_info->tex_type =
1259                queryTexType(props.colorAttachmenti_textures[colorAttachmentIndex]);
1260            res_info->tex_multisamples =
1261                queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
1262        } else {
1263            res_info->type = FBO_ATTACHMENT_NONE;
1264        }
1265    }
1266
1267    switch (attachment) {
1268    case GL_DEPTH_ATTACHMENT:
1269        if (props.depthAttachment_hasRbo) {
1270            res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1271            res_info->rb_format = queryRboFormat(props.depthAttachment_rbo);
1272            res_info->rb_multisamples =
1273                queryRboSamples(
1274                        props.colorAttachmenti_rbos[colorAttachmentIndex]);
1275        } else if (props.depthAttachment_hasTexObj) {
1276            res_info->type = FBO_ATTACHMENT_TEXTURE;
1277            res_info->tex_internalformat = queryTexInternalFormat(props.depthAttachment_texture);
1278            res_info->tex_format = queryTexFormat(props.depthAttachment_texture);
1279            res_info->tex_type = queryTexType(props.depthAttachment_texture);
1280            res_info->tex_multisamples =
1281                queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
1282        } else {
1283            res_info->type = FBO_ATTACHMENT_NONE;
1284        }
1285        break;
1286    case GL_STENCIL_ATTACHMENT:
1287        if (props.stencilAttachment_hasRbo) {
1288            res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1289            res_info->rb_format = queryRboFormat(props.stencilAttachment_rbo);
1290            res_info->rb_multisamples =
1291                queryRboSamples(
1292                        props.colorAttachmenti_rbos[colorAttachmentIndex]);
1293        } else if (props.stencilAttachment_hasTexObj) {
1294            res_info->type = FBO_ATTACHMENT_TEXTURE;
1295            res_info->tex_internalformat = queryTexInternalFormat(props.stencilAttachment_texture);
1296            res_info->tex_format = queryTexFormat(props.stencilAttachment_texture);
1297            res_info->tex_type = queryTexType(props.stencilAttachment_texture);
1298            res_info->tex_multisamples =
1299                queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
1300        } else {
1301            res_info->type = FBO_ATTACHMENT_NONE;
1302        }
1303        break;
1304    case GL_DEPTH_STENCIL_ATTACHMENT:
1305        if (props.depthstencilAttachment_hasRbo) {
1306            res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1307            res_info->rb_format = queryRboFormat(props.depthstencilAttachment_rbo);
1308            res_info->rb_multisamples =
1309                queryRboSamples(
1310                        props.colorAttachmenti_rbos[colorAttachmentIndex]);
1311        } else if (props.depthstencilAttachment_hasTexObj) {
1312            res_info->type = FBO_ATTACHMENT_TEXTURE;
1313            res_info->tex_internalformat = queryTexInternalFormat(props.depthstencilAttachment_texture);
1314            res_info->tex_format = queryTexFormat(props.depthstencilAttachment_texture);
1315            res_info->tex_type = queryTexType(props.depthstencilAttachment_texture);
1316            res_info->tex_multisamples =
1317                queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
1318        } else {
1319            res_info->type = FBO_ATTACHMENT_NONE;
1320        }
1321        break;
1322    }
1323}
1324
1325FboAttachmentType GLClientState::getBoundFramebufferAttachmentType(GLenum target, GLenum attachment) const {
1326    FboFormatInfo info;
1327    getBoundFramebufferFormat(target, attachment, &info);
1328    return info.type;
1329}
1330
1331
1332int GLClientState::getMaxColorAttachments() const {
1333    return m_max_color_attachments;
1334}
1335
1336int GLClientState::getMaxDrawBuffers() const {
1337    return m_max_draw_buffers;
1338}
1339
1340void GLClientState::addFreshFramebuffer(GLuint name) {
1341    FboProps props;
1342    props.name = name;
1343    props.previouslyBound = false;
1344
1345    props.colorAttachmenti_textures.resize(m_max_color_attachments, 0);
1346    props.depthAttachment_texture = 0;
1347    props.stencilAttachment_texture = 0;
1348    props.depthstencilAttachment_texture = 0;
1349
1350    props.colorAttachmenti_hasTex.resize(m_max_color_attachments, false);
1351    props.depthAttachment_hasTexObj = false;
1352    props.stencilAttachment_hasTexObj = false;
1353    props.depthstencilAttachment_hasTexObj = false;
1354
1355    props.colorAttachmenti_rbos.resize(m_max_color_attachments, 0);
1356    props.depthAttachment_rbo = 0;
1357    props.stencilAttachment_rbo = 0;
1358    props.depthstencilAttachment_rbo = 0;
1359
1360    props.colorAttachmenti_hasRbo.resize(m_max_color_attachments, false);
1361    props.depthAttachment_hasRbo = false;
1362    props.stencilAttachment_hasRbo = false;
1363    props.depthstencilAttachment_hasRbo = false;
1364    mFboState.fboData[name] = props;
1365}
1366
1367void GLClientState::addFramebuffers(GLsizei n, GLuint* framebuffers) {
1368    for (size_t i = 0; i < n; i++) {
1369        addFreshFramebuffer(framebuffers[i]);
1370    }
1371}
1372
1373void GLClientState::removeFramebuffers(GLsizei n, const GLuint* framebuffers) {
1374    for (size_t i = 0; i < n; i++) {
1375        if (framebuffers[i] != 0) { // Never remove the zero fb.
1376            if (framebuffers[i] == mFboState.boundDrawFramebuffer) {
1377                bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1378            }
1379            if (framebuffers[i] == mFboState.boundReadFramebuffer) {
1380                bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1381            }
1382            mFboState.fboData.erase(framebuffers[i]);
1383        }
1384    }
1385}
1386
1387bool GLClientState::usedFramebufferName(GLuint name) const {
1388    return mFboState.fboData.find(name) != mFboState.fboData.end();
1389}
1390
1391FboProps& GLClientState::boundFboProps(GLenum target) {
1392    switch (target) {
1393    case GL_DRAW_FRAMEBUFFER:
1394        return mFboState.fboData[mFboState.boundDrawFramebuffer];
1395    case GL_READ_FRAMEBUFFER:
1396        return mFboState.fboData[mFboState.boundReadFramebuffer];
1397    case GL_FRAMEBUFFER:
1398        return mFboState.fboData[mFboState.boundDrawFramebuffer];
1399    }
1400    return mFboState.fboData[mFboState.boundDrawFramebuffer];
1401}
1402
1403const FboProps& GLClientState::boundFboProps_const(GLenum target) const {
1404    switch (target) {
1405    case GL_DRAW_FRAMEBUFFER:
1406        return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
1407    case GL_READ_FRAMEBUFFER:
1408        return mFboState.fboData.find(mFboState.boundReadFramebuffer)->second;
1409    case GL_FRAMEBUFFER:
1410        return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
1411    }
1412    return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
1413}
1414
1415void GLClientState::bindFramebuffer(GLenum target, GLuint name) {
1416    // If unused, add it.
1417    if (!usedFramebufferName(name)) {
1418        addFreshFramebuffer(name);
1419    }
1420    switch (target) {
1421        case GL_DRAW_FRAMEBUFFER:
1422            mFboState.boundDrawFramebuffer = name;
1423            break;
1424        case GL_READ_FRAMEBUFFER:
1425            mFboState.boundReadFramebuffer = name;
1426            break;
1427        default: // case GL_FRAMEBUFFER:
1428            mFboState.boundDrawFramebuffer = name;
1429            mFboState.boundReadFramebuffer = name;
1430            break;
1431    }
1432    boundFboProps(target).previouslyBound = true;
1433}
1434
1435void GLClientState::setCheckFramebufferStatus(GLenum target, GLenum status) {
1436    switch (target) {
1437        case GL_DRAW_FRAMEBUFFER:
1438            mFboState.drawFboCheckStatus = status;
1439            break;
1440        case GL_READ_FRAMEBUFFER:
1441            mFboState.readFboCheckStatus = status;
1442            break;
1443        case GL_FRAMEBUFFER:
1444            mFboState.drawFboCheckStatus = status;
1445            break;
1446    }
1447}
1448
1449GLenum GLClientState::getCheckFramebufferStatus(GLenum target) const {
1450    switch (target) {
1451    case GL_DRAW_FRAMEBUFFER:
1452        return mFboState.drawFboCheckStatus;
1453    case GL_READ_FRAMEBUFFER:
1454        return mFboState.readFboCheckStatus;
1455    case GL_FRAMEBUFFER:
1456        return mFboState.drawFboCheckStatus;
1457    }
1458    return mFboState.drawFboCheckStatus;
1459}
1460
1461GLuint GLClientState::boundFramebuffer(GLenum target) const {
1462    return boundFboProps_const(target).name;
1463}
1464
1465// Texture objects for FBOs/////////////////////////////////////////////////////
1466
1467void GLClientState::attachTextureObject(
1468        GLenum target,
1469        GLenum attachment, GLuint texture) {
1470
1471    int colorAttachmentIndex =
1472        glUtilsColorAttachmentIndex(attachment);
1473
1474    if (colorAttachmentIndex != -1) {
1475        boundFboProps(target).colorAttachmenti_textures[colorAttachmentIndex] = texture;
1476        boundFboProps(target).colorAttachmenti_hasTex[colorAttachmentIndex] = true;
1477    }
1478
1479    switch (attachment) {
1480    case GL_DEPTH_ATTACHMENT:
1481        boundFboProps(target).depthAttachment_texture = texture;
1482        boundFboProps(target).depthAttachment_hasTexObj = true;
1483        break;
1484    case GL_STENCIL_ATTACHMENT:
1485        boundFboProps(target).stencilAttachment_texture = texture;
1486        boundFboProps(target).stencilAttachment_hasTexObj = true;
1487        break;
1488    case GL_DEPTH_STENCIL_ATTACHMENT:
1489        boundFboProps(target).depthstencilAttachment_texture = texture;
1490        boundFboProps(target).depthstencilAttachment_hasTexObj = true;
1491        boundFboProps(target).stencilAttachment_texture = texture;
1492        boundFboProps(target).stencilAttachment_hasTexObj = true;
1493        boundFboProps(target).depthAttachment_texture = texture;
1494        boundFboProps(target).depthAttachment_hasTexObj = true;
1495        break;
1496    }
1497}
1498
1499GLuint GLClientState::getFboAttachmentTextureId(GLenum target, GLenum attachment) const {
1500    GLuint res = 0; // conservative
1501
1502    int colorAttachmentIndex =
1503        glUtilsColorAttachmentIndex(attachment);
1504
1505    if (colorAttachmentIndex != -1) {
1506        res = boundFboProps_const(target).colorAttachmenti_textures[colorAttachmentIndex];
1507    }
1508
1509    switch (attachment) {
1510    case GL_DEPTH_ATTACHMENT:
1511        res = boundFboProps_const(target).depthAttachment_texture;
1512        break;
1513    case GL_STENCIL_ATTACHMENT:
1514        res = boundFboProps_const(target).stencilAttachment_texture;
1515        break;
1516    case GL_DEPTH_STENCIL_ATTACHMENT:
1517        res = boundFboProps_const(target).depthstencilAttachment_texture;
1518        break;
1519    }
1520    return res;
1521}
1522
1523// RBOs for FBOs////////////////////////////////////////////////////////////////
1524
1525void GLClientState::detachRbo(GLuint renderbuffer) {
1526    for (int i = 0; i < m_max_color_attachments; i++) {
1527        detachRboFromFbo(GL_DRAW_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
1528        detachRboFromFbo(GL_READ_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
1529    }
1530
1531    detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
1532    detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
1533
1534    detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
1535    detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
1536
1537    detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
1538    detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
1539}
1540
1541void GLClientState::detachRboFromFbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
1542    int colorAttachmentIndex =
1543        glUtilsColorAttachmentIndex(attachment);
1544
1545    if (colorAttachmentIndex != -1) {
1546        if (boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] &&
1547            boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] == renderbuffer) {
1548            boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = 0;
1549            boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = false;
1550        }
1551    }
1552
1553    switch (attachment) {
1554    case GL_DEPTH_ATTACHMENT:
1555        if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
1556            boundFboProps(target).depthAttachment_hasRbo) {
1557            boundFboProps(target).depthAttachment_rbo = 0;
1558            boundFboProps(target).depthAttachment_hasRbo = false;
1559        }
1560        break;
1561    case GL_STENCIL_ATTACHMENT:
1562        if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
1563            boundFboProps(target).stencilAttachment_hasRbo) {
1564            boundFboProps(target).stencilAttachment_rbo = 0;
1565            boundFboProps(target).stencilAttachment_hasRbo = false;
1566        }
1567        break;
1568    case GL_DEPTH_STENCIL_ATTACHMENT:
1569        if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
1570            boundFboProps(target).depthAttachment_hasRbo) {
1571            boundFboProps(target).depthAttachment_rbo = 0;
1572            boundFboProps(target).depthAttachment_hasRbo = false;
1573        }
1574        if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
1575            boundFboProps(target).stencilAttachment_hasRbo) {
1576            boundFboProps(target).stencilAttachment_rbo = 0;
1577            boundFboProps(target).stencilAttachment_hasRbo = false;
1578        }
1579        if (boundFboProps(target).depthstencilAttachment_rbo == renderbuffer &&
1580            boundFboProps(target).depthstencilAttachment_hasRbo) {
1581            boundFboProps(target).depthstencilAttachment_rbo = 0;
1582            boundFboProps(target).depthstencilAttachment_hasRbo = false;
1583        }
1584        break;
1585    }
1586}
1587
1588void GLClientState::attachRbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
1589
1590    int colorAttachmentIndex =
1591        glUtilsColorAttachmentIndex(attachment);
1592
1593    if (colorAttachmentIndex != -1) {
1594        boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = renderbuffer;
1595        boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = true;
1596    }
1597
1598    switch (attachment) {
1599    case GL_DEPTH_ATTACHMENT:
1600        boundFboProps(target).depthAttachment_rbo = renderbuffer;
1601        boundFboProps(target).depthAttachment_hasRbo = true;
1602        break;
1603    case GL_STENCIL_ATTACHMENT:
1604        boundFboProps(target).stencilAttachment_rbo = renderbuffer;
1605        boundFboProps(target).stencilAttachment_hasRbo = true;
1606        break;
1607    case GL_DEPTH_STENCIL_ATTACHMENT:
1608        boundFboProps(target).depthAttachment_rbo = renderbuffer;
1609        boundFboProps(target).depthAttachment_hasRbo = true;
1610        boundFboProps(target).stencilAttachment_rbo = renderbuffer;
1611        boundFboProps(target).stencilAttachment_hasRbo = true;
1612        boundFboProps(target).depthstencilAttachment_rbo = renderbuffer;
1613        boundFboProps(target).depthstencilAttachment_hasRbo = true;
1614        break;
1615    }
1616}
1617
1618GLuint GLClientState::getFboAttachmentRboId(GLenum target, GLenum attachment) const {
1619    GLuint res = 0; // conservative
1620
1621    int colorAttachmentIndex =
1622        glUtilsColorAttachmentIndex(attachment);
1623
1624    if (colorAttachmentIndex != -1) {
1625        res = boundFboProps_const(target).colorAttachmenti_rbos[colorAttachmentIndex];
1626    }
1627
1628    switch (attachment) {
1629    case GL_DEPTH_ATTACHMENT:
1630        res = boundFboProps_const(target).depthAttachment_rbo;
1631        break;
1632    case GL_STENCIL_ATTACHMENT:
1633        res = boundFboProps_const(target).stencilAttachment_rbo;
1634        break;
1635    case GL_DEPTH_STENCIL_ATTACHMENT:
1636        res = boundFboProps_const(target).depthstencilAttachment_rbo;
1637        break;
1638    }
1639    return res;
1640}
1641
1642bool GLClientState::attachmentHasObject(GLenum target, GLenum attachment) const {
1643    bool res = true; // liberal
1644
1645    int colorAttachmentIndex =
1646        glUtilsColorAttachmentIndex(attachment);
1647
1648    if (colorAttachmentIndex != -1) {
1649        res = boundFboProps_const(target).colorAttachmenti_hasTex[colorAttachmentIndex] ||
1650              boundFboProps_const(target).colorAttachmenti_hasRbo[colorAttachmentIndex];
1651    }
1652
1653    switch (attachment) {
1654    case GL_DEPTH_ATTACHMENT:
1655        res = (boundFboProps_const(target).depthAttachment_hasTexObj) ||
1656              (boundFboProps_const(target).depthAttachment_hasRbo);
1657        break;
1658    case GL_STENCIL_ATTACHMENT:
1659        res = (boundFboProps_const(target).stencilAttachment_hasTexObj) ||
1660              (boundFboProps_const(target).stencilAttachment_hasRbo);
1661        break;
1662    case GL_DEPTH_STENCIL_ATTACHMENT:
1663        res = (boundFboProps_const(target).depthstencilAttachment_hasTexObj) ||
1664              (boundFboProps_const(target).depthstencilAttachment_hasRbo);
1665        break;
1666    }
1667    return res;
1668}
1669
1670GLuint GLClientState::objectOfAttachment(GLenum target, GLenum attachment) const {
1671    const FboProps& props = boundFboProps_const(target);
1672
1673    int colorAttachmentIndex =
1674        glUtilsColorAttachmentIndex(attachment);
1675
1676    if (colorAttachmentIndex != -1) {
1677        if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
1678            return props.colorAttachmenti_textures[colorAttachmentIndex];
1679        } else if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
1680            return props.colorAttachmenti_rbos[colorAttachmentIndex];
1681        } else {
1682            return 0;
1683        }
1684    }
1685
1686    switch (attachment) {
1687    case GL_DEPTH_ATTACHMENT:
1688        if (props.depthAttachment_hasTexObj) {
1689            return props.depthAttachment_texture;
1690        } else if (props.depthAttachment_hasRbo) {
1691            return props.depthAttachment_rbo;
1692        } else {
1693            return 0;
1694        }
1695        break;
1696    case GL_STENCIL_ATTACHMENT:
1697        if (props.stencilAttachment_hasTexObj) {
1698            return props.stencilAttachment_texture;
1699        } else if (props.stencilAttachment_hasRbo) {
1700            return props.stencilAttachment_rbo;
1701        } else {
1702            return 0;
1703        }
1704    case GL_DEPTH_STENCIL_ATTACHMENT:
1705        if (props.depthstencilAttachment_hasTexObj) {
1706            return props.depthstencilAttachment_texture;
1707        } else if (props.depthstencilAttachment_hasRbo) {
1708            return props.depthstencilAttachment_rbo;
1709        } else {
1710            return 0;
1711        }
1712        break;
1713    }
1714    return 0;
1715}
1716
1717void GLClientState::setTransformFeedbackActiveUnpaused(bool activeUnpaused) {
1718    m_transformFeedbackActiveUnpaused = activeUnpaused;
1719}
1720
1721bool GLClientState::getTransformFeedbackActiveUnpaused() const {
1722    return m_transformFeedbackActiveUnpaused;
1723}
1724
1725void GLClientState::setTextureData(SharedTextureDataMap* sharedTexData) {
1726    m_tex.textureRecs = sharedTexData;
1727}
1728
1729void GLClientState::fromMakeCurrent() {
1730    if (mFboState.fboData.find(0) == mFboState.fboData.end()) {
1731        addFreshFramebuffer(0);
1732    }
1733    FboProps& default_fb_props = mFboState.fboData[0];
1734    default_fb_props.colorAttachmenti_hasRbo[0] = true;
1735    default_fb_props.depthAttachment_hasRbo = true;
1736    default_fb_props.stencilAttachment_hasRbo = true;
1737    default_fb_props.depthstencilAttachment_hasRbo = true;
1738}
1739
1740void GLClientState::initFromCaps(
1741    int max_transform_feedback_separate_attribs,
1742    int max_uniform_buffer_bindings,
1743    int max_atomic_counter_buffer_bindings,
1744    int max_shader_storage_buffer_bindings,
1745    int max_vertex_attrib_bindings,
1746    int max_color_attachments,
1747    int max_draw_buffers) {
1748
1749    m_max_vertex_attrib_bindings = max_vertex_attrib_bindings;
1750
1751    if (m_glesMajorVersion >= 3) {
1752        m_max_transform_feedback_separate_attribs = max_transform_feedback_separate_attribs;
1753        m_max_uniform_buffer_bindings = max_uniform_buffer_bindings;
1754        m_max_atomic_counter_buffer_bindings = max_atomic_counter_buffer_bindings;
1755        m_max_shader_storage_buffer_bindings = max_shader_storage_buffer_bindings;
1756
1757        if (m_max_transform_feedback_separate_attribs)
1758            m_indexedTransformFeedbackBuffers.resize(m_max_transform_feedback_separate_attribs);
1759        if (m_max_uniform_buffer_bindings)
1760            m_indexedUniformBuffers.resize(m_max_uniform_buffer_bindings);
1761        if (m_max_atomic_counter_buffer_bindings)
1762            m_indexedAtomicCounterBuffers.resize(m_max_atomic_counter_buffer_bindings);
1763        if (m_max_shader_storage_buffer_bindings)
1764            m_indexedShaderStorageBuffers.resize(m_max_shader_storage_buffer_bindings);
1765
1766        BufferBinding buf0Binding;
1767        buf0Binding.buffer = 0;
1768        buf0Binding.offset = 0;
1769        buf0Binding.size = 0;
1770        buf0Binding.stride = 0;
1771        buf0Binding.effectiveStride = 0;
1772
1773        for (size_t i = 0; i < m_indexedTransformFeedbackBuffers.size(); ++i)
1774            m_indexedTransformFeedbackBuffers[i] = buf0Binding;
1775        for (size_t i = 0; i < m_indexedUniformBuffers.size(); ++i)
1776            m_indexedUniformBuffers[i] = buf0Binding;
1777        for (size_t i = 0; i < m_indexedAtomicCounterBuffers.size(); ++i)
1778            m_indexedAtomicCounterBuffers[i] = buf0Binding;
1779        for (size_t i = 0; i < m_indexedShaderStorageBuffers.size(); ++i)
1780            m_indexedShaderStorageBuffers[i] = buf0Binding;
1781    }
1782
1783    m_max_color_attachments = max_color_attachments;
1784    m_max_draw_buffers = max_draw_buffers;
1785
1786    addFreshRenderbuffer(0);
1787    addFreshFramebuffer(0);
1788
1789    m_initialized = true;
1790}
1791
1792bool GLClientState::needsInitFromCaps() const {
1793    return !m_initialized;
1794}
1795