OSDN Git Service

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