• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "GLClientState.h"
17 #include "GLESTextureUtils.h"
18 #include "ErrorLog.h"
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "glUtils.h"
23 
24 #if PLATFORM_SDK_VERSION < 26
25 #include <cutils/log.h>
26 #else
27 #include <log/log.h>
28 #endif
29 
30 #ifndef MAX
31 #define MAX(a, b) ((a) < (b) ? (b) : (a))
32 #endif
33 
34 // Don't include these in the .h file, or we get weird compile errors.
35 #include <GLES2/gl2ext.h>
36 #include <GLES3/gl3.h>
37 #include <GLES3/gl31.h>
38 
39 using android::base::guest::AutoReadLock;
40 using android::base::guest::AutoWriteLock;
41 
init()42 void GLClientState::init() {
43     m_initialized = false;
44 
45     state_GL_STENCIL_TEST = false;
46     state_GL_STENCIL_FUNC = GL_ALWAYS;
47     state_GL_STENCIL_VALUE_MASK = ~(0);
48     state_GL_STENCIL_REF = 0;
49     state_GL_STENCIL_FAIL = GL_KEEP;
50     state_GL_STENCIL_PASS_DEPTH_FAIL = GL_KEEP;
51     state_GL_STENCIL_PASS_DEPTH_PASS = GL_KEEP;
52     state_GL_STENCIL_BACK_FUNC = GL_ALWAYS;
53     state_GL_STENCIL_BACK_VALUE_MASK = ~(0);
54     state_GL_STENCIL_BACK_REF = 0;
55     state_GL_STENCIL_BACK_FAIL = GL_KEEP;
56     state_GL_STENCIL_BACK_PASS_DEPTH_FAIL = GL_KEEP;
57     state_GL_STENCIL_BACK_PASS_DEPTH_PASS = GL_KEEP;
58     state_GL_STENCIL_WRITEMASK = ~(0);
59     state_GL_STENCIL_BACK_WRITEMASK = ~(0);
60     state_GL_STENCIL_CLEAR_VALUE = 0;
61 
62 
63     m_arrayBuffer = 0;
64     m_arrayBuffer_lastEncode = 0;
65 
66     m_attribEnableCache = 0;
67     m_vaoAttribBindingCacheInvalid = 0xffff;
68     m_vaoAttribBindingHasClientArrayCache = 0;
69     m_vaoAttribBindingHasVboCache = 0;
70     m_noClientArraysCache = 0;
71 
72     addVertexArrayObject(0);
73     setVertexArrayObject(0);
74     // init gl constans;
75     m_currVaoState[VERTEX_LOCATION].glConst = GL_VERTEX_ARRAY;
76     m_currVaoState[NORMAL_LOCATION].glConst = GL_NORMAL_ARRAY;
77     m_currVaoState[COLOR_LOCATION].glConst = GL_COLOR_ARRAY;
78     m_currVaoState[POINTSIZE_LOCATION].glConst = GL_POINT_SIZE_ARRAY_OES;
79     m_currVaoState[TEXCOORD0_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
80     m_currVaoState[TEXCOORD1_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
81     m_currVaoState[TEXCOORD2_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
82     m_currVaoState[TEXCOORD3_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
83     m_currVaoState[TEXCOORD4_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
84     m_currVaoState[TEXCOORD5_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
85     m_currVaoState[TEXCOORD6_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
86     m_currVaoState[TEXCOORD7_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
87     m_currVaoState[MATRIXINDEX_LOCATION].glConst = GL_MATRIX_INDEX_ARRAY_OES;
88     m_currVaoState[WEIGHT_LOCATION].glConst = GL_WEIGHT_ARRAY_OES;
89 
90     m_copyReadBuffer = 0;
91     m_copyWriteBuffer = 0;
92     m_pixelPackBuffer = 0;
93     m_pixelUnpackBuffer = 0;
94     m_transformFeedbackBuffer = 0;
95     m_uniformBuffer = 0;
96     m_atomicCounterBuffer = 0;
97     m_dispatchIndirectBuffer = 0;
98     m_drawIndirectBuffer = 0;
99     m_shaderStorageBuffer = 0;
100     m_textureBuffer = 0;
101 
102     m_transformFeedbackActive = false;
103     m_transformFeedbackUnpaused = false;
104     m_transformFeedbackVaryingsCountForLinking = 0;
105 
106     m_activeTexture = 0;
107     m_currentProgram = 0;
108     m_currentShaderProgram = 0;
109 
110     m_pixelStore.unpack_alignment = 4;
111     m_pixelStore.pack_alignment = 4;
112 
113     m_pixelStore.unpack_row_length = 0;
114     m_pixelStore.unpack_image_height = 0;
115     m_pixelStore.unpack_skip_pixels = 0;
116     m_pixelStore.unpack_skip_rows = 0;
117     m_pixelStore.unpack_skip_images = 0;
118 
119     m_pixelStore.pack_row_length = 0;
120     m_pixelStore.pack_skip_pixels = 0;
121     m_pixelStore.pack_skip_rows = 0;
122 
123     memset(m_tex.unit, 0, sizeof(m_tex.unit));
124     m_tex.activeUnit = &m_tex.unit[0];
125     m_tex.textureRecs = NULL;
126 
127     mRboState.boundRenderbuffer = nullptr;
128 
129     mFboState.boundDrawFramebuffer = 0;
130     mFboState.boundReadFramebuffer = 0;
131     mFboState.drawFboCheckStatus = GL_NONE;
132     mFboState.readFboCheckStatus = GL_NONE;
133 
134     m_extensions_set = false;
135 
136 #ifdef GFXSTREAM
137     // The default transform feedback buffer object
138     // The default sampler object
139     GLuint defaultId = 0;
140     setExistence(ObjectType::TransformFeedback, true, 1, &defaultId);
141 
142     mBoundTransformFeedbackValidity.id = 0;
143     mBoundTransformFeedbackValidity.valid = true;
144 
145     // query must take id that was created via glGenQueries
146     mBoundQueryValidity_AnySamplesPassed.valid = false;
147     mBoundQueryValidity_AnySamplesPassedConservative.valid = false;
148     mBoundQueryValidity_TransformFeedbackPrimitivesWritten.valid = false;
149 #endif
150 }
151 
GLClientState()152 GLClientState::GLClientState()
153 {
154     init();
155 }
156 
GLClientState(int majorVersion,int minorVersion)157 GLClientState::GLClientState(int majorVersion, int minorVersion) :
158     m_glesMajorVersion(majorVersion),
159     m_glesMinorVersion(minorVersion) {
160     init();
161 }
162 
~GLClientState()163 GLClientState::~GLClientState()
164 {
165 }
166 
enable(int location,int state)167 void GLClientState::enable(int location, int state)
168 {
169     m_currVaoState[location].enableDirty |= (state != m_currVaoState[location].enabled);
170     m_currVaoState[location].enabled = state;
171     if (state) {
172         m_attribEnableCache |= (1 << location);
173         m_noClientArraysCache = 0;
174     } else {
175         m_attribEnableCache &= ~(1 << location);
176     }
177 }
178 
setVertexAttribState(int location,int size,GLenum type,GLboolean normalized,GLsizei stride,const void * data,bool isInt)179 void GLClientState::setVertexAttribState(int location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data, bool isInt)
180 {
181     m_currVaoState[location].size = size;
182     m_currVaoState[location].type = type;
183     m_currVaoState[location].stride = stride;
184     m_currVaoState[location].data = (void*)data;
185     m_currVaoState[location].bufferObject = m_arrayBuffer;
186     m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
187     switch (type) {
188         case GL_INT_2_10_10_10_REV:
189         case GL_UNSIGNED_INT_2_10_10_10_REV:
190             m_currVaoState[location].elementSize =
191                 m_currVaoState[location].elementSize / 4;
192             break;
193         default:
194             break;
195     }
196     m_currVaoState[location].normalized = normalized;
197     m_currVaoState[location].isInt = isInt;
198 }
199 
setVertexBindingDivisor(int bindingindex,GLuint divisor)200 void GLClientState::setVertexBindingDivisor(int bindingindex, GLuint divisor) {
201     m_currVaoState.bufferBinding(bindingindex).divisor = divisor;
202 }
203 
getCurrAttributeBindingInfo(int attribindex)204 const GLClientState::BufferBinding& GLClientState::getCurrAttributeBindingInfo(int attribindex) {
205     return m_currVaoState.bufferBindings_const()[m_currVaoState[attribindex].bindingindex];
206 }
207 
setVertexAttribBinding(int attribindex,int bindingindex)208 void GLClientState::setVertexAttribBinding(int attribindex, int bindingindex) {
209     m_currVaoState[attribindex].bindingindex = bindingindex;
210     m_currVaoState.bufferBinding(bindingindex).vertexAttribLoc = attribindex;
211     m_vaoAttribBindingCacheInvalid |= (1 << attribindex);
212     m_noClientArraysCache = 0;
213 }
214 
setVertexAttribFormat(int location,int size,GLenum type,GLboolean normalized,GLuint reloffset,bool isInt)215 void GLClientState::setVertexAttribFormat(int location, int size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt) {
216     m_currVaoState[location].size = size;
217     m_currVaoState[location].type = type;
218     m_currVaoState[location].normalized = normalized;
219     m_currVaoState[location].reloffset = reloffset;
220     m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
221     switch (type) {
222         case GL_INT_2_10_10_10_REV:
223         case GL_UNSIGNED_INT_2_10_10_10_REV:
224             m_currVaoState[location].elementSize =
225                 m_currVaoState[location].elementSize / 4;
226             break;
227         default:
228             break;
229     }
230     m_currVaoState[location].isInt = isInt;
231 }
232 
addVertexArrayObjects(GLsizei n,GLuint * arrays)233 void GLClientState::addVertexArrayObjects(GLsizei n, GLuint* arrays) {
234     for (GLsizei i = 0; i < n; i++) {
235         addVertexArrayObject(arrays[i]);
236     }
237 }
238 
removeVertexArrayObjects(GLsizei n,const GLuint * arrays)239 void GLClientState::removeVertexArrayObjects(GLsizei n, const GLuint* arrays) {
240     for (GLsizei i = 0; i < n; i++) {
241         if (arrays[i] && m_currVaoState.vaoId() == arrays[i]) {
242             setVertexArrayObject(0);
243         }
244         removeVertexArrayObject(arrays[i]);
245     }
246 }
247 
addVertexArrayObject(GLuint name)248 void GLClientState::addVertexArrayObject(GLuint name) {
249     if (m_vaoMap.find(name) !=
250         m_vaoMap.end()) {
251         ALOGE("%s: ERROR: %u already part of current VAO state!",
252               __FUNCTION__, name);
253         return;
254     }
255 
256     m_vaoMap.insert(
257             VAOStateMap::value_type(
258                 name,
259                 VAOState(0, CODEC_MAX_VERTEX_ATTRIBUTES, CODEC_MAX_VERTEX_ATTRIBUTES)));
260     VertexAttribStateVector& attribState =
261         m_vaoMap.find(name)->second.attribState;
262     for (int i = 0; i < CODEC_MAX_VERTEX_ATTRIBUTES; i++) {
263         attribState[i].enabled = 0;
264         attribState[i].enableDirty = false;
265         attribState[i].data = 0;
266         attribState[i].reloffset = 0;
267         attribState[i].bindingindex = i;
268         attribState[i].divisor = 0;
269         attribState[i].size = 4; // 4 is the default size
270         attribState[i].type = GL_FLOAT; // GL_FLOAT is the default type
271     }
272 
273     VertexAttribBindingVector& bindingState =
274         m_vaoMap.find(name)->second.bindingState;
275     for (int i = 0; i < bindingState.size(); i++) {
276         bindingState[i].effectiveStride = 16;
277     }
278 }
279 
removeVertexArrayObject(GLuint name)280 void GLClientState::removeVertexArrayObject(GLuint name) {
281     if (name == 0) {
282         ALOGE("%s: ERROR: cannot delete VAO 0!",
283               __FUNCTION__);
284         return;
285     }
286     if (m_vaoMap.find(name) ==
287         m_vaoMap.end()) {
288         ALOGE("%s: ERROR: %u not found in VAO state!",
289               __FUNCTION__, name);
290         return;
291     }
292     m_vaoMap.erase(name);
293 }
294 
setVertexArrayObject(GLuint name)295 void GLClientState::setVertexArrayObject(GLuint name) {
296     if (m_vaoMap.find(name) ==
297         m_vaoMap.end()) {
298         ALOGE("%s: ERROR: %u not found in VAO state!",
299               __FUNCTION__, name);
300         return;
301     }
302 
303     if (name && m_currVaoState.vaoId() == name) {
304         ALOGV("%s: set vao to self, no-op (%u)",
305               __FUNCTION__, name);
306         return;
307     }
308 
309     m_currVaoState =
310         VAOStateRef(m_vaoMap.find(name));
311 }
312 
isVertexArrayObject(GLuint vao) const313 bool GLClientState::isVertexArrayObject(GLuint vao) const {
314     return m_vaoMap.find(vao) != m_vaoMap.end();
315 }
316 
getVBOUsage(bool * hasClientArrays,bool * hasVBOs)317 void GLClientState::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) {
318     uint8_t todo_count = 0;
319     uint8_t todo[CODEC_MAX_VERTEX_ATTRIBUTES];
320 
321     if (m_noClientArraysCache) {
322         *hasClientArrays = false;
323         *hasVBOs = true;
324         return;
325     }
326 
327     for (int i = 0; i < CODEC_MAX_VERTEX_ATTRIBUTES; i++) {
328         if ((1 << i) & (m_attribEnableCache)) {
329             if (!((1 << i) & m_vaoAttribBindingCacheInvalid)) {
330                 if ((1 << i) & m_vaoAttribBindingHasClientArrayCache) {
331                     *hasClientArrays = true;
332                 }
333                 if ((1 << i) & m_vaoAttribBindingHasVboCache) {
334                     *hasVBOs = true;
335                 }
336                 if (*hasClientArrays && *hasVBOs) return;
337             } else {
338                 todo[todo_count] = i;
339                 ++todo_count;
340             }
341         }
342     }
343 
344     if (todo_count == 0 &&
345         !(*hasClientArrays) &&
346         *hasVBOs) {
347         m_noClientArraysCache = 1;
348     }
349 
350     for (int k = 0; k < todo_count; ++k) {
351         int i = todo[k];
352         const GLClientState::BufferBinding& curr_binding =
353             m_currVaoState.bufferBindings_const()[
354                 m_currVaoState[i].bindingindex];
355         GLuint bufferObject = curr_binding.buffer;
356         if (bufferObject == 0 && curr_binding.offset && hasClientArrays) {
357             *hasClientArrays = true;
358             m_vaoAttribBindingHasClientArrayCache |= (1 << i);
359         } else {
360             m_vaoAttribBindingHasClientArrayCache &= ~(1 << i);
361         }
362         if (bufferObject != 0 && hasVBOs) {
363             *hasVBOs = true;
364             m_vaoAttribBindingHasVboCache |= (1 << i);
365         } else {
366             m_vaoAttribBindingHasVboCache &= ~(1 << i);
367         }
368         m_vaoAttribBindingCacheInvalid &= ~(1 << i);
369         if (*hasClientArrays && *hasVBOs) return;
370     }
371 
372     if (!(*hasClientArrays) &&
373         *hasVBOs) {
374         m_noClientArraysCache = 1;
375     }
376 }
377 
getState(int location)378 const GLClientState::VertexAttribState& GLClientState::getState(int location) {
379     return m_currVaoState[location];
380 }
381 
getStateAndEnableDirty(int location,bool * enableChanged)382 const GLClientState::VertexAttribState& GLClientState::getStateAndEnableDirty(int location, bool *enableChanged)
383 {
384     if (enableChanged) {
385         *enableChanged = m_currVaoState[location].enableDirty;
386     }
387 
388     m_currVaoState[location].enableDirty = false;
389     return m_currVaoState[location];
390 }
391 
updateEnableDirtyArrayForDraw()392 void GLClientState::updateEnableDirtyArrayForDraw() {
393     bool enableChanged;
394     VAOState& vaoState = m_currVaoState.vaoState();
395 
396     int k = 0;
397     for (int i = 0; i < CODEC_MAX_VERTEX_ATTRIBUTES; ++i) {
398         const VertexAttribState &state = getStateAndEnableDirty(i, &enableChanged);
399         if (enableChanged || state.enabled) {
400             vaoState.attributesNeedingUpdateForDraw[k] = i;
401             ++k;
402         }
403     }
404     vaoState.numAttributesNeedingUpdateForDraw = k;
405 }
406 
currentVaoState()407 GLClientState::VAOState& GLClientState::currentVaoState() {
408     return m_currVaoState.vaoState();
409 }
410 
getLocation(GLenum loc)411 int GLClientState::getLocation(GLenum loc)
412 {
413     int retval;
414 
415     switch(loc) {
416     case GL_VERTEX_ARRAY:
417         retval = int(VERTEX_LOCATION);
418         break;
419     case GL_NORMAL_ARRAY:
420         retval = int(NORMAL_LOCATION);
421         break;
422     case GL_COLOR_ARRAY:
423         retval = int(COLOR_LOCATION);
424         break;
425     case GL_POINT_SIZE_ARRAY_OES:
426         retval = int(POINTSIZE_LOCATION);
427         break;
428     case GL_TEXTURE_COORD_ARRAY:
429         retval = int (TEXCOORD0_LOCATION + m_activeTexture);
430         break;
431     case GL_MATRIX_INDEX_ARRAY_OES:
432         retval = int (MATRIXINDEX_LOCATION);
433         break;
434     case GL_WEIGHT_ARRAY_OES:
435         retval = int (WEIGHT_LOCATION);
436         break;
437     default:
438         retval = loc;
439     }
440     return retval;
441 }
442 
sClearIndexedBufferBinding(GLuint id,std::vector<GLClientState::BufferBinding> & bindings)443 static void sClearIndexedBufferBinding(GLuint id, std::vector<GLClientState::BufferBinding>& bindings) {
444     for (size_t i = 0; i < bindings.size(); i++) {
445         if (bindings[i].buffer == id) {
446             bindings[i].offset = 0;
447             bindings[i].stride = 0;
448             bindings[i].effectiveStride = 16;
449             bindings[i].size = 0;
450             bindings[i].buffer = 0;
451         }
452     }
453 }
454 
455 #ifdef GFXSTREAM
456 
addBuffer(GLuint id)457 void GLClientState::addBuffer(GLuint id) {
458     mBufferIds.add(id);
459     mBufferIds.set(id, true);
460     mHostMappedBufferDirty.add(id);
461 }
462 
removeBuffer(GLuint id)463 void GLClientState::removeBuffer(GLuint id) {
464     mHostMappedBufferDirty.remove(id);
465     mBufferIds.remove(id);
466 }
467 
bufferIdExists(GLuint id) const468 bool GLClientState::bufferIdExists(GLuint id) const {
469     return mBufferIds.get(id);
470 }
471 
setBufferHostMapDirty(GLuint id,bool dirty)472 void GLClientState::setBufferHostMapDirty(GLuint id, bool dirty) {
473     mHostMappedBufferDirty.set(id, dirty);
474 }
475 
isBufferHostMapDirty(GLuint id) const476 bool GLClientState::isBufferHostMapDirty(GLuint id) const {
477     return mHostMappedBufferDirty.get(id);
478 }
479 
setExistence(ObjectType type,bool exists,GLsizei count,const GLuint * ids)480 void GLClientState::setExistence(ObjectType type, bool exists, GLsizei count, const GLuint* ids) {
481     if (type == ObjectType::Sampler) {
482         SamplerInfo::ScopedView view(mSamplerInfo);
483         if (exists) {
484             for (GLsizei i = 0; i < count; ++i) {
485                 view.addFresh(ids[i]);
486             }
487         } else {
488             for (GLsizei i = 0; i < count; ++i) {
489                 view.unref(ids[i]);
490             }
491         }
492     } else {
493         ExistenceMap* existenceMap = &mBufferIds;
494 
495         switch (type) {
496             case ObjectType::Buffer:
497                 existenceMap = &mBufferIds;
498                 break;
499             case ObjectType::TransformFeedback:
500                 existenceMap = &mTransformFeedbackIds;
501                 break;
502             case ObjectType::Query:
503                 existenceMap = &mQueryIds;
504                 for (GLsizei i = 0; i < count; ++i) {
505                     // reset the last query target
506                     mLastQueryTargets.add(ids[i], 0);
507                 }
508                 break;
509             case ObjectType::Sampler:
510             default:
511                 ALOGE("%s: Unreachable code\n", __func__);
512                 abort();
513         }
514 
515         if (exists) {
516             for (GLsizei i = 0; i < count; ++i) {
517                 existenceMap->add(ids[i]);
518                 existenceMap->set(ids[i], true);
519             }
520         } else {
521             for (GLsizei i = 0; i < count; ++i) {
522                 existenceMap->remove(ids[i]);
523             }
524         }
525     }
526 }
527 
queryExistence(ObjectType type,GLuint id) const528 bool GLClientState::queryExistence(ObjectType type, GLuint id) const {
529     switch (type) {
530         case ObjectType::Buffer:
531             return mBufferIds.get(id);
532         case ObjectType::TransformFeedback:
533             return mTransformFeedbackIds.get(id);
534         case ObjectType::Sampler:
535             return samplerExists(id);
536         case ObjectType::Query:
537             return mQueryIds.get(id);
538         default:
539             ALOGD("%s: unknown object type: 0x%x\n", __func__, type);
540             abort();
541     }
542 }
543 
samplerExists(GLuint id) const544 bool GLClientState::samplerExists(GLuint id) const {
545     if (!id) return true;
546     SamplerInfo::ScopedView view(mSamplerInfo);
547     return view.samplerExists(id);
548 }
549 
tryBind(GLenum target,GLuint id)550 bool GLClientState::tryBind(GLenum target, GLuint id) {
551     if (0 == id) { // unbind operation
552         switch (target) {
553             case GL_TRANSFORM_FEEDBACK:
554                 mBoundTransformFeedbackValidity.id = 0;
555                 mBoundTransformFeedbackValidity.valid = true;
556                 break;
557             case GL_ANY_SAMPLES_PASSED:
558                 mBoundQueryValidity_AnySamplesPassed.id = 0;
559                 mBoundQueryValidity_AnySamplesPassed.valid = false;
560                 break;
561             case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
562                 mBoundQueryValidity_AnySamplesPassedConservative.id = 0;
563                 mBoundQueryValidity_AnySamplesPassedConservative.valid = false;
564                 break;
565             case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
566                 mBoundQueryValidity_TransformFeedbackPrimitivesWritten.id = 0;
567                 mBoundQueryValidity_TransformFeedbackPrimitivesWritten.valid = false;
568                 break;
569             default:
570                 ALOGE("%s: target 0x%x not yet supported in new state tracking model\n", __func__, target);
571                 abort();
572         }
573         return true;
574     }
575 
576     switch (target) {
577         case GL_TRANSFORM_FEEDBACK:
578             if (!queryExistence(ObjectType::TransformFeedback, id)) return false;
579             break;
580         case GL_ANY_SAMPLES_PASSED:
581         case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
582         case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
583             if (!queryExistence(ObjectType::Query, id)) {
584                 return false;
585             }
586             break;
587         default:
588             ALOGE("%s: target 0x%x not yet supported in new state tracking model\n", __func__, target);
589             abort();
590     }
591 
592     // valid bind
593     switch (target) {
594     case GL_TRANSFORM_FEEDBACK:
595         mBoundTransformFeedbackValidity.id = id;
596         mBoundTransformFeedbackValidity.valid = true;
597         break;
598     case GL_ANY_SAMPLES_PASSED:
599         mBoundQueryValidity_AnySamplesPassed.id = id;
600         mBoundQueryValidity_AnySamplesPassed.valid = true;
601         break;
602     case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
603         mBoundQueryValidity_AnySamplesPassedConservative.id = id;
604         mBoundQueryValidity_AnySamplesPassedConservative.valid = true;
605         break;
606     case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
607         mBoundQueryValidity_TransformFeedbackPrimitivesWritten.id = id;
608         mBoundQueryValidity_TransformFeedbackPrimitivesWritten.valid = true;
609         break;
610     default:
611         ALOGE("%s: target 0x%x not yet supported in new state tracking model\n", __func__, target);
612         abort();
613     }
614     return true;
615 }
616 
isBoundTargetValid(GLenum target)617 bool GLClientState::isBoundTargetValid(GLenum target) {
618     switch (target) {
619     case GL_TRANSFORM_FEEDBACK:
620         return mBoundTransformFeedbackValidity.valid;
621     case GL_ANY_SAMPLES_PASSED:
622         return mBoundQueryValidity_AnySamplesPassed.valid;
623     case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
624         return mBoundQueryValidity_AnySamplesPassedConservative.valid;
625     case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
626         return mBoundQueryValidity_TransformFeedbackPrimitivesWritten.valid;
627     default:
628         ALOGE("%s: target 0x%x not yet supported in new state tracking model\n", __func__, target);
629         abort();
630     }
631 }
632 
isQueryBound(GLenum target)633 bool GLClientState::isQueryBound(GLenum target) {
634     switch (target) {
635     case GL_ANY_SAMPLES_PASSED:
636         return mBoundQueryValidity_AnySamplesPassed.valid;
637     case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
638         return mBoundQueryValidity_AnySamplesPassedConservative.valid;
639     case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
640         return mBoundQueryValidity_TransformFeedbackPrimitivesWritten.valid;
641     default:
642         return false;
643     }
644 }
645 
isQueryObjectActive(GLuint id)646 bool GLClientState::isQueryObjectActive(GLuint id) {
647     if (mBoundQueryValidity_AnySamplesPassed.valid &&
648         (id == mBoundQueryValidity_AnySamplesPassed.id))
649         return true;
650     if (mBoundQueryValidity_AnySamplesPassedConservative.valid &&
651         (id == mBoundQueryValidity_AnySamplesPassedConservative.id))
652         return true;
653     if (mBoundQueryValidity_TransformFeedbackPrimitivesWritten.valid &&
654         (id == mBoundQueryValidity_TransformFeedbackPrimitivesWritten.id))
655         return true;
656     return false;
657 }
658 
setLastQueryTarget(GLenum target,GLuint id)659 void GLClientState::setLastQueryTarget(GLenum target, GLuint id) {
660     mLastQueryTargets.add(id, target);
661 }
662 
getLastQueryTarget(GLuint id)663 GLenum GLClientState::getLastQueryTarget(GLuint id) {
664     auto targetPtr = mLastQueryTargets.get_const(id);
665     if (!targetPtr) return 0;
666     return *targetPtr;
667 }
668 
669 #else // GFXSTREAM
670 
addBuffer(GLuint id)671 void GLClientState::addBuffer(GLuint id) {
672     mBufferIds.insert(id);
673 }
674 
removeBuffer(GLuint id)675 void GLClientState::removeBuffer(GLuint id) {
676     mBufferIds.erase(id);
677 }
678 
bufferIdExists(GLuint id) const679 bool GLClientState::bufferIdExists(GLuint id) const {
680     return mBufferIds.find(id) != mBufferIds.end();
681 }
682 
setBufferHostMapDirty(GLuint id,bool dirty)683 void GLClientState::setBufferHostMapDirty(GLuint id, bool dirty) {
684     (void)id;
685     (void)dirty;
686 }
687 
isBufferHostMapDirty(GLuint id) const688 bool GLClientState::isBufferHostMapDirty(GLuint id) const {
689     (void)id;
690     return true;
691 }
692 
setExistence(ObjectType,bool,GLsizei,const GLuint *)693 void GLClientState::setExistence(ObjectType, bool, GLsizei, const GLuint*) {
694     // no-op in non-gfxstream
695 }
696 
697 #endif // !GFXSTREAM
698 
setBoundPixelPackBufferDirtyForHostMap()699 void GLClientState::setBoundPixelPackBufferDirtyForHostMap() {
700     if (m_pixelPackBuffer)
701         setBufferHostMapDirty(m_pixelPackBuffer, true /* dirty */);
702 }
703 
setBoundTransformFeedbackBuffersDirtyForHostMap()704 void GLClientState::setBoundTransformFeedbackBuffersDirtyForHostMap() {
705     if (m_transformFeedbackBuffer)
706         setBufferHostMapDirty(
707             m_transformFeedbackBuffer,
708             true /* dirty */);
709 
710     for (size_t i = 0; i < m_indexedTransformFeedbackBuffers.size(); ++i)
711         if (m_indexedTransformFeedbackBuffers[i].buffer)
712             setBufferHostMapDirty(
713                 m_indexedTransformFeedbackBuffers[i].buffer,
714                 true /* dirty */);
715 }
716 
setBoundShaderStorageBuffersDirtyForHostMap()717 void GLClientState::setBoundShaderStorageBuffersDirtyForHostMap() {
718     if (m_glesMajorVersion == 3 && m_glesMinorVersion == 0) return;
719 
720     if (m_shaderStorageBuffer)
721         setBufferHostMapDirty(
722             m_shaderStorageBuffer,
723             true /* dirty */);
724 
725     for (size_t i = 0; i < m_indexedShaderStorageBuffers.size(); ++i)
726         if (m_indexedShaderStorageBuffers[i].buffer)
727             setBufferHostMapDirty(
728                 m_indexedShaderStorageBuffers[i].buffer,
729                 true /* dirty */);
730 }
731 
setBoundAtomicCounterBuffersDirtyForHostMap()732 void GLClientState::setBoundAtomicCounterBuffersDirtyForHostMap() {
733     if (m_glesMajorVersion == 3 && m_glesMinorVersion == 0) return;
734 
735     if (m_atomicCounterBuffer)
736         setBufferHostMapDirty(
737             m_atomicCounterBuffer,
738             true /* dirty */);
739 
740     for (size_t i = 0; i < m_indexedAtomicCounterBuffers.size(); ++i)
741         if (m_indexedAtomicCounterBuffers[i].buffer)
742             setBufferHostMapDirty(
743                 m_indexedAtomicCounterBuffers[i].buffer,
744                 true /* dirty */);
745 }
746 
unBindBuffer(GLuint id)747 void GLClientState::unBindBuffer(GLuint id) {
748     if (m_arrayBuffer == id) {
749         m_arrayBuffer = 0;
750         m_arrayBuffer_lastEncode = 0;
751     }
752 
753     if (m_currVaoState.iboId() == id) {
754         m_currVaoState.iboId() = 0;
755         m_currVaoState.iboIdLastEncode() = 0;
756     }
757 
758     if (m_copyReadBuffer == id)
759         m_copyReadBuffer = 0;
760     if (m_copyWriteBuffer == id)
761         m_copyWriteBuffer = 0;
762     if (m_pixelPackBuffer == id)
763         m_pixelPackBuffer = 0;
764     if (m_pixelUnpackBuffer == id)
765         m_pixelUnpackBuffer = 0;
766     if (m_transformFeedbackBuffer == id)
767         m_transformFeedbackBuffer = 0;
768     if (m_uniformBuffer == id)
769         m_uniformBuffer = 0;
770     if (m_atomicCounterBuffer == id)
771         m_atomicCounterBuffer = 0;
772     if (m_dispatchIndirectBuffer == id)
773         m_dispatchIndirectBuffer = 0;
774     if (m_drawIndirectBuffer == id)
775         m_drawIndirectBuffer = 0;
776     if (m_shaderStorageBuffer == id)
777         m_shaderStorageBuffer = 0;
778     if (m_textureBuffer == id)
779         m_textureBuffer = 0;
780 
781     sClearIndexedBufferBinding(id, m_indexedTransformFeedbackBuffers);
782     sClearIndexedBufferBinding(id, m_indexedUniformBuffers);
783     sClearIndexedBufferBinding(id, m_indexedAtomicCounterBuffers);
784     sClearIndexedBufferBinding(id, m_indexedShaderStorageBuffers);
785     sClearIndexedBufferBinding(id, m_currVaoState.bufferBindings());
786     m_vaoAttribBindingCacheInvalid = 0xffff;
787     m_noClientArraysCache = 0;
788 }
789 
bindBuffer(GLenum target,GLuint id)790 int GLClientState::bindBuffer(GLenum target, GLuint id)
791 {
792     int err = 0;
793     switch(target) {
794     case GL_ARRAY_BUFFER:
795         m_arrayBuffer = id;
796         break;
797     case GL_ELEMENT_ARRAY_BUFFER:
798         m_currVaoState.iboId() = id;
799         break;
800     case GL_COPY_READ_BUFFER:
801         m_copyReadBuffer = id;
802         break;
803     case GL_COPY_WRITE_BUFFER:
804         m_copyWriteBuffer = id;
805         break;
806     case GL_PIXEL_PACK_BUFFER:
807         m_pixelPackBuffer = id;
808         break;
809     case GL_PIXEL_UNPACK_BUFFER:
810         m_pixelUnpackBuffer = id;
811         break;
812     case GL_TRANSFORM_FEEDBACK_BUFFER:
813         m_transformFeedbackBuffer = id;
814         break;
815     case GL_UNIFORM_BUFFER:
816         m_uniformBuffer = id;
817         break;
818     case GL_ATOMIC_COUNTER_BUFFER:
819         m_atomicCounterBuffer = id;
820         break;
821     case GL_DISPATCH_INDIRECT_BUFFER:
822         m_dispatchIndirectBuffer = id;
823         break;
824     case GL_DRAW_INDIRECT_BUFFER:
825         m_drawIndirectBuffer = id;
826         break;
827     case GL_SHADER_STORAGE_BUFFER:
828         m_shaderStorageBuffer = id;
829         break;
830     case GL_TEXTURE_BUFFER_OES:
831         m_textureBuffer = id;
832         break;
833     default:
834         err = -1;
835     }
836     return err;
837 }
838 
bindIndexedBuffer(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size,GLintptr stride,GLintptr effectiveStride)839 void GLClientState::bindIndexedBuffer(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride) {
840     switch (target) {
841     case GL_TRANSFORM_FEEDBACK_BUFFER:
842         m_indexedTransformFeedbackBuffers[index].buffer = buffer;
843         m_indexedTransformFeedbackBuffers[index].offset = offset;
844         m_indexedTransformFeedbackBuffers[index].size = size;
845         m_indexedTransformFeedbackBuffers[index].stride = stride;
846         break;
847     case GL_UNIFORM_BUFFER:
848         m_indexedUniformBuffers[index].buffer = buffer;
849         m_indexedUniformBuffers[index].offset = offset;
850         m_indexedUniformBuffers[index].size = size;
851         m_indexedUniformBuffers[index].stride = stride;
852         break;
853     case GL_ATOMIC_COUNTER_BUFFER:
854         m_indexedAtomicCounterBuffers[index].buffer = buffer;
855         m_indexedAtomicCounterBuffers[index].offset = offset;
856         m_indexedAtomicCounterBuffers[index].size = size;
857         m_indexedAtomicCounterBuffers[index].stride = stride;
858         break;
859     case GL_SHADER_STORAGE_BUFFER:
860         m_indexedShaderStorageBuffers[index].buffer = buffer;
861         m_indexedShaderStorageBuffers[index].offset = offset;
862         m_indexedShaderStorageBuffers[index].size = size;
863         m_indexedShaderStorageBuffers[index].stride = stride;
864         break;
865     default:
866         m_currVaoState.bufferBinding(index).buffer = buffer;
867         m_currVaoState.bufferBinding(index).offset = offset;
868         m_currVaoState.bufferBinding(index).size = size;
869         m_currVaoState.bufferBinding(index).stride = stride;
870         m_currVaoState.bufferBinding(index).effectiveStride = effectiveStride;
871         m_vaoAttribBindingCacheInvalid |= (1 << m_currVaoState.bufferBinding(index).vertexAttribLoc);
872         return;
873     }
874 }
875 
getMaxIndexedBufferBindings(GLenum target) const876 int GLClientState::getMaxIndexedBufferBindings(GLenum target) const {
877     switch (target) {
878     case GL_TRANSFORM_FEEDBACK_BUFFER:
879         return m_indexedTransformFeedbackBuffers.size();
880     case GL_UNIFORM_BUFFER:
881         return m_indexedUniformBuffers.size();
882     case GL_ATOMIC_COUNTER_BUFFER:
883         return m_indexedAtomicCounterBuffers.size();
884     case GL_SHADER_STORAGE_BUFFER:
885         return m_indexedShaderStorageBuffers.size();
886     default:
887         return m_currVaoState.bufferBindings_const().size();
888     }
889 }
890 
isNonIndexedBindNoOp(GLenum target,GLuint buffer)891 bool GLClientState::isNonIndexedBindNoOp(GLenum target, GLuint buffer) {
892     if (buffer != getLastEncodedBufferBind(target)) return false;
893 
894     int idOrError = getBuffer(target);
895     if (idOrError < 0) {
896         return false;
897     } else {
898         return buffer == (GLuint)idOrError;
899     }
900 }
901 
isIndexedBindNoOp(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size,GLintptr stride,GLintptr effectiveStride)902 bool GLClientState::isIndexedBindNoOp(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride) {
903 
904     if (target == GL_TRANSFORM_FEEDBACK_BUFFER) return false;
905 
906     if (buffer != getLastEncodedBufferBind(target)) return false;
907 
908     switch (target) {
909     case GL_TRANSFORM_FEEDBACK_BUFFER:
910         return m_indexedTransformFeedbackBuffers[index].buffer == buffer &&
911                m_indexedTransformFeedbackBuffers[index].offset == offset &&
912                m_indexedTransformFeedbackBuffers[index].size == size &&
913                m_indexedTransformFeedbackBuffers[index].stride == stride;
914     case GL_UNIFORM_BUFFER:
915         return m_indexedUniformBuffers[index].buffer == buffer &&
916                m_indexedUniformBuffers[index].offset == offset &&
917                m_indexedUniformBuffers[index].size == size &&
918                m_indexedUniformBuffers[index].stride == stride;
919     case GL_ATOMIC_COUNTER_BUFFER:
920         return m_indexedAtomicCounterBuffers[index].buffer == buffer &&
921                m_indexedAtomicCounterBuffers[index].offset == offset &&
922                m_indexedAtomicCounterBuffers[index].size == size &&
923                m_indexedAtomicCounterBuffers[index].stride == stride;
924     case GL_SHADER_STORAGE_BUFFER:
925         return m_indexedShaderStorageBuffers[index].buffer == buffer &&
926                m_indexedShaderStorageBuffers[index].offset == offset &&
927                m_indexedShaderStorageBuffers[index].size == size &&
928                m_indexedShaderStorageBuffers[index].stride == stride;
929     default:
930         return m_currVaoState.bufferBinding(index).buffer == buffer &&
931                m_currVaoState.bufferBinding(index).offset == offset &&
932                m_currVaoState.bufferBinding(index).size == size &&
933                m_currVaoState.bufferBinding(index).stride == stride &&
934                m_currVaoState.bufferBinding(index).effectiveStride == effectiveStride;
935     }
936 }
937 
getMaxTextureSize() const938 int GLClientState::getMaxTextureSize() const {
939     return m_hostDriverCaps.max_texture_size;
940 }
941 
getMaxTextureSize3D() const942 int GLClientState::getMaxTextureSize3D() const {
943     return m_hostDriverCaps.max_texture_size_3d;
944 }
945 
getMaxTextureSizeCubeMap() const946 int GLClientState::getMaxTextureSizeCubeMap() const {
947     return m_hostDriverCaps.max_texture_size_cube_map;
948 }
949 
getLog2MaxTextureSize() const950 int GLClientState::getLog2MaxTextureSize() const {
951     return m_log2MaxTextureSize;
952 }
953 
postDraw()954 void GLClientState::postDraw() {
955     setBoundTransformFeedbackBuffersDirtyForHostMap();
956     setBoundShaderStorageBuffersDirtyForHostMap();
957     setBoundAtomicCounterBuffersDirtyForHostMap();
958 }
959 
postReadPixels()960 void GLClientState::postReadPixels() {
961     setBoundPixelPackBufferDirtyForHostMap();
962 }
963 
postDispatchCompute()964 void GLClientState::postDispatchCompute() {
965     setBoundShaderStorageBuffersDirtyForHostMap();
966     setBoundAtomicCounterBuffersDirtyForHostMap();
967 }
968 
shouldSkipHostMapBuffer(GLenum target)969 bool GLClientState::shouldSkipHostMapBuffer(GLenum target) {
970     GLuint id = getBuffer(target);
971     return !isBufferHostMapDirty(id);
972 }
973 
onHostMappedBuffer(GLenum target)974 void GLClientState::onHostMappedBuffer(GLenum target) {
975     GLuint id = getBuffer(target);
976     setBufferHostMapDirty(id, false /* not dirty */);
977 }
978 
getBuffer(GLenum target)979 int GLClientState::getBuffer(GLenum target) {
980     int ret=0;
981     switch (target) {
982         case GL_ARRAY_BUFFER:
983             ret = m_arrayBuffer;
984             break;
985         case GL_ELEMENT_ARRAY_BUFFER:
986             ret = m_currVaoState.iboId();
987             break;
988         case GL_COPY_READ_BUFFER:
989             ret = m_copyReadBuffer;
990             break;
991         case GL_COPY_WRITE_BUFFER:
992             ret = m_copyWriteBuffer;
993             break;
994         case GL_PIXEL_PACK_BUFFER:
995             ret = m_pixelPackBuffer;
996             break;
997         case GL_PIXEL_UNPACK_BUFFER:
998             ret = m_pixelUnpackBuffer;
999             break;
1000         case GL_TRANSFORM_FEEDBACK_BUFFER:
1001             ret = m_transformFeedbackBuffer;
1002             break;
1003         case GL_UNIFORM_BUFFER:
1004             ret = m_uniformBuffer;
1005             break;
1006         case GL_ATOMIC_COUNTER_BUFFER:
1007             ret = m_atomicCounterBuffer;
1008             break;
1009         case GL_DISPATCH_INDIRECT_BUFFER:
1010             ret = m_dispatchIndirectBuffer;
1011             break;
1012         case GL_DRAW_INDIRECT_BUFFER:
1013             ret = m_drawIndirectBuffer;
1014             break;
1015         case GL_SHADER_STORAGE_BUFFER:
1016             ret = m_shaderStorageBuffer;
1017             break;
1018         case GL_TEXTURE_BUFFER_OES:
1019             ret = m_textureBuffer;
1020             break;
1021         default:
1022             ret = -1;
1023     }
1024     return ret;
1025 }
1026 
getLastEncodedBufferBind(GLenum target)1027 GLuint GLClientState::getLastEncodedBufferBind(GLenum target) {
1028     GLuint ret;
1029     switch (target)
1030     {
1031     case GL_ARRAY_BUFFER:
1032         ret = m_arrayBuffer_lastEncode;
1033         break;
1034     case GL_ELEMENT_ARRAY_BUFFER:
1035         ret = m_currVaoState.iboIdLastEncode();
1036         break;
1037     default:
1038     {
1039         int idOrError = getBuffer(target);
1040         ret = (idOrError < 0) ? 0 : (GLuint)idOrError;
1041     }
1042     }
1043 
1044     return ret;
1045 }
1046 
setLastEncodedBufferBind(GLenum target,GLuint id)1047 void GLClientState::setLastEncodedBufferBind(GLenum target, GLuint id)
1048 {
1049     switch (target)
1050     {
1051     case GL_ARRAY_BUFFER:
1052         m_arrayBuffer_lastEncode = id;
1053         break;
1054     case GL_ELEMENT_ARRAY_BUFFER:
1055         m_currVaoState.iboIdLastEncode() = id;
1056         break;
1057     default:
1058         break;
1059     }
1060 }
1061 
isTexture(GLuint tex_name) const1062 bool GLClientState::isTexture(GLuint tex_name) const {
1063     return getTextureRec(tex_name) != nullptr;
1064 }
1065 
isTextureWithStorage(GLuint tex_name) const1066 bool GLClientState::isTextureWithStorage(GLuint tex_name) const {
1067     TextureRec* rec = getTextureRecPtr(tex_name);
1068     if (!rec) return false;
1069     return rec->hasStorage;
1070 }
1071 
isTextureCubeMap(GLuint tex_name) const1072 bool GLClientState::isTextureCubeMap(GLuint tex_name) const {
1073     TextureRec* texrec = getTextureRecPtr(tex_name);
1074     if (!texrec) return false;
1075     switch (texrec->target) {
1076         case GL_TEXTURE_CUBE_MAP:
1077         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1078         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1079         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1080         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1081         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1082         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1083             return true;
1084         default:
1085             return false;
1086     }
1087 }
1088 
isRenderbuffer(GLuint name) const1089 bool GLClientState::isRenderbuffer(GLuint name) const {
1090     if (!name) return false;
1091 
1092     RenderbufferInfo::ScopedView view(mRboState.rboData);
1093     return view.hasRbo(name);
1094 }
1095 
isRenderbufferThatWasBound(GLuint name) const1096 bool GLClientState::isRenderbufferThatWasBound(GLuint name) const {
1097     if (!name) return true;
1098 
1099     RenderbufferInfo::ScopedView view(mRboState.rboData);
1100     if (!view.hasRbo(name)) return false;
1101 
1102     const RboProps* props = view.get_const(name);
1103     return props->previouslyBound;
1104 }
1105 
getClientStatePointer(GLenum pname,GLvoid ** params)1106 void GLClientState::getClientStatePointer(GLenum pname, GLvoid** params)
1107 {
1108     GLenum which_state = -1;
1109     switch (pname) {
1110     case GL_VERTEX_ARRAY_POINTER: {
1111         which_state = GLClientState::VERTEX_LOCATION;
1112         break;
1113         }
1114     case GL_NORMAL_ARRAY_POINTER: {
1115         which_state = GLClientState::NORMAL_LOCATION;
1116         break;
1117         }
1118     case GL_COLOR_ARRAY_POINTER: {
1119         which_state = GLClientState::COLOR_LOCATION;
1120         break;
1121         }
1122     case GL_TEXTURE_COORD_ARRAY_POINTER: {
1123         which_state = getActiveTexture() + GLClientState::TEXCOORD0_LOCATION;
1124         break;
1125         }
1126     case GL_POINT_SIZE_ARRAY_POINTER_OES: {
1127         which_state = GLClientState::POINTSIZE_LOCATION;
1128         break;
1129         }
1130     case GL_MATRIX_INDEX_ARRAY_POINTER_OES: {
1131         which_state = GLClientState::MATRIXINDEX_LOCATION;
1132         break;
1133         }
1134     case GL_WEIGHT_ARRAY_POINTER_OES: {
1135         which_state = GLClientState::WEIGHT_LOCATION;
1136         break;
1137         }
1138     }
1139     if (which_state != -1)
1140         *params = m_currVaoState[which_state].data;
1141 }
1142 
setPixelStore(GLenum param,GLint value)1143 int GLClientState::setPixelStore(GLenum param, GLint value)
1144 {
1145     int retval = 0;
1146     switch(param) {
1147     case GL_UNPACK_ALIGNMENT:
1148         m_pixelStore.unpack_alignment = value;
1149         break;
1150     case GL_PACK_ALIGNMENT:
1151         m_pixelStore.pack_alignment = value;
1152         break;
1153     case GL_UNPACK_ROW_LENGTH:
1154         m_pixelStore.unpack_row_length = value;
1155         break;
1156     case GL_UNPACK_IMAGE_HEIGHT:
1157         m_pixelStore.unpack_image_height = value;
1158         break;
1159     case GL_UNPACK_SKIP_PIXELS:
1160         m_pixelStore.unpack_skip_pixels = value;
1161         break;
1162     case GL_UNPACK_SKIP_ROWS:
1163         m_pixelStore.unpack_skip_rows = value;
1164         break;
1165     case GL_UNPACK_SKIP_IMAGES:
1166         m_pixelStore.unpack_skip_images = value;
1167         break;
1168     case GL_PACK_ROW_LENGTH:
1169         m_pixelStore.pack_row_length = value;
1170         break;
1171     case GL_PACK_SKIP_PIXELS:
1172         m_pixelStore.pack_skip_pixels = value;
1173         break;
1174     case GL_PACK_SKIP_ROWS:
1175         m_pixelStore.pack_skip_rows = value;
1176         break;
1177     default:
1178         retval = GL_INVALID_ENUM;
1179     }
1180     return retval;
1181 }
1182 
1183 
pixelDataSize(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int pack) const1184 size_t GLClientState::pixelDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const
1185 {
1186     if (width <= 0 || height <= 0 || depth <= 0) return 0;
1187 
1188     ALOGV("%s: pack? %d", __FUNCTION__, pack);
1189     if (pack) {
1190         ALOGV("%s: pack stats", __FUNCTION__);
1191         ALOGV("%s: pack align %d", __FUNCTION__, m_pixelStore.pack_alignment);
1192         ALOGV("%s: pack rowlen %d", __FUNCTION__, m_pixelStore.pack_row_length);
1193         ALOGV("%s: pack skippixels %d", __FUNCTION__, m_pixelStore.pack_skip_pixels);
1194         ALOGV("%s: pack skiprows %d", __FUNCTION__, m_pixelStore.pack_skip_rows);
1195     } else {
1196         ALOGV("%s: unpack stats", __FUNCTION__);
1197         ALOGV("%s: unpack align %d", __FUNCTION__, m_pixelStore.unpack_alignment);
1198         ALOGV("%s: unpack rowlen %d", __FUNCTION__, m_pixelStore.unpack_row_length);
1199         ALOGV("%s: unpack imgheight %d", __FUNCTION__, m_pixelStore.unpack_image_height);
1200         ALOGV("%s: unpack skippixels %d", __FUNCTION__, m_pixelStore.unpack_skip_pixels);
1201         ALOGV("%s: unpack skiprows %d", __FUNCTION__, m_pixelStore.unpack_skip_rows);
1202         ALOGV("%s: unpack skipimages %d", __FUNCTION__, m_pixelStore.unpack_skip_images);
1203     }
1204     return GLESTextureUtils::computeTotalImageSize(
1205             width, height, depth,
1206             format, type,
1207             pack ? m_pixelStore.pack_alignment : m_pixelStore.unpack_alignment,
1208             pack ? m_pixelStore.pack_row_length : m_pixelStore.unpack_row_length,
1209             pack ? 0 : m_pixelStore.unpack_image_height,
1210             pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
1211             pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
1212             pack ? 0 : m_pixelStore.unpack_skip_images);
1213 }
1214 
pboNeededDataSize(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int pack,int ignoreTrailing) const1215 size_t GLClientState::pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack, int ignoreTrailing) const
1216 {
1217     if (width <= 0 || height <= 0 || depth <= 0) return 0;
1218 
1219     ALOGV("%s: pack? %d", __FUNCTION__, pack);
1220     if (pack) {
1221         ALOGV("%s: pack stats", __FUNCTION__);
1222         ALOGV("%s: pack align %d", __FUNCTION__, m_pixelStore.pack_alignment);
1223         ALOGV("%s: pack rowlen %d", __FUNCTION__, m_pixelStore.pack_row_length);
1224         ALOGV("%s: pack skippixels %d", __FUNCTION__, m_pixelStore.pack_skip_pixels);
1225         ALOGV("%s: pack skiprows %d", __FUNCTION__, m_pixelStore.pack_skip_rows);
1226     } else {
1227         ALOGV("%s: unpack stats", __FUNCTION__);
1228         ALOGV("%s: unpack align %d", __FUNCTION__, m_pixelStore.unpack_alignment);
1229         ALOGV("%s: unpack rowlen %d", __FUNCTION__, m_pixelStore.unpack_row_length);
1230         ALOGV("%s: unpack imgheight %d", __FUNCTION__, m_pixelStore.unpack_image_height);
1231         ALOGV("%s: unpack skippixels %d", __FUNCTION__, m_pixelStore.unpack_skip_pixels);
1232         ALOGV("%s: unpack skiprows %d", __FUNCTION__, m_pixelStore.unpack_skip_rows);
1233         ALOGV("%s: unpack skipimages %d", __FUNCTION__, m_pixelStore.unpack_skip_images);
1234     }
1235     return GLESTextureUtils::computeNeededBufferSize(
1236             width, height, depth,
1237             format, type,
1238             pack ? m_pixelStore.pack_alignment : m_pixelStore.unpack_alignment,
1239             pack ? m_pixelStore.pack_row_length : m_pixelStore.unpack_row_length,
1240             pack ? 0 : m_pixelStore.unpack_image_height,
1241             pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
1242             pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
1243             pack ? 0 : m_pixelStore.unpack_skip_images,
1244             ignoreTrailing);
1245 }
1246 
1247 
clearBufferNumElts(GLenum buffer) const1248 size_t GLClientState::clearBufferNumElts(GLenum buffer) const
1249 {
1250     switch (buffer) {
1251     case GL_COLOR:
1252         return 4;
1253     case GL_DEPTH:
1254     case GL_STENCIL:
1255         return 1;
1256     }
1257     return 1;
1258 }
1259 
getPackingOffsets2D(GLsizei width,GLsizei height,GLenum format,GLenum type,int * bpp,int * startOffset,int * pixelRowSize,int * totalRowSize,int * skipRows) const1260 void GLClientState::getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
1261 {
1262     if (width <= 0 || height <= 0) {
1263         *startOffset = 0;
1264         *pixelRowSize = 0;
1265         *totalRowSize = 0;
1266         return;
1267     }
1268 
1269     GLESTextureUtils::computePackingOffsets2D(
1270             width, height,
1271             format, type,
1272             m_pixelStore.pack_alignment,
1273             m_pixelStore.pack_row_length,
1274             m_pixelStore.pack_skip_pixels,
1275             m_pixelStore.pack_skip_rows,
1276             bpp,
1277             startOffset,
1278             pixelRowSize,
1279             totalRowSize);
1280 
1281     *skipRows = m_pixelStore.pack_skip_rows;
1282 }
1283 
getUnpackingOffsets2D(GLsizei width,GLsizei height,GLenum format,GLenum type,int * bpp,int * startOffset,int * pixelRowSize,int * totalRowSize,int * skipRows) const1284 void GLClientState::getUnpackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
1285 {
1286     if (width <= 0 || height <= 0) {
1287         *startOffset = 0;
1288         *pixelRowSize = 0;
1289         *totalRowSize = 0;
1290         return;
1291     }
1292 
1293     GLESTextureUtils::computePackingOffsets2D(
1294             width, height,
1295             format, type,
1296             m_pixelStore.unpack_alignment,
1297             m_pixelStore.unpack_row_length,
1298             m_pixelStore.unpack_skip_pixels,
1299             m_pixelStore.unpack_skip_rows,
1300             bpp,
1301             startOffset,
1302             pixelRowSize,
1303             totalRowSize);
1304 
1305     *skipRows = m_pixelStore.unpack_skip_rows;
1306 }
1307 
getUnpackingOffsets3D(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int * bpp,int * startOffset,int * pixelRowSize,int * totalRowSize,int * pixelImageSize,int * totalImageSize,int * skipRows,int * skipImages) const1308 void GLClientState::getUnpackingOffsets3D(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* pixelImageSize, int* totalImageSize, int* skipRows, int* skipImages) const
1309 {
1310     if (width <= 0 || height <= 0) {
1311         *startOffset = 0;
1312         *pixelRowSize = 0;
1313         *totalRowSize = 0;
1314         return;
1315     }
1316 
1317     GLESTextureUtils::computePackingOffsets3D(
1318             width, height, depth,
1319             format, type,
1320             m_pixelStore.unpack_alignment,
1321             m_pixelStore.unpack_row_length,
1322             m_pixelStore.unpack_image_height,
1323             m_pixelStore.unpack_skip_pixels,
1324             m_pixelStore.unpack_skip_rows,
1325             m_pixelStore.unpack_skip_images,
1326             bpp,
1327             startOffset,
1328             pixelRowSize,
1329             totalRowSize,
1330             pixelImageSize,
1331             totalImageSize);
1332 
1333     *skipRows = m_pixelStore.unpack_skip_rows;
1334     *skipImages = m_pixelStore.unpack_skip_images;
1335 }
1336 
setNumActiveUniformsInUniformBlock(GLuint program,GLuint uniformBlockIndex,GLint numActiveUniforms)1337 void GLClientState::setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms) {
1338     UniformBlockInfoKey key;
1339     key.program = program;
1340     key.uniformBlockIndex = uniformBlockIndex;
1341 
1342     UniformBlockUniformInfo info;
1343     info.numActiveUniforms = (size_t)numActiveUniforms;
1344 
1345     m_uniformBlockInfoMap[key] = info;
1346 }
1347 
numActiveUniformsInUniformBlock(GLuint program,GLuint uniformBlockIndex) const1348 size_t GLClientState::numActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex) const {
1349     UniformBlockInfoKey key;
1350     key.program = program;
1351     key.uniformBlockIndex = uniformBlockIndex;
1352     UniformBlockInfoMap::const_iterator it =
1353         m_uniformBlockInfoMap.find(key);
1354     if (it == m_uniformBlockInfoMap.end()) return 0;
1355     return it->second.numActiveUniforms;
1356 }
1357 
associateProgramWithPipeline(GLuint program,GLuint pipeline)1358 void GLClientState::associateProgramWithPipeline(GLuint program, GLuint pipeline) {
1359     m_programPipelines[program] = pipeline;
1360 }
1361 
programPipelineBegin()1362 GLClientState::ProgramPipelineIterator GLClientState::programPipelineBegin() {
1363     return m_programPipelines.begin();
1364 }
1365 
programPipelineEnd()1366 GLClientState::ProgramPipelineIterator GLClientState::programPipelineEnd() {
1367     return m_programPipelines.end();
1368 }
1369 
setActiveTextureUnit(GLenum texture)1370 GLenum GLClientState::setActiveTextureUnit(GLenum texture)
1371 {
1372     GLuint unit = texture - GL_TEXTURE0;
1373     if (unit >= MAX_TEXTURE_UNITS) {
1374         return GL_INVALID_ENUM;
1375     }
1376     m_tex.activeUnit = &m_tex.unit[unit];
1377     return GL_NO_ERROR;
1378 }
1379 
getActiveTextureUnit() const1380 GLenum GLClientState::getActiveTextureUnit() const
1381 {
1382     return GL_TEXTURE0 + (m_tex.activeUnit - &m_tex.unit[0]);
1383 }
1384 
enableTextureTarget(GLenum target)1385 void GLClientState::enableTextureTarget(GLenum target)
1386 {
1387     switch (target) {
1388     case GL_TEXTURE_2D:
1389         m_tex.activeUnit->enables |= (1u << TEXTURE_2D);
1390         break;
1391     case GL_TEXTURE_EXTERNAL_OES:
1392         m_tex.activeUnit->enables |= (1u << TEXTURE_EXTERNAL);
1393         break;
1394     }
1395 }
1396 
disableTextureTarget(GLenum target)1397 void GLClientState::disableTextureTarget(GLenum target)
1398 {
1399     switch (target) {
1400     case GL_TEXTURE_2D:
1401         m_tex.activeUnit->enables &= ~(1u << TEXTURE_2D);
1402         break;
1403     case GL_TEXTURE_EXTERNAL_OES:
1404         m_tex.activeUnit->enables &= ~(1u << TEXTURE_EXTERNAL);
1405         break;
1406     }
1407 }
1408 
bindSampler(GLuint unit,GLuint sampler)1409 bool GLClientState::bindSampler(GLuint unit, GLuint sampler) {
1410     SamplerInfo::ScopedView view(mSamplerInfo);
1411     view.ref(sampler);
1412     if (m_tex.unit[unit].boundSampler) {
1413         view.unref(sampler);
1414     }
1415     m_tex.unit[unit].boundSampler = sampler;
1416     return true;
1417 }
1418 
isSamplerBindNoOp(GLuint unit,GLuint sampler)1419 bool GLClientState::isSamplerBindNoOp(GLuint unit, GLuint sampler) {
1420     return m_tex.unit[unit].boundSampler == sampler;
1421 }
1422 
onDeleteSamplers(GLsizei n,const GLuint * samplers)1423 void GLClientState::onDeleteSamplers(GLsizei n, const GLuint* samplers) {
1424     for (uint32_t i = 0; i < n; ++i) {
1425         for (uint32_t j = 0; j < MAX_TEXTURE_UNITS; ++j) {
1426             uint32_t currentSampler = m_tex.unit[j].boundSampler;
1427             if (currentSampler == samplers[i]) {
1428                 m_tex.unit[j].boundSampler = 0;
1429             }
1430         }
1431     }
1432 }
1433 
getPriorityEnabledTarget(GLenum allDisabled) const1434 GLenum GLClientState::getPriorityEnabledTarget(GLenum allDisabled) const
1435 {
1436     unsigned int enables = m_tex.activeUnit->enables;
1437     if (enables & (1u << TEXTURE_EXTERNAL)) {
1438         return GL_TEXTURE_EXTERNAL_OES;
1439     } else if (enables & (1u << TEXTURE_2D)) {
1440         return GL_TEXTURE_2D;
1441     } else {
1442         return allDisabled;
1443     }
1444 }
1445 
compareTexId(const void * pid,const void * prec)1446 int GLClientState::compareTexId(const void* pid, const void* prec)
1447 {
1448     const GLuint* id = (const GLuint*)pid;
1449     const TextureRec* rec = (const TextureRec*)prec;
1450     return (GLint)(*id) - (GLint)rec->id;
1451 }
1452 
bindTexture(GLenum target,GLuint texture,GLboolean * firstUse)1453 GLenum GLClientState::bindTexture(GLenum target, GLuint texture,
1454         GLboolean* firstUse)
1455 {
1456     GLboolean first = GL_FALSE;
1457 
1458     TextureRec* texrec = getTextureRecPtr(texture);
1459     if (!texrec) {
1460         texrec = addTextureRec(texture, target);
1461         first = GL_TRUE;
1462     }
1463 
1464     if (texture && target != texrec->target &&
1465         (target != GL_TEXTURE_EXTERNAL_OES &&
1466          texrec->target != GL_TEXTURE_EXTERNAL_OES)) {
1467         return GL_INVALID_OPERATION;
1468     }
1469 
1470     switch (target) {
1471     case GL_TEXTURE_2D:
1472         m_tex.activeUnit->texture[TEXTURE_2D] = texture;
1473         break;
1474     case GL_TEXTURE_EXTERNAL_OES:
1475         m_tex.activeUnit->texture[TEXTURE_EXTERNAL] = texture;
1476         break;
1477     case GL_TEXTURE_CUBE_MAP:
1478         m_tex.activeUnit->texture[TEXTURE_CUBE_MAP] = texture;
1479         break;
1480     case GL_TEXTURE_2D_ARRAY:
1481         m_tex.activeUnit->texture[TEXTURE_2D_ARRAY] = texture;
1482         break;
1483     case GL_TEXTURE_3D:
1484         m_tex.activeUnit->texture[TEXTURE_3D] = texture;
1485         break;
1486     case GL_TEXTURE_2D_MULTISAMPLE:
1487         m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE] = texture;
1488         break;
1489     case GL_TEXTURE_BUFFER_OES:
1490         m_tex.activeUnit->texture[TEXTURE_BUFFER] = texture;
1491         break;
1492     }
1493 
1494     if (firstUse) {
1495         *firstUse = first;
1496     }
1497 
1498     return GL_NO_ERROR;
1499 }
1500 
setBoundEGLImage(GLenum target,GLeglImageOES image,int width,int height)1501 void GLClientState::setBoundEGLImage(GLenum target, GLeglImageOES image, int width, int height) {
1502     (void)image;
1503 
1504     if (target == GL_RENDERBUFFER) {
1505         if (!boundRenderbuffer()) return;
1506         setBoundRenderbufferEGLImageBacked();
1507         setBoundRenderbufferFormat(GL_RGBA);
1508         setBoundRenderbufferSamples(0);
1509         setBoundRenderbufferDimensions(width, height);
1510     } else {
1511         GLuint texture = getBoundTexture(target);
1512         TextureRec* texrec = getTextureRecPtr(texture);
1513         if (!texrec) return;
1514         texrec->boundEGLImage = true;
1515         setBoundTextureInternalFormat(target, GL_RGBA);
1516         setBoundTextureFormat(target, GL_RGBA);
1517         setBoundTextureType(target, GL_UNSIGNED_BYTE);
1518         setBoundTextureSamples(target, 0);
1519         setBoundTextureDims(target, target, 0, width, height, 1);
1520     }
1521 }
1522 
addTextureRec(GLuint id,GLenum target)1523 TextureRec* GLClientState::addTextureRec(GLuint id, GLenum target)
1524 {
1525     TextureRec* tex = new TextureRec;
1526     tex->id = id;
1527     tex->target = target;
1528     tex->format = -1;
1529     tex->multisamples = 0;
1530     tex->immutable = false;
1531     tex->boundEGLImage = false;
1532     tex->hasStorage = false;
1533     tex->dims = new TextureDims[6];
1534     tex->hasCubeNegX = false;
1535     tex->hasCubePosX = false;
1536     tex->hasCubeNegY = false;
1537     tex->hasCubePosY = false;
1538     tex->hasCubeNegZ = false;
1539     tex->hasCubePosZ = false;
1540 
1541     AutoWriteLock guard(m_tex.textureRecs->lock);
1542     m_tex.textureRecs->map[id] = std::shared_ptr<TextureRec>(tex);
1543     return tex;
1544 }
1545 
getTextureRec(GLuint id) const1546 std::shared_ptr<TextureRec> GLClientState::getTextureRec(GLuint id) const {
1547     AutoReadLock guard(m_tex.textureRecs->lock);
1548     SharedTextureDataMap::const_iterator it =
1549         m_tex.textureRecs->map.find(id);
1550     if (it == m_tex.textureRecs->map.end()) {
1551         return NULL;
1552     }
1553     return it->second;
1554 }
1555 
getTextureRecPtrLocked(GLuint id) const1556 TextureRec* GLClientState::getTextureRecPtrLocked(GLuint id) const {
1557     SharedTextureDataMap::const_iterator it =
1558         m_tex.textureRecs->map.find(id);
1559     if (it == m_tex.textureRecs->map.end()) {
1560         return NULL;
1561     }
1562     return it->second.get();
1563 }
1564 
getTextureRecPtr(GLuint id) const1565 TextureRec* GLClientState::getTextureRecPtr(GLuint id) const {
1566     AutoReadLock guard(m_tex.textureRecs->lock);
1567     return getTextureRecPtrLocked(id);
1568 }
1569 
setBoundTextureInternalFormat(GLenum target,GLint internalformat)1570 void GLClientState::setBoundTextureInternalFormat(GLenum target, GLint internalformat) {
1571     GLuint texture = getBoundTexture(target);
1572     TextureRec* texrec = getTextureRecPtr(texture);
1573     if (!texrec) return;
1574     texrec->internalformat = internalformat;
1575 }
1576 
setBoundTextureFormat(GLenum target,GLenum format)1577 void GLClientState::setBoundTextureFormat(GLenum target, GLenum format) {
1578     GLuint texture = getBoundTexture(target);
1579     TextureRec* texrec = getTextureRecPtr(texture);
1580     if (!texrec) return;
1581     texrec->format = format;
1582 }
1583 
setBoundTextureType(GLenum target,GLenum type)1584 void GLClientState::setBoundTextureType(GLenum target, GLenum type) {
1585     GLuint texture = getBoundTexture(target);
1586     TextureRec* texrec = getTextureRecPtr(texture);
1587     if (!texrec) return;
1588     texrec->type = type;
1589 }
1590 
textureDimArrayOfCubeTarget(GLenum cubetarget)1591 static size_t textureDimArrayOfCubeTarget(GLenum cubetarget) {
1592     switch (cubetarget) {
1593         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1594             return 0;
1595         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1596             return 1;
1597         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1598             return 2;
1599         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1600             return 3;
1601         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1602             return 4;
1603         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1604             return 5;
1605     }
1606     return 0;
1607 }
1608 
setBoundTextureDims(GLenum target,GLenum cubetarget,GLsizei level,GLsizei width,GLsizei height,GLsizei depth)1609 void GLClientState::setBoundTextureDims(GLenum target, GLenum cubetarget, GLsizei level, GLsizei width, GLsizei height, GLsizei depth) {
1610     GLuint texture = getBoundTexture(target);
1611     TextureRec* texrec = getTextureRecPtr(texture);
1612     if (!texrec) {
1613         return;
1614     }
1615 
1616     texrec->hasStorage = true;
1617 
1618     size_t indexToSet = 0;
1619 
1620     if (target == GL_TEXTURE_CUBE_MAP) {
1621         if (-1 == cubetarget) {
1622             setBoundTextureDims(target, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, width, height, depth);
1623             setBoundTextureDims(target, GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, width, height, depth);
1624             setBoundTextureDims(target, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, width, height, depth);
1625             setBoundTextureDims(target, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, width, height, depth);
1626             setBoundTextureDims(target, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, width, height, depth);
1627             setBoundTextureDims(target, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, width, height, depth);
1628             return;
1629         }
1630         indexToSet = textureDimArrayOfCubeTarget(cubetarget);
1631     }
1632 
1633 
1634     if (level == -1) {
1635         GLsizei curr_width = width;
1636         GLsizei curr_height = height;
1637         GLsizei curr_depth = depth;
1638         GLsizei curr_level = 0;
1639 
1640         while (true) {
1641             texrec->dims[indexToSet].widths[curr_level] = curr_width;
1642             texrec->dims[indexToSet].heights[curr_level] = curr_height;
1643             texrec->dims[indexToSet].depths[curr_level] = curr_depth;
1644             if (curr_width >> 1 == 0 &&
1645                 curr_height >> 1 == 0 &&
1646                 ((target == GL_TEXTURE_3D && curr_depth == 0) ||
1647                  true)) {
1648                 break;
1649             }
1650             curr_width = (curr_width >> 1) ? (curr_width >> 1) : 1;
1651             curr_height = (curr_height >> 1) ? (curr_height >> 1) : 1;
1652             if (target == GL_TEXTURE_3D) {
1653                 curr_depth = (curr_depth >> 1) ? (curr_depth >> 1) : 1;
1654             }
1655             curr_level++;
1656         }
1657 
1658     } else {
1659         texrec->dims[indexToSet].widths[level] = width;
1660         texrec->dims[indexToSet].heights[level] = height;
1661         texrec->dims[indexToSet].depths[level] = depth;
1662     }
1663 
1664     setFboCompletenessDirtyForTexture(texture);
1665 }
1666 
setBoundTextureSamples(GLenum target,GLsizei samples)1667 void GLClientState::setBoundTextureSamples(GLenum target, GLsizei samples) {
1668     GLuint texture = getBoundTexture(target);
1669     TextureRec* texrec = getTextureRecPtr(texture);
1670     if (!texrec) return;
1671     texrec->multisamples = samples;
1672 }
1673 
addTextureCubeMapImage(GLenum stateTarget,GLenum cubeTarget)1674 void GLClientState::addTextureCubeMapImage(GLenum stateTarget, GLenum cubeTarget) {
1675     if (stateTarget != GL_TEXTURE_CUBE_MAP) return;
1676 
1677     GLuint texture = getBoundTexture(stateTarget);
1678     TextureRec* texrec = getTextureRecPtr(texture);
1679     if (!texrec) return;
1680 
1681     switch (cubeTarget) {
1682         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1683             texrec->hasCubeNegX = true;
1684             return;
1685         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1686             texrec->hasCubePosX = true;
1687             return;
1688         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1689             texrec->hasCubeNegY = true;
1690             return;
1691         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1692             texrec->hasCubePosY = true;
1693             return;
1694         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1695             texrec->hasCubeNegZ = true;
1696             return;
1697         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1698             texrec->hasCubePosZ = true;
1699             return;
1700     }
1701 }
1702 
setBoundTextureImmutableFormat(GLenum target)1703 void GLClientState::setBoundTextureImmutableFormat(GLenum target) {
1704     GLuint texture = getBoundTexture(target);
1705     TextureRec* texrec = getTextureRecPtr(texture);
1706     if (!texrec) return;
1707     texrec->immutable = true;
1708     if (target == GL_TEXTURE_CUBE_MAP) {
1709         texrec->hasCubeNegX = true;
1710         texrec->hasCubePosX = true;
1711         texrec->hasCubeNegY = true;
1712         texrec->hasCubePosY = true;
1713         texrec->hasCubeNegZ = true;
1714         texrec->hasCubePosZ = true;
1715     }
1716 }
1717 
isBoundTextureImmutableFormat(GLenum target) const1718 bool GLClientState::isBoundTextureImmutableFormat(GLenum target) const {
1719     GLuint texture = getBoundTexture(target);
1720     TextureRec* texrec = getTextureRecPtr(texture);
1721     if (!texrec) return false;
1722     return texrec->immutable;
1723 }
1724 
isBoundTextureComplete(GLenum target) const1725 bool GLClientState::isBoundTextureComplete(GLenum target) const {
1726     GLuint texture = getBoundTexture(target);
1727     TextureRec* texrec = getTextureRecPtr(texture);
1728     if (!texrec) return false;
1729 
1730     if (texrec->immutable) return true;
1731     if (!texrec->hasStorage) return true;
1732 
1733     if (target == GL_TEXTURE_CUBE_MAP) {
1734         if (!(texrec->hasCubeNegX &&
1735              texrec->hasCubePosX &&
1736              texrec->hasCubeNegY &&
1737              texrec->hasCubePosY &&
1738              texrec->hasCubeNegZ &&
1739              texrec->hasCubePosZ)) return false;
1740 
1741         size_t currBaseLevel = texrec->dims[0].widths.begin()->first;
1742         size_t currWidth = texrec->dims[0].widths.begin()->second;
1743         size_t currHeight = texrec->dims[0].heights.begin()->second;
1744         for (size_t i = 1; i < 6; ++i) {
1745             size_t nextLevel = texrec->dims[i].widths.begin()->first;
1746             size_t nextWidth = texrec->dims[i].widths.begin()->second;
1747             size_t nextHeight = texrec->dims[i].heights.begin()->second;
1748             if (currBaseLevel != nextLevel) return false;
1749             if (currWidth != nextWidth) return false;
1750             if (currHeight != nextHeight) return false;
1751         }
1752 
1753         return true;
1754     }
1755 
1756     return true;
1757 }
1758 
1759 
getBoundTexture(GLenum target) const1760 GLuint GLClientState::getBoundTexture(GLenum target) const
1761 {
1762     switch (target) {
1763     case GL_TEXTURE_2D:
1764         return m_tex.activeUnit->texture[TEXTURE_2D];
1765     case GL_TEXTURE_EXTERNAL_OES:
1766         return m_tex.activeUnit->texture[TEXTURE_EXTERNAL];
1767     case GL_TEXTURE_CUBE_MAP:
1768         return m_tex.activeUnit->texture[TEXTURE_CUBE_MAP];
1769     case GL_TEXTURE_2D_ARRAY:
1770         return m_tex.activeUnit->texture[TEXTURE_2D_ARRAY];
1771     case GL_TEXTURE_3D:
1772         return m_tex.activeUnit->texture[TEXTURE_3D];
1773     case GL_TEXTURE_2D_MULTISAMPLE:
1774         return m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE];
1775     case GL_TEXTURE_BUFFER_OES:
1776         return m_tex.activeUnit->texture[TEXTURE_BUFFER];
1777     default:
1778         return 0;
1779     }
1780 }
1781 
getBoundFramebuffer(GLenum target) const1782 GLuint GLClientState::getBoundFramebuffer(GLenum target) const
1783 {
1784     switch (target) {
1785     case GL_FRAMEBUFFER:
1786     case GL_DRAW_FRAMEBUFFER:
1787         return mFboState.boundDrawFramebuffer;
1788     case GL_READ_FRAMEBUFFER:
1789         return mFboState.boundReadFramebuffer;
1790     default:
1791         return 0;
1792     }
1793 }
1794 
checkFramebufferCompleteness(GLenum target)1795 GLenum GLClientState::checkFramebufferCompleteness(GLenum target) {
1796     // Default framebuffer is complete
1797     // TODO: Check the case where the default framebuffer is 0x0
1798     if (0 == boundFramebuffer(target)) {
1799         return GL_FRAMEBUFFER_COMPLETE;
1800     }
1801 
1802     bool hasAttachment = false;
1803     FboProps& props = boundFboProps(target);
1804 
1805     if (!props.completenessDirty) {
1806         return props.cachedCompleteness;
1807     }
1808 
1809     int currentSamples = -1;
1810 
1811     for (int i = 0; i < getMaxColorAttachments(); i++) {
1812         if (!props.colorAttachmenti_hasTex[i] &&
1813             !props.colorAttachmenti_hasRbo[i]) continue;
1814 
1815         GLenum attachmentRes = checkFramebufferAttachmentCompleteness(target, glUtilsColorAttachmentName(i), &currentSamples);
1816         if (attachmentRes != GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) {
1817             hasAttachment = true;
1818         }
1819         if (attachmentRes) {
1820             ALOGD("%s: color attachment %d not complete: 0x%x\n", __func__, i, attachmentRes);
1821             return attachmentRes;
1822         }
1823     }
1824 
1825     bool hasDepth = (props.depthAttachment_hasTexObj || props.depthAttachment_hasRbo || props.depthstencilAttachment_hasTexObj || props.depthstencilAttachment_hasRbo);
1826     bool hasStencil = (props.stencilAttachment_hasTexObj || props.stencilAttachment_hasRbo || props.depthstencilAttachment_hasTexObj || props.depthstencilAttachment_hasRbo);
1827 
1828     if (hasDepth) {
1829         GLenum depthAttachmentRes = checkFramebufferAttachmentCompleteness(target, GL_DEPTH_ATTACHMENT, &currentSamples);
1830         if (depthAttachmentRes != GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) {
1831             hasAttachment = true;
1832         }
1833         if (depthAttachmentRes) {
1834             ALOGD("%s: depth attachment not complete: 0x%x\n", __func__, depthAttachmentRes);
1835             return depthAttachmentRes;
1836         }
1837     }
1838 
1839     if (hasStencil) {
1840         GLenum stencilAttachmentRes = checkFramebufferAttachmentCompleteness(target, GL_STENCIL_ATTACHMENT, &currentSamples);
1841         if (stencilAttachmentRes != GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) {
1842             hasAttachment = true;
1843         }
1844         if (stencilAttachmentRes) {
1845             ALOGD("%s: stencil attachment not complete: 0x%x\n", __func__, stencilAttachmentRes);
1846             return stencilAttachmentRes;
1847         }
1848     }
1849 
1850     if (hasDepth && hasStencil) {
1851         // In gles3, depth/stencil must use the same image.
1852         if (m_glesMajorVersion > 2) {
1853             if ((props.depthAttachment_hasTexObj && props.stencilAttachment_hasRbo) ||
1854                 (props.stencilAttachment_hasTexObj && props.depthAttachment_hasRbo)) {
1855                 ALOGD("%s: GL_FRAMEBUFFER_UNSUPPORTED: using different types of depth/stencil attachment images in GLES 3+\n", __func__);
1856                 return GL_FRAMEBUFFER_UNSUPPORTED;
1857             }
1858             if (props.depthAttachment_hasTexObj) {
1859                 if (props.depthAttachment_texture != props.stencilAttachment_texture) {
1860                     ALOGD("%s: GL_FRAMEBUFFER_UNSUPPORTED: using different texture images for depth and stencil attachments in GLES 3+\n", __func__);
1861                     return GL_FRAMEBUFFER_UNSUPPORTED;
1862                 }
1863             }
1864             if (props.depthAttachment_hasRbo) {
1865                 if (props.depthAttachment_rbo != props.stencilAttachment_rbo) {
1866                     ALOGD("%s: GL_FRAMEBUFFER_UNSUPPORTED: using different renderbuffers for depth and stencil attachments in GLES 3+\n", __func__);
1867                     return GL_FRAMEBUFFER_UNSUPPORTED;
1868                 }
1869             }
1870         }
1871     }
1872 
1873     if (!hasAttachment) {
1874         // Framebuffers may be missing an attachment if they have nonzero
1875         // default width and height
1876         if (props.defaultWidth == 0 || props.defaultHeight == 0) {
1877             return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
1878         }
1879     }
1880 
1881     props.completenessDirty = false;
1882     props.cachedCompleteness = GL_FRAMEBUFFER_COMPLETE;
1883     return GL_FRAMEBUFFER_COMPLETE;
1884 }
1885 
checkFramebufferAttachmentCompleteness(GLenum target,GLenum attachment,int * currentSamples) const1886 GLenum GLClientState::checkFramebufferAttachmentCompleteness(GLenum target, GLenum attachment, int* currentSamples) const {
1887     FboFormatInfo fbo_format_info;
1888     getBoundFramebufferFormat(target, attachment, &fbo_format_info);
1889 
1890     // Check format and renderability
1891     bool renderable = false;
1892     switch (fbo_format_info.type) {
1893         case FBO_ATTACHMENT_RENDERBUFFER:
1894             switch (attachment) {
1895                 case GL_DEPTH_ATTACHMENT:
1896                     renderable = fbo_format_info.rb_external || depthRenderableFormat(fbo_format_info.rb_format);
1897                     break;
1898                 case GL_STENCIL_ATTACHMENT:
1899                     renderable = fbo_format_info.rb_external || stencilRenderableFormat(fbo_format_info.rb_format);
1900                     break;
1901                 default:
1902                     renderable = fbo_format_info.rb_external || colorRenderableFormat(
1903                             fbo_format_info.rb_format,
1904                             GL_UNSIGNED_BYTE,
1905                             m_glesMajorVersion, m_glesMinorVersion,
1906                             m_has_color_buffer_float_extension,
1907                             m_has_color_buffer_half_float_extension);
1908                     if (!renderable) {
1909                         ALOGD("%s: rbo not color renderable. format: 0x%x\n", __func__, fbo_format_info.rb_format); }
1910                     break;
1911             }
1912             break;
1913         case FBO_ATTACHMENT_TEXTURE:
1914             switch (attachment) {
1915                 case GL_DEPTH_ATTACHMENT:
1916                     renderable = fbo_format_info.tex_external || depthRenderableFormat(fbo_format_info.tex_internalformat);
1917                     break;
1918                 case GL_STENCIL_ATTACHMENT:
1919                     renderable = fbo_format_info.tex_external || stencilRenderableFormat(fbo_format_info.tex_internalformat);
1920                     break;
1921                 default:
1922                     renderable = fbo_format_info.tex_external || colorRenderableFormat(
1923                             fbo_format_info.tex_internalformat,
1924                             fbo_format_info.tex_type,
1925                             m_glesMajorVersion, m_glesMinorVersion,
1926                             m_has_color_buffer_float_extension,
1927                             m_has_color_buffer_half_float_extension);
1928                     if (!renderable) {
1929                         ALOGD("%s: tex not color renderable. format: 0x%x type 0x%x maj min %d %d floatext %d hfloatext %d\n", __func__, fbo_format_info.tex_internalformat, fbo_format_info.tex_type, m_glesMajorVersion, m_glesMinorVersion, m_has_color_buffer_float_extension, m_has_color_buffer_half_float_extension);
1930                     }
1931                     break;
1932             }
1933             break;
1934         case FBO_ATTACHMENT_NONE:
1935         default:
1936             return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
1937     }
1938 
1939     if (!renderable) return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1940 
1941     // Check dimensions
1942     std::shared_ptr<TextureRec> texrec;
1943     std::shared_ptr<RboProps> rbo;
1944     switch (fbo_format_info.type) {
1945     case FBO_ATTACHMENT_RENDERBUFFER:
1946         rbo = getFboAttachmentRbo(target, attachment);
1947         if (!fbo_format_info.rb_external) {
1948             if (!rbo || 0 == rbo->width || 0 == rbo->height) {
1949                 ALOGD("%s: rbo has zero dimension\n", __func__);
1950                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1951             }
1952         }
1953         break;
1954     case FBO_ATTACHMENT_TEXTURE:
1955         texrec = getFboAttachmentTexture(target, attachment);
1956         if (!fbo_format_info.tex_external) {
1957             if (0 == texrec->dims->widths[fbo_format_info.tex_level] ||
1958                     0 == texrec->dims->heights[fbo_format_info.tex_level]) {
1959                 ALOGD("%s: texture has zero dimension\n", __func__);
1960                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1961             }
1962             GLsizei depth = texrec->dims->depths[fbo_format_info.tex_level];
1963             if (fbo_format_info.tex_layer >= depth) {
1964                 ALOGD("%s: texture layer/zoffset too high, wanted %d but only have %d layers\n", __func__,
1965                       fbo_format_info.tex_layer, depth);
1966                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1967             }
1968         }
1969         break;
1970     case FBO_ATTACHMENT_NONE:
1971     default:
1972         return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
1973     }
1974 
1975     // Check samples
1976     int currSamplesVal = *currentSamples;
1977     bool firstTime = -1 == currSamplesVal;
1978     int samplesThisAttachment = 0;
1979     switch (fbo_format_info.type) {
1980     case FBO_ATTACHMENT_RENDERBUFFER:
1981         samplesThisAttachment = fbo_format_info.rb_multisamples;
1982         break;
1983     case FBO_ATTACHMENT_TEXTURE:
1984         samplesThisAttachment = fbo_format_info.tex_multisamples;
1985         break;
1986     case FBO_ATTACHMENT_NONE:
1987         break;
1988     default:
1989         return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
1990     }
1991 
1992     if (firstTime) {
1993         *currentSamples = samplesThisAttachment;
1994     } else {
1995         if (samplesThisAttachment != currSamplesVal) {
1996             return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1997         }
1998     }
1999 
2000     return 0;
2001 }
2002 
2003 // BEGIN driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2004 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
2005 
unreliableInternalFormat(GLenum internalformat)2006 static bool unreliableInternalFormat(GLenum internalformat) {
2007     switch (internalformat) {
2008     case GL_LUMINANCE:
2009         return true;
2010     default:
2011         return false;
2012     }
2013 }
2014 
writeCopyTexImageState(GLenum target,GLint level,GLenum internalformat)2015 void GLClientState::writeCopyTexImageState
2016     (GLenum target, GLint level, GLenum internalformat) {
2017     if (unreliableInternalFormat(internalformat)) {
2018         CubeMapDef entry;
2019         entry.id = getBoundTexture(GL_TEXTURE_2D);
2020         entry.target = target;
2021         entry.level = level;
2022         entry.internalformat = internalformat;
2023         m_cubeMapDefs.insert(entry);
2024     }
2025 }
2026 
identifyPositiveCubeMapComponent(GLenum target)2027 static GLenum identifyPositiveCubeMapComponent(GLenum target) {
2028     switch (target) {
2029     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2030         return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2031     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2032         return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
2033     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2034         return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
2035     default:
2036         return 0;
2037     }
2038 }
2039 
copyTexImageNeededTarget(GLenum target,GLint level,GLenum internalformat)2040 GLenum GLClientState::copyTexImageNeededTarget
2041     (GLenum target, GLint level, GLenum internalformat) {
2042     if (unreliableInternalFormat(internalformat)) {
2043         GLenum positiveComponent =
2044             identifyPositiveCubeMapComponent(target);
2045         if (positiveComponent) {
2046             CubeMapDef query;
2047             query.id = getBoundTexture(GL_TEXTURE_2D);
2048             query.target = positiveComponent;
2049             query.level = level;
2050             query.internalformat = internalformat;
2051             if (m_cubeMapDefs.find(query) ==
2052                 m_cubeMapDefs.end()) {
2053                 return positiveComponent;
2054             }
2055         }
2056     }
2057     return 0;
2058 }
2059 
copyTexImageLuminanceCubeMapAMDWorkaround(GLenum target,GLint level,GLenum internalformat)2060 GLenum GLClientState::copyTexImageLuminanceCubeMapAMDWorkaround
2061     (GLenum target, GLint level, GLenum internalformat) {
2062     writeCopyTexImageState(target, level, internalformat);
2063     return copyTexImageNeededTarget(target, level, internalformat);
2064 }
2065 
2066 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
2067 // END driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2068 
deleteTextures(GLsizei n,const GLuint * textures)2069 void GLClientState::deleteTextures(GLsizei n, const GLuint* textures)
2070 {
2071     for (const GLuint* texture = textures; texture != textures + n; texture++) {
2072         setFboCompletenessDirtyForTexture(*texture);
2073     }
2074 
2075     // Updating the textures array could be made more efficient when deleting
2076     // several textures:
2077     // - compacting the array could be done in a single pass once the deleted
2078     //   textures are marked, or
2079     // - could swap deleted textures to the end and re-sort.
2080     TextureRec* texrec;
2081     for (const GLuint* texture = textures; texture != textures + n; texture++) {
2082         AutoWriteLock guard(m_tex.textureRecs->lock);
2083         texrec = getTextureRecPtrLocked(*texture);
2084         if (texrec && texrec->dims) {
2085             delete [] texrec->dims;
2086         }
2087         if (texrec) {
2088             m_tex.textureRecs->map.erase(*texture);
2089             for (TextureUnit* unit = m_tex.unit;
2090                  unit != m_tex.unit + MAX_TEXTURE_UNITS;
2091                  unit++)
2092             {
2093                 if (unit->texture[TEXTURE_2D] == *texture) {
2094                     unit->texture[TEXTURE_2D] = 0;
2095                 } else if (unit->texture[TEXTURE_EXTERNAL] == *texture) {
2096                     unit->texture[TEXTURE_EXTERNAL] = 0;
2097                 }
2098             }
2099         }
2100     }
2101 }
2102 
2103 // RBO//////////////////////////////////////////////////////////////////////////
2104 
addFreshRenderbuffer(GLuint name)2105 void GLClientState::addFreshRenderbuffer(GLuint name) {
2106     if (!name) return;
2107 
2108     RenderbufferInfo::ScopedView view(mRboState.rboData);
2109     view.addFresh(name);
2110 }
2111 
addRenderbuffers(GLsizei n,GLuint * renderbuffers)2112 void GLClientState::addRenderbuffers(GLsizei n, GLuint* renderbuffers) {
2113     for (size_t i = 0; i < n; i++) {
2114         addFreshRenderbuffer(renderbuffers[i]);
2115     }
2116 }
2117 
removeRenderbuffers(GLsizei n,const GLuint * renderbuffers)2118 void GLClientState::removeRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
2119     bool unbindCurrent = false;
2120     {
2121         RenderbufferInfo::ScopedView view(mRboState.rboData);
2122         for (size_t i = 0; i < n; i++) {
2123             if (renderbuffers[i] != 0) { // Never remove the zero rb.
2124                 auto rboPtr = view.get_shared_ptr(renderbuffers[i]);
2125                 if (!rboPtr) {
2126                     continue;
2127                 }
2128                 unbindCurrent |=
2129                         (mRboState.boundRenderbuffer == rboPtr);
2130                 setFboCompletenessDirtyForRbo(rboPtr);
2131                 view.remove(renderbuffers[i]);
2132             }
2133         }
2134     }
2135 
2136     if (unbindCurrent) {
2137         bindRenderbuffer(GL_RENDERBUFFER, 0);
2138     }
2139 }
2140 
usedRenderbufferName(GLuint name) const2141 bool GLClientState::usedRenderbufferName(GLuint name) const {
2142     if (!name) return false;
2143 
2144     RenderbufferInfo::ScopedView view(mRboState.rboData);
2145     return view.get_const(name) != 0;
2146 }
2147 
bindRenderbuffer(GLenum target,GLuint name)2148 void GLClientState::bindRenderbuffer(GLenum target, GLuint name) {
2149 
2150     (void)target; // Must be GL_RENDERBUFFER
2151     RenderbufferInfo::ScopedView view(mRboState.rboData);
2152     mRboState.boundRenderbuffer = view.bind(name);
2153 }
2154 
boundRenderbuffer() const2155 GLuint GLClientState::boundRenderbuffer() const {
2156     return mRboState.boundRenderbuffer->id;
2157 }
2158 
setBoundRenderbufferFormat(GLenum format)2159 void GLClientState::setBoundRenderbufferFormat(GLenum format) {
2160     mRboState.boundRenderbuffer->format = format;
2161 }
2162 
setBoundRenderbufferSamples(GLsizei samples)2163 void GLClientState::setBoundRenderbufferSamples(GLsizei samples) {
2164     mRboState.boundRenderbuffer->multisamples = samples;
2165 }
2166 
setBoundRenderbufferDimensions(GLsizei width,GLsizei height)2167 void GLClientState::setBoundRenderbufferDimensions(GLsizei width, GLsizei height) {
2168     mRboState.boundRenderbuffer->width = width;
2169     mRboState.boundRenderbuffer->height = height;
2170 }
2171 
setBoundRenderbufferEGLImageBacked()2172 void GLClientState::setBoundRenderbufferEGLImageBacked() {
2173     mRboState.boundRenderbuffer->boundEGLImage = true;
2174 }
2175 
2176 // FBO//////////////////////////////////////////////////////////////////////////
2177 
queryTexInternalFormat(GLuint tex_name) const2178 GLint GLClientState::queryTexInternalFormat(GLuint tex_name) const {
2179     TextureRec* texrec = getTextureRecPtr(tex_name);
2180     if (!texrec) return -1;
2181     return texrec->internalformat;
2182 }
2183 
queryTexWidth(GLsizei level,GLuint tex_name) const2184 GLsizei GLClientState::queryTexWidth(GLsizei level, GLuint tex_name) const {
2185     TextureRec* texrec = getTextureRecPtr(tex_name);
2186     if (!texrec) {
2187         return 0;
2188     }
2189     return texrec->dims->widths[level];
2190 }
2191 
queryTexHeight(GLsizei level,GLuint tex_name) const2192 GLsizei GLClientState::queryTexHeight(GLsizei level, GLuint tex_name) const {
2193     TextureRec* texrec = getTextureRecPtr(tex_name);
2194     if (!texrec) return 0;
2195     return texrec->dims->heights[level];
2196 }
2197 
queryTexDepth(GLsizei level,GLuint tex_name) const2198 GLsizei GLClientState::queryTexDepth(GLsizei level, GLuint tex_name) const {
2199     TextureRec* texrec = getTextureRecPtr(tex_name);
2200     if (!texrec) return 0;
2201     return texrec->dims->depths[level];
2202 }
2203 
queryTexEGLImageBacked(GLuint tex_name) const2204 bool GLClientState::queryTexEGLImageBacked(GLuint tex_name) const {
2205     TextureRec* texrec = getTextureRecPtr(tex_name);
2206     if (!texrec) return false;
2207     return texrec->boundEGLImage;
2208 }
2209 
queryTexFormat(GLuint tex_name) const2210 GLenum GLClientState::queryTexFormat(GLuint tex_name) const {
2211     TextureRec* texrec = getTextureRecPtr(tex_name);
2212     if (!texrec) return -1;
2213     return texrec->format;
2214 }
2215 
queryTexType(GLuint tex_name) const2216 GLenum GLClientState::queryTexType(GLuint tex_name) const {
2217     TextureRec* texrec = getTextureRecPtr(tex_name);
2218     if (!texrec) return -1;
2219     return texrec->type;
2220 }
2221 
queryTexSamples(GLuint tex_name) const2222 GLsizei GLClientState::queryTexSamples(GLuint tex_name) const {
2223     TextureRec* texrec = getTextureRecPtr(tex_name);
2224     if (!texrec) return 0;
2225     return texrec->multisamples;
2226 }
2227 
queryTexLastBoundTarget(GLuint tex_name) const2228 GLenum GLClientState::queryTexLastBoundTarget(GLuint tex_name) const {
2229     TextureRec* texrec = getTextureRecPtr(tex_name);
2230     if (!texrec) return GL_NONE;
2231     return texrec->target;
2232 }
2233 
getBoundFramebufferFormat(GLenum target,GLenum attachment,FboFormatInfo * res_info) const2234 void GLClientState::getBoundFramebufferFormat(
2235         GLenum target,
2236         GLenum attachment, FboFormatInfo* res_info) const {
2237     const FboProps& props = boundFboProps_const(target);
2238 
2239     res_info->type = FBO_ATTACHMENT_NONE;
2240     res_info->rb_format = GL_NONE;
2241     res_info->rb_multisamples = 0;
2242     res_info->rb_external = false;
2243     res_info->tex_internalformat = -1;
2244     res_info->tex_format = GL_NONE;
2245     res_info->tex_type = GL_NONE;
2246     res_info->tex_multisamples = 0;
2247     res_info->tex_external = false;
2248 
2249     int colorAttachmentIndex =
2250         glUtilsColorAttachmentIndex(attachment);
2251 
2252     if (colorAttachmentIndex != -1) {
2253         if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
2254             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
2255             res_info->rb_format = props.colorAttachmenti_rbos[colorAttachmentIndex]->format;
2256             res_info->rb_multisamples =
2257                     props.colorAttachmenti_rbos[colorAttachmentIndex]->multisamples;
2258             res_info->rb_external =
2259                     props.colorAttachmenti_rbos[colorAttachmentIndex]->boundEGLImage;
2260         } else if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
2261             res_info->type = FBO_ATTACHMENT_TEXTURE;
2262             res_info->tex_external =
2263                     props.colorAttachmenti_textures[colorAttachmentIndex]->boundEGLImage;
2264             res_info->tex_internalformat =
2265                     props.colorAttachmenti_textures[colorAttachmentIndex]->internalformat;
2266             res_info->tex_format =
2267                     props.colorAttachmenti_textures[colorAttachmentIndex]->format;
2268             res_info->tex_type =
2269                     props.colorAttachmenti_textures[colorAttachmentIndex]->type;
2270             res_info->tex_multisamples =
2271                     props.colorAttachmenti_textures[colorAttachmentIndex]->multisamples;
2272             res_info->tex_level = props.colorAttachmenti_texture_levels[colorAttachmentIndex];
2273             res_info->tex_layer = props.colorAttachmenti_texture_layers[colorAttachmentIndex];
2274         } else {
2275             res_info->type = FBO_ATTACHMENT_NONE;
2276         }
2277     }
2278 
2279     switch (attachment) {
2280     case GL_DEPTH_ATTACHMENT:
2281         if (props.depthAttachment_hasRbo) {
2282             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
2283             res_info->rb_format = props.depthAttachment_rbo->format;
2284             res_info->rb_multisamples = props.depthAttachment_rbo->multisamples;
2285             res_info->rb_external = props.depthAttachment_rbo->boundEGLImage;
2286         } else if (props.depthAttachment_hasTexObj) {
2287             res_info->type = FBO_ATTACHMENT_TEXTURE;
2288             res_info->tex_external = props.depthAttachment_texture->boundEGLImage;
2289             res_info->tex_internalformat = props.depthAttachment_texture->internalformat;
2290             res_info->tex_format = props.depthAttachment_texture->format;
2291             res_info->tex_type = props.depthAttachment_texture->type;
2292             res_info->tex_multisamples = props.depthAttachment_texture->multisamples;
2293             res_info->tex_level = props.depthAttachment_texture_level;
2294             res_info->tex_layer = props.depthAttachment_texture_layer;
2295         } else {
2296             res_info->type = FBO_ATTACHMENT_NONE;
2297         }
2298         break;
2299     case GL_STENCIL_ATTACHMENT:
2300         if (props.stencilAttachment_hasRbo) {
2301             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
2302             res_info->rb_format = props.stencilAttachment_rbo->format;
2303             res_info->rb_multisamples = props.stencilAttachment_rbo->multisamples;
2304             res_info->rb_external = props.stencilAttachment_rbo->boundEGLImage;
2305         } else if (props.stencilAttachment_hasTexObj) {
2306             res_info->type = FBO_ATTACHMENT_TEXTURE;
2307             res_info->tex_external = props.stencilAttachment_texture->boundEGLImage;
2308             res_info->tex_internalformat = props.stencilAttachment_texture->internalformat;
2309             res_info->tex_format = props.stencilAttachment_texture->format;
2310             res_info->tex_type = props.stencilAttachment_texture->type;
2311             res_info->tex_multisamples = props.stencilAttachment_texture->multisamples;
2312             res_info->tex_level = props.depthAttachment_texture_level;
2313             res_info->tex_layer = props.depthAttachment_texture_layer;
2314         } else {
2315             res_info->type = FBO_ATTACHMENT_NONE;
2316         }
2317         break;
2318     case GL_DEPTH_STENCIL_ATTACHMENT:
2319         if (props.depthstencilAttachment_hasRbo) {
2320             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
2321             res_info->rb_format = props.depthstencilAttachment_rbo->format;
2322             res_info->rb_multisamples = props.depthstencilAttachment_rbo->multisamples;
2323             res_info->rb_external = props.depthstencilAttachment_rbo->boundEGLImage;
2324         } else if (props.depthstencilAttachment_hasTexObj) {
2325             res_info->type = FBO_ATTACHMENT_TEXTURE;
2326             res_info->tex_external = props.depthstencilAttachment_texture->boundEGLImage;
2327             res_info->tex_internalformat = props.depthstencilAttachment_texture->internalformat;
2328             res_info->tex_format = props.depthstencilAttachment_texture->format;
2329             res_info->tex_type = props.depthstencilAttachment_texture->type;
2330             res_info->tex_multisamples = props.depthstencilAttachment_texture->multisamples;
2331             res_info->tex_level = props.depthAttachment_texture_level;
2332             res_info->tex_layer = props.depthAttachment_texture_layer;
2333         } else {
2334             res_info->type = FBO_ATTACHMENT_NONE;
2335         }
2336         break;
2337     }
2338 }
2339 
getBoundFramebufferAttachmentType(GLenum target,GLenum attachment) const2340 FboAttachmentType GLClientState::getBoundFramebufferAttachmentType(GLenum target, GLenum attachment) const {
2341     FboFormatInfo info;
2342     getBoundFramebufferFormat(target, attachment, &info);
2343     return info.type;
2344 }
2345 
getMaxColorAttachments() const2346 int GLClientState::getMaxColorAttachments() const {
2347     return m_hostDriverCaps.max_color_attachments;
2348 }
2349 
getMaxDrawBuffers() const2350 int GLClientState::getMaxDrawBuffers() const {
2351     return m_hostDriverCaps.max_draw_buffers;
2352 }
2353 
2354 #define UNIFORM_VALIDATION_ERR_COND(cond, code) if (cond) { *err = code; return; }
2355 
2356 #define UNIFORM_VALIDATION_INFO_VAR_NAME info
2357 
2358 #define UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_FLOATS \
2359     (!(UNIFORM_VALIDATION_INFO_VAR_NAME->isBool) && (UNIFORM_VALIDATION_INFO_VAR_NAME->isInt || UNIFORM_VALIDATION_INFO_VAR_NAME->isSampler))
2360 
2361 #define UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_INTS \
2362     (!(UNIFORM_VALIDATION_INFO_VAR_NAME->isBool) && (!UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_FLOATS || UNIFORM_VALIDATION_INFO_VAR_NAME->isUnsigned))
2363 
2364 #define UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_UNSIGNED_INTS \
2365     (!(UNIFORM_VALIDATION_INFO_VAR_NAME->isBool) && (!UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_FLOATS || !(UNIFORM_VALIDATION_INFO_VAR_NAME->isUnsigned)))
2366 
2367 #define UNIFORM_VALIDATION_INLINING
2368 
validateUniform(bool isFloat,bool isUnsigned,GLint columns,GLint rows,GLint location,GLsizei count,GLenum * err)2369 void GLClientState::validateUniform(bool isFloat, bool isUnsigned, GLint columns, GLint rows, GLint location, GLsizei count, GLenum* err) {
2370     UNIFORM_VALIDATION_ERR_COND(!m_currentProgram && !m_currentShaderProgram, GL_INVALID_OPERATION);
2371     if (-1 == location) return;
2372     auto info = currentUniformValidationInfo.get_const(location);
2373     UNIFORM_VALIDATION_ERR_COND(!info || !info->valid, GL_INVALID_OPERATION);
2374     UNIFORM_VALIDATION_ERR_COND(columns != info->columns || rows != info->rows, GL_INVALID_OPERATION);
2375     UNIFORM_VALIDATION_ERR_COND(count > 1 && !info->isArray, GL_INVALID_OPERATION);
2376     if (isFloat) {
2377         UNIFORM_VALIDATION_ERR_COND(UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_FLOATS, GL_INVALID_OPERATION);
2378     } else {
2379         if (isUnsigned) {
2380             UNIFORM_VALIDATION_ERR_COND(UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_UNSIGNED_INTS, GL_INVALID_OPERATION);
2381         } else {
2382             UNIFORM_VALIDATION_ERR_COND(UNIFORM_VALIDATION_TYPE_VIOLATION_FOR_INTS, GL_INVALID_OPERATION);
2383         }
2384     }
2385 }
2386 
isAttribIndexUsedByProgram(int index)2387 bool GLClientState::isAttribIndexUsedByProgram(int index) {
2388     auto info = currentAttribValidationInfo.get_const(index);
2389     if (!info) return false;
2390     if (!info->validInProgram) return false;
2391     return true;
2392 }
2393 
addFreshFramebuffer(GLuint name)2394 void GLClientState::addFreshFramebuffer(GLuint name) {
2395     FboProps props;
2396     props.name = name;
2397     props.previouslyBound = false;
2398 
2399     props.completenessDirty = true;
2400 
2401     props.colorAttachmenti_textures.resize(m_hostDriverCaps.max_color_attachments, 0);
2402     props.colorAttachmenti_texture_levels.resize(m_hostDriverCaps.max_color_attachments, 0);
2403     props.colorAttachmenti_texture_layers.resize(m_hostDriverCaps.max_color_attachments, 0);
2404 
2405     props.depthAttachment_texture_level = 0;
2406     props.depthAttachment_texture_layer = 0;
2407     props.stencilAttachment_texture_level = 0;
2408     props.stencilAttachment_texture_layer = 0;
2409 
2410     props.depthAttachment_texture = 0;
2411     props.stencilAttachment_texture = 0;
2412     props.depthstencilAttachment_texture = 0;
2413 
2414     props.colorAttachmenti_hasTex.resize(m_hostDriverCaps.max_color_attachments, false);
2415     props.depthAttachment_hasTexObj = false;
2416     props.stencilAttachment_hasTexObj = false;
2417     props.depthstencilAttachment_hasTexObj = false;
2418 
2419     props.colorAttachmenti_rbos.resize(m_hostDriverCaps.max_color_attachments, 0);
2420     props.depthAttachment_rbo = 0;
2421     props.stencilAttachment_rbo = 0;
2422     props.depthstencilAttachment_rbo = 0;
2423 
2424     props.colorAttachmenti_hasRbo.resize(m_hostDriverCaps.max_color_attachments, false);
2425     props.depthAttachment_hasRbo = false;
2426     props.stencilAttachment_hasRbo = false;
2427     props.depthstencilAttachment_hasRbo = false;
2428 
2429     props.defaultWidth = 0;
2430     props.defaultHeight = 0;
2431 
2432     mFboState.fboData[name] = props;
2433 }
2434 
addFramebuffers(GLsizei n,GLuint * framebuffers)2435 void GLClientState::addFramebuffers(GLsizei n, GLuint* framebuffers) {
2436     for (size_t i = 0; i < n; i++) {
2437         addFreshFramebuffer(framebuffers[i]);
2438     }
2439 }
2440 
removeFramebuffers(GLsizei n,const GLuint * framebuffers)2441 void GLClientState::removeFramebuffers(GLsizei n, const GLuint* framebuffers) {
2442     RenderbufferInfo::ScopedView view(mRboState.rboData);
2443     for (size_t i = 0; i < n; i++) {
2444         if (framebuffers[i] != 0) { // Never remove the zero fb.
2445             if (framebuffers[i] == mFboState.boundDrawFramebuffer) {
2446                 bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
2447             }
2448             if (framebuffers[i] == mFboState.boundReadFramebuffer) {
2449                 bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
2450             }
2451             mFboState.fboData.erase(framebuffers[i]);
2452         }
2453     }
2454 }
2455 
usedFramebufferName(GLuint name) const2456 bool GLClientState::usedFramebufferName(GLuint name) const {
2457     return mFboState.fboData.find(name) != mFboState.fboData.end();
2458 }
2459 
boundFboProps(GLenum target)2460 FboProps& GLClientState::boundFboProps(GLenum target) {
2461     switch (target) {
2462     case GL_DRAW_FRAMEBUFFER:
2463         return mFboState.fboData[mFboState.boundDrawFramebuffer];
2464     case GL_READ_FRAMEBUFFER:
2465         return mFboState.fboData[mFboState.boundReadFramebuffer];
2466     case GL_FRAMEBUFFER:
2467         return mFboState.fboData[mFboState.boundDrawFramebuffer];
2468     }
2469     return mFboState.fboData[mFboState.boundDrawFramebuffer];
2470 }
2471 
boundFboProps_const(GLenum target) const2472 const FboProps& GLClientState::boundFboProps_const(GLenum target) const {
2473     switch (target) {
2474     case GL_DRAW_FRAMEBUFFER:
2475         return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
2476     case GL_READ_FRAMEBUFFER:
2477         return mFboState.fboData.find(mFboState.boundReadFramebuffer)->second;
2478     case GL_FRAMEBUFFER:
2479         return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
2480     }
2481     return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
2482 }
2483 
bindFramebuffer(GLenum target,GLuint name)2484 void GLClientState::bindFramebuffer(GLenum target, GLuint name) {
2485     // If unused, add it.
2486     if (!usedFramebufferName(name)) {
2487         addFreshFramebuffer(name);
2488     }
2489     switch (target) {
2490         case GL_DRAW_FRAMEBUFFER:
2491             mFboState.boundDrawFramebuffer = name;
2492             break;
2493         case GL_READ_FRAMEBUFFER:
2494             mFboState.boundReadFramebuffer = name;
2495             break;
2496         default: // case GL_FRAMEBUFFER:
2497             mFboState.boundDrawFramebuffer = name;
2498             mFboState.boundReadFramebuffer = name;
2499             break;
2500     }
2501     boundFboProps(target).previouslyBound = true;
2502 }
2503 
setCheckFramebufferStatus(GLenum target,GLenum status)2504 void GLClientState::setCheckFramebufferStatus(GLenum target, GLenum status) {
2505     switch (target) {
2506         case GL_DRAW_FRAMEBUFFER:
2507             mFboState.drawFboCheckStatus = status;
2508             break;
2509         case GL_READ_FRAMEBUFFER:
2510             mFboState.readFboCheckStatus = status;
2511             break;
2512         case GL_FRAMEBUFFER:
2513             mFboState.drawFboCheckStatus = status;
2514             break;
2515     }
2516 }
2517 
setFramebufferParameter(GLenum target,GLenum pname,GLint param)2518 void GLClientState::setFramebufferParameter(GLenum target, GLenum pname, GLint param) {
2519     switch (pname) {
2520         case GL_FRAMEBUFFER_DEFAULT_WIDTH:
2521             boundFboProps(target).defaultWidth = param;
2522             boundFboProps(target).completenessDirty = true;
2523             break;
2524         case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
2525             boundFboProps(target).defaultHeight = param;
2526             boundFboProps(target).completenessDirty = true;
2527             break;
2528     }
2529 }
2530 
getCheckFramebufferStatus(GLenum target) const2531 GLenum GLClientState::getCheckFramebufferStatus(GLenum target) const {
2532     switch (target) {
2533     case GL_DRAW_FRAMEBUFFER:
2534         return mFboState.drawFboCheckStatus;
2535     case GL_READ_FRAMEBUFFER:
2536         return mFboState.readFboCheckStatus;
2537     case GL_FRAMEBUFFER:
2538         return mFboState.drawFboCheckStatus;
2539     }
2540     return mFboState.drawFboCheckStatus;
2541 }
2542 
boundFramebuffer(GLenum target) const2543 GLuint GLClientState::boundFramebuffer(GLenum target) const {
2544     return boundFboProps_const(target).name;
2545 }
2546 
2547 // Texture objects for FBOs/////////////////////////////////////////////////////
2548 
attachTextureObject(GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer)2549 void GLClientState::attachTextureObject(
2550         GLenum target,
2551         GLenum attachment, GLuint texture, GLint level, GLint layer) {
2552 
2553     bool attach = texture != 0;
2554     std::shared_ptr<TextureRec> texrec = getTextureRec(texture);
2555 
2556     int colorAttachmentIndex =
2557         glUtilsColorAttachmentIndex(attachment);
2558 
2559     boundFboProps(target).completenessDirty = true;
2560 
2561     if (colorAttachmentIndex != -1) {
2562         boundFboProps(target).colorAttachmenti_textures[colorAttachmentIndex] = texrec;
2563         boundFboProps(target).colorAttachmenti_texture_levels[colorAttachmentIndex] = level;
2564         boundFboProps(target).colorAttachmenti_texture_layers[colorAttachmentIndex] = layer;
2565         boundFboProps(target).colorAttachmenti_hasTex[colorAttachmentIndex] = attach;
2566     }
2567 
2568     switch (attachment) {
2569     case GL_DEPTH_ATTACHMENT:
2570         boundFboProps(target).depthAttachment_texture = texrec;
2571         boundFboProps(target).depthAttachment_texture_level = level;
2572         boundFboProps(target).depthAttachment_texture_layer = layer;
2573         boundFboProps(target).depthAttachment_hasTexObj = attach;
2574         break;
2575     case GL_STENCIL_ATTACHMENT:
2576         boundFboProps(target).stencilAttachment_texture = texrec;
2577         boundFboProps(target).stencilAttachment_texture_level = level;
2578         boundFboProps(target).stencilAttachment_texture_layer = layer;
2579         boundFboProps(target).stencilAttachment_hasTexObj = attach;
2580         break;
2581     case GL_DEPTH_STENCIL_ATTACHMENT:
2582         boundFboProps(target).depthstencilAttachment_texture = texrec;
2583         boundFboProps(target).depthstencilAttachment_hasTexObj = attach;
2584         boundFboProps(target).stencilAttachment_texture = texrec;
2585         boundFboProps(target).stencilAttachment_hasTexObj = attach;
2586         boundFboProps(target).depthAttachment_texture = texrec;
2587         boundFboProps(target).depthAttachment_hasTexObj = attach;
2588         boundFboProps(target).depthAttachment_texture_level = level;
2589         boundFboProps(target).depthAttachment_texture_layer = layer;
2590         boundFboProps(target).stencilAttachment_texture_level = level;
2591         boundFboProps(target).stencilAttachment_texture_layer = layer;
2592         break;
2593     }
2594 }
2595 
getFboAttachmentTexture(GLenum target,GLenum attachment) const2596 std::shared_ptr<TextureRec> GLClientState::getFboAttachmentTexture(GLenum target, GLenum attachment) const {
2597     std::shared_ptr<TextureRec> res = {}; // conservative
2598 
2599     int colorAttachmentIndex =
2600         glUtilsColorAttachmentIndex(attachment);
2601 
2602     if (colorAttachmentIndex != -1) {
2603         res = boundFboProps_const(target).colorAttachmenti_textures[colorAttachmentIndex];
2604     }
2605 
2606     switch (attachment) {
2607     case GL_DEPTH_ATTACHMENT:
2608         res = boundFboProps_const(target).depthAttachment_texture;
2609         break;
2610     case GL_STENCIL_ATTACHMENT:
2611         res = boundFboProps_const(target).stencilAttachment_texture;
2612         break;
2613     case GL_DEPTH_STENCIL_ATTACHMENT:
2614         res = boundFboProps_const(target).depthstencilAttachment_texture;
2615         break;
2616     }
2617     return res;
2618 }
2619 
2620 // RBOs for FBOs////////////////////////////////////////////////////////////////
2621 
detachRbo(GLuint renderbuffer)2622 void GLClientState::detachRbo(GLuint renderbuffer) {
2623     for (int i = 0; i < m_hostDriverCaps.max_color_attachments; i++) {
2624         detachRboFromFbo(GL_DRAW_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
2625         detachRboFromFbo(GL_READ_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
2626     }
2627 
2628     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
2629     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
2630 
2631     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
2632     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
2633 
2634     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
2635     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
2636 }
2637 
detachRboFromFbo(GLenum target,GLenum attachment,GLuint renderbuffer)2638 void GLClientState::detachRboFromFbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
2639     int colorAttachmentIndex =
2640         glUtilsColorAttachmentIndex(attachment);
2641 
2642     boundFboProps(target).completenessDirty = true;
2643 
2644     RenderbufferInfo::ScopedView view(mRboState.rboData);
2645     auto renderBufferSharedPtr = view.get_shared_ptr(renderbuffer);
2646     if (colorAttachmentIndex != -1) {
2647         if (boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] &&
2648             boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex]
2649                     == renderBufferSharedPtr) {
2650             boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = nullptr;
2651             boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = false;
2652         }
2653     }
2654 
2655     switch (attachment) {
2656     case GL_DEPTH_ATTACHMENT:
2657         if (boundFboProps(target).depthAttachment_rbo == renderBufferSharedPtr &&
2658             boundFboProps(target).depthAttachment_hasRbo) {
2659             boundFboProps(target).depthAttachment_rbo = nullptr;
2660             boundFboProps(target).depthAttachment_hasRbo = false;
2661         }
2662         break;
2663     case GL_STENCIL_ATTACHMENT:
2664         if (boundFboProps(target).stencilAttachment_rbo == renderBufferSharedPtr &&
2665             boundFboProps(target).stencilAttachment_hasRbo) {
2666             boundFboProps(target).stencilAttachment_rbo = nullptr;
2667             boundFboProps(target).stencilAttachment_hasRbo = false;
2668         }
2669         break;
2670     case GL_DEPTH_STENCIL_ATTACHMENT:
2671         if (boundFboProps(target).depthAttachment_rbo == renderBufferSharedPtr &&
2672             boundFboProps(target).depthAttachment_hasRbo) {
2673             boundFboProps(target).depthAttachment_rbo = nullptr;
2674             boundFboProps(target).depthAttachment_hasRbo = false;
2675         }
2676         if (boundFboProps(target).stencilAttachment_rbo == renderBufferSharedPtr &&
2677             boundFboProps(target).stencilAttachment_hasRbo) {
2678             boundFboProps(target).stencilAttachment_rbo = nullptr;
2679             boundFboProps(target).stencilAttachment_hasRbo = false;
2680         }
2681         if (boundFboProps(target).depthstencilAttachment_rbo == renderBufferSharedPtr &&
2682             boundFboProps(target).depthstencilAttachment_hasRbo) {
2683             boundFboProps(target).depthstencilAttachment_rbo = nullptr;
2684             boundFboProps(target).depthstencilAttachment_hasRbo = false;
2685         }
2686         break;
2687     }
2688 }
2689 
attachRbo(GLenum target,GLenum attachment,GLuint renderbuffer)2690 void GLClientState::attachRbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
2691 
2692     bool attach = 0 != renderbuffer;
2693 
2694     int colorAttachmentIndex =
2695         glUtilsColorAttachmentIndex(attachment);
2696 
2697     boundFboProps(target).completenessDirty = true;
2698 
2699     RenderbufferInfo::ScopedView view(mRboState.rboData);
2700     auto rboSharedPtr = view.get_or_add_shared_ptr(renderbuffer);
2701     if (colorAttachmentIndex != -1) {
2702         boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = rboSharedPtr;
2703         boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = attach;
2704     }
2705 
2706     switch (attachment) {
2707     case GL_DEPTH_ATTACHMENT:
2708         boundFboProps(target).depthAttachment_rbo = rboSharedPtr;
2709         boundFboProps(target).depthAttachment_hasRbo = attach;
2710         break;
2711     case GL_STENCIL_ATTACHMENT:
2712         boundFboProps(target).stencilAttachment_rbo = rboSharedPtr;
2713         boundFboProps(target).stencilAttachment_hasRbo = attach;
2714         break;
2715     case GL_DEPTH_STENCIL_ATTACHMENT:
2716         boundFboProps(target).depthAttachment_rbo = rboSharedPtr;
2717         boundFboProps(target).depthAttachment_hasRbo = attach;
2718         boundFboProps(target).stencilAttachment_rbo = rboSharedPtr;
2719         boundFboProps(target).stencilAttachment_hasRbo = attach;
2720         boundFboProps(target).depthstencilAttachment_rbo = rboSharedPtr;
2721         boundFboProps(target).depthstencilAttachment_hasRbo = attach;
2722         break;
2723     }
2724 }
2725 
getFboAttachmentRbo(GLenum target,GLenum attachment) const2726 std::shared_ptr<RboProps> GLClientState::getFboAttachmentRbo(GLenum target, GLenum attachment) const {
2727     int colorAttachmentIndex =
2728         glUtilsColorAttachmentIndex(attachment);
2729 
2730     if (colorAttachmentIndex != -1) {
2731         return boundFboProps_const(target).colorAttachmenti_rbos[colorAttachmentIndex];
2732     }
2733 
2734     switch (attachment) {
2735     case GL_DEPTH_ATTACHMENT:
2736         return  boundFboProps_const(target).depthAttachment_rbo;
2737     case GL_STENCIL_ATTACHMENT:
2738         return  boundFboProps_const(target).stencilAttachment_rbo;
2739     case GL_DEPTH_STENCIL_ATTACHMENT:
2740         return  boundFboProps_const(target).depthstencilAttachment_rbo;
2741     }
2742 
2743     // Bad attachment enum. Should be unreachable.
2744     return nullptr;
2745 }
2746 
setFboCompletenessDirtyForTexture(GLuint texture)2747 void GLClientState::setFboCompletenessDirtyForTexture(GLuint texture) {
2748     std::shared_ptr<TextureRec> texrec = getTextureRec(texture);
2749     std::map<GLuint, FboProps>::iterator it = mFboState.fboData.begin();
2750     while (it != mFboState.fboData.end()) {
2751         FboProps& props = it->second;
2752         for (int i = 0; i < m_hostDriverCaps.max_color_attachments; ++i) {
2753             if (props.colorAttachmenti_hasTex[i]) {
2754                 if (texrec == props.colorAttachmenti_textures[i]) {
2755                     props.completenessDirty = true;
2756                     return;
2757                 }
2758             }
2759         }
2760 
2761         if (props.depthAttachment_hasTexObj) {
2762             if (texrec == props.depthAttachment_texture) {
2763                     props.completenessDirty = true;
2764                     return;
2765             }
2766         }
2767 
2768         if (props.stencilAttachment_hasTexObj) {
2769             if (texrec == props.stencilAttachment_texture) {
2770                 props.completenessDirty = true;
2771                 return;
2772             }
2773         }
2774 
2775         if (props.depthstencilAttachment_hasTexObj) {
2776             if (texrec == props.depthstencilAttachment_texture) {
2777                 props.completenessDirty = true;
2778                 return;
2779             }
2780         }
2781         ++it;
2782     }
2783 }
2784 
setFboCompletenessDirtyForRbo(std::shared_ptr<RboProps> rbo)2785 void GLClientState::setFboCompletenessDirtyForRbo(std::shared_ptr<RboProps> rbo) {
2786     std::map<GLuint, FboProps>::iterator it = mFboState.fboData.begin();
2787     while (it != mFboState.fboData.end()) {
2788         FboProps& props = it->second;
2789         for (int i = 0; i < m_hostDriverCaps.max_color_attachments; ++i) {
2790             if (props.colorAttachmenti_hasRbo[i]) {
2791                 if (rbo == props.colorAttachmenti_rbos[i]) {
2792                     props.completenessDirty = true;
2793                     return;
2794                 }
2795             }
2796         }
2797 
2798         if (props.depthAttachment_hasRbo) {
2799             if (rbo == props.depthAttachment_rbo) {
2800                     props.completenessDirty = true;
2801                     return;
2802             }
2803         }
2804 
2805         if (props.stencilAttachment_hasRbo) {
2806             if (rbo == props.stencilAttachment_rbo) {
2807                 props.completenessDirty = true;
2808                 return;
2809             }
2810         }
2811 
2812         if (props.depthstencilAttachment_hasRbo) {
2813             if (rbo == props.depthstencilAttachment_rbo) {
2814                 props.completenessDirty = true;
2815                 return;
2816             }
2817         }
2818         ++it;
2819     }
2820 }
2821 
attachmentHasObject(GLenum target,GLenum attachment) const2822 bool GLClientState::attachmentHasObject(GLenum target, GLenum attachment) const {
2823     bool res = true; // liberal
2824 
2825     int colorAttachmentIndex =
2826         glUtilsColorAttachmentIndex(attachment);
2827 
2828     if (colorAttachmentIndex != -1) {
2829         res = boundFboProps_const(target).colorAttachmenti_hasTex[colorAttachmentIndex] ||
2830               boundFboProps_const(target).colorAttachmenti_hasRbo[colorAttachmentIndex];
2831     }
2832 
2833     switch (attachment) {
2834     case GL_DEPTH_ATTACHMENT:
2835         res = (boundFboProps_const(target).depthAttachment_hasTexObj) ||
2836               (boundFboProps_const(target).depthAttachment_hasRbo);
2837         break;
2838     case GL_STENCIL_ATTACHMENT:
2839         res = (boundFboProps_const(target).stencilAttachment_hasTexObj) ||
2840               (boundFboProps_const(target).stencilAttachment_hasRbo);
2841         break;
2842     case GL_DEPTH_STENCIL_ATTACHMENT:
2843         res = (boundFboProps_const(target).depthstencilAttachment_hasTexObj) ||
2844               (boundFboProps_const(target).depthstencilAttachment_hasRbo);
2845         break;
2846     }
2847     return res;
2848 }
2849 
depthStencilHasSameObject(GLenum target) const2850 bool GLClientState::depthStencilHasSameObject(GLenum target) const {
2851     const FboProps& props = boundFboProps_const(target);
2852 
2853     if (props.depthAttachment_hasTexObj != props.stencilAttachment_hasTexObj
2854             || props.depthAttachment_hasRbo != props.stencilAttachment_hasRbo) {
2855         return false;
2856     }
2857     if (props.depthAttachment_hasTexObj) {
2858         return props.depthAttachment_texture == props.stencilAttachment_texture;
2859     }
2860     if (props.depthAttachment_hasRbo) {
2861         return props.depthAttachment_rbo == props.stencilAttachment_rbo;
2862     }
2863     // No attachment in either
2864     return true;
2865 }
2866 
setTransformFeedbackActive(bool active)2867 void GLClientState::setTransformFeedbackActive(bool active) {
2868     m_transformFeedbackActive = active;
2869 }
2870 
setTransformFeedbackUnpaused(bool unpaused)2871 void GLClientState::setTransformFeedbackUnpaused(bool unpaused) {
2872     m_transformFeedbackUnpaused = unpaused;
2873 }
2874 
setTransformFeedbackVaryingsCountForLinking(uint32_t count)2875 void GLClientState::setTransformFeedbackVaryingsCountForLinking(uint32_t count) {
2876     m_transformFeedbackVaryingsCountForLinking = count;
2877 }
2878 
getTransformFeedbackActive() const2879 bool GLClientState::getTransformFeedbackActive() const {
2880     return m_transformFeedbackActive;
2881 }
2882 
getTransformFeedbackUnpaused() const2883 bool GLClientState::getTransformFeedbackUnpaused() const {
2884     return m_transformFeedbackUnpaused;
2885 }
2886 
getTransformFeedbackActiveUnpaused() const2887 bool GLClientState::getTransformFeedbackActiveUnpaused() const {
2888     return m_transformFeedbackActive && m_transformFeedbackUnpaused;
2889 }
2890 
getTransformFeedbackVaryingsCountForLinking() const2891 uint32_t GLClientState::getTransformFeedbackVaryingsCountForLinking() const {
2892     return m_transformFeedbackVaryingsCountForLinking;
2893 }
2894 
stencilFuncSeparate(GLenum face,GLenum func,GLint ref,GLuint mask)2895 void GLClientState::stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) {
2896     if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
2897         state_GL_STENCIL_FUNC = func;
2898         state_GL_STENCIL_REF = ref;
2899         state_GL_STENCIL_VALUE_MASK = mask;
2900     }
2901 
2902     if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
2903         state_GL_STENCIL_BACK_FUNC = func;
2904         state_GL_STENCIL_BACK_REF = ref;
2905         state_GL_STENCIL_BACK_VALUE_MASK = mask;
2906     }
2907 }
2908 
stencilMaskSeparate(GLenum face,GLuint mask)2909 void GLClientState::stencilMaskSeparate(GLenum face, GLuint mask) {
2910     if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
2911         state_GL_STENCIL_WRITEMASK = mask;
2912     }
2913 
2914     if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
2915         state_GL_STENCIL_BACK_WRITEMASK = mask;
2916     }
2917 }
2918 
stencilOpSeparate(GLenum face,GLenum fail,GLenum zfail,GLenum zpass)2919 void GLClientState::stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
2920     if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
2921         state_GL_STENCIL_FAIL = fail;
2922         state_GL_STENCIL_PASS_DEPTH_FAIL = zfail;
2923         state_GL_STENCIL_PASS_DEPTH_PASS = zpass;
2924     }
2925 
2926     if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
2927         state_GL_STENCIL_BACK_FAIL = fail;
2928         state_GL_STENCIL_BACK_PASS_DEPTH_FAIL = zfail;
2929         state_GL_STENCIL_BACK_PASS_DEPTH_PASS = zpass;
2930     }
2931 }
2932 
setTextureData(SharedTextureDataMap * sharedTexData)2933 void GLClientState::setTextureData(SharedTextureDataMap* sharedTexData) {
2934     m_tex.textureRecs = sharedTexData;
2935 }
2936 
setRenderbufferInfo(RenderbufferInfo * rbInfo)2937 void GLClientState::setRenderbufferInfo(RenderbufferInfo* rbInfo) {
2938     mRboState.rboData = rbInfo;
2939     if (rbInfo) {
2940         RenderbufferInfo::ScopedView view(mRboState.rboData);
2941         auto rbo = view.get_or_add_shared_ptr(0);
2942         mRboState.boundRenderbuffer = rbo;
2943     }
2944 }
2945 
setSamplerInfo(SamplerInfo * samplerInfo)2946 void GLClientState::setSamplerInfo(SamplerInfo* samplerInfo) {
2947     mSamplerInfo = samplerInfo;
2948 }
2949 
compressedTexImageSizeCompatible(GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLsizei imageSize)2950 bool GLClientState::compressedTexImageSizeCompatible(GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize) {
2951     bool error = false;
2952     GLsizei compressedSize = GLESTextureUtils::getCompressedImageSize(internalformat, width, height, depth, &error);
2953     if (error) return false;
2954     return imageSize == compressedSize;
2955 }
2956 
fromMakeCurrent()2957 void GLClientState::fromMakeCurrent() {
2958     if (mFboState.fboData.find(0) == mFboState.fboData.end()) {
2959         addFreshFramebuffer(0);
2960         FboProps& default_fb_props = mFboState.fboData[0];
2961         default_fb_props.colorAttachmenti_hasRbo[0] = true;
2962         default_fb_props.depthAttachment_hasRbo = true;
2963         default_fb_props.stencilAttachment_hasRbo = true;
2964         default_fb_props.depthstencilAttachment_hasRbo = true;
2965         RenderbufferInfo::ScopedView view(mRboState.rboData);
2966         // Use RBO 0 as placeholder
2967         auto rbo0 = view.get_or_add_shared_ptr(0);
2968         default_fb_props.colorAttachmenti_rbos[0] = rbo0;
2969         default_fb_props.depthAttachment_rbo = rbo0;
2970         default_fb_props.stencilAttachment_rbo = rbo0;
2971         default_fb_props.depthstencilAttachment_rbo = rbo0;
2972 
2973     }
2974 
2975     if (!samplerExists(0)) {
2976         GLuint id = 0;
2977         setExistence(ObjectType::Sampler, true, 1, &id);
2978     }
2979 
2980 }
2981 
initFromCaps(const HostDriverCaps & caps)2982 void GLClientState::initFromCaps(
2983     const HostDriverCaps& caps) {
2984     m_hostDriverCaps = caps;
2985 
2986     // Override some of them
2987     m_hostDriverCaps.max_vertex_attribs = CODEC_MAX_VERTEX_ATTRIBUTES;
2988     m_hostDriverCaps.max_vertex_attrib_bindings = m_hostDriverCaps.max_vertex_attribs;
2989 
2990     // Derive some other settings
2991     m_log2MaxTextureSize = 0;
2992     uint32_t current = 1;
2993     while (current < m_hostDriverCaps.max_texture_size) {
2994         current = current << 1;
2995         ++m_log2MaxTextureSize;
2996     }
2997 
2998     if (m_glesMajorVersion >= 3) {
2999         if (m_hostDriverCaps.max_transform_feedback_separate_attribs)
3000             m_indexedTransformFeedbackBuffers.resize(m_hostDriverCaps.max_transform_feedback_separate_attribs);
3001         if (m_hostDriverCaps.max_uniform_buffer_bindings)
3002             m_indexedUniformBuffers.resize(m_hostDriverCaps.max_uniform_buffer_bindings);
3003         if (m_hostDriverCaps.max_atomic_counter_buffer_bindings)
3004             m_indexedAtomicCounterBuffers.resize(m_hostDriverCaps.max_atomic_counter_buffer_bindings);
3005         if (m_hostDriverCaps.max_shader_storage_buffer_bindings)
3006             m_indexedShaderStorageBuffers.resize(m_hostDriverCaps.max_shader_storage_buffer_bindings);
3007 
3008         BufferBinding buf0Binding;
3009         buf0Binding.buffer = 0;
3010         buf0Binding.offset = 0;
3011         buf0Binding.size = 0;
3012         buf0Binding.stride = 0;
3013         buf0Binding.effectiveStride = 0;
3014 
3015         for (size_t i = 0; i < m_indexedTransformFeedbackBuffers.size(); ++i)
3016             m_indexedTransformFeedbackBuffers[i] = buf0Binding;
3017         for (size_t i = 0; i < m_indexedUniformBuffers.size(); ++i)
3018             m_indexedUniformBuffers[i] = buf0Binding;
3019         for (size_t i = 0; i < m_indexedAtomicCounterBuffers.size(); ++i)
3020             m_indexedAtomicCounterBuffers[i] = buf0Binding;
3021         for (size_t i = 0; i < m_indexedShaderStorageBuffers.size(); ++i)
3022             m_indexedShaderStorageBuffers[i] = buf0Binding;
3023     }
3024 
3025     addFreshFramebuffer(0);
3026 
3027     m_initialized = true;
3028 }
3029 
needsInitFromCaps() const3030 bool GLClientState::needsInitFromCaps() const {
3031     return !m_initialized;
3032 }
3033 
setExtensions(const std::string & extensions)3034 void GLClientState::setExtensions(const std::string& extensions) {
3035     if (!m_extensions_set) m_extensions = extensions;
3036 
3037     m_has_color_buffer_float_extension =
3038         hasExtension("GL_EXT_color_buffer_float");
3039     m_has_color_buffer_half_float_extension =
3040         hasExtension("GL_EXT_color_buffer_half_float");
3041     m_extensions_set = true;
3042 }
3043 
hasExtension(const char * ext) const3044 bool GLClientState::hasExtension(const char* ext) const {
3045     return m_extensions.find(ext) != std::string::npos;
3046 }
3047 
3048 using android::base::guest::AutoLock;
3049 using android::base::guest::Lock;
3050 
3051 // A process-wide fence registry (because we can use fence sync objects across multiple contexts)
3052 struct FenceRegistry {
3053     Lock lock;
3054     PredicateMap<uint64_t, false> existence;
3055 
onFenceCreatedFenceRegistry3056     void onFenceCreated(GLsync sync) {
3057         AutoLock<Lock> scopedLock(lock);
3058         uint64_t asUint64 = (uint64_t)(uintptr_t)(sync);
3059         existence.add(asUint64);
3060         existence.set(asUint64, true);
3061     }
3062 
onFenceDestroyedFenceRegistry3063     void onFenceDestroyed(GLsync sync) {
3064         AutoLock<Lock> scopedLock(lock);
3065         uint64_t asUint64 = (uint64_t)(uintptr_t)(sync);
3066         existence.remove(asUint64);
3067     }
3068 
existsFenceRegistry3069     bool exists(GLsync sync) {
3070         AutoLock<Lock> scopedLock(lock);
3071         uint64_t asUint64 = (uint64_t)(uintptr_t)(sync);
3072         return existence.get(asUint64);
3073     }
3074 };
3075 
3076 static FenceRegistry sFenceRegistry;
3077 
onFenceCreated(GLsync sync)3078 void GLClientState::onFenceCreated(GLsync sync) {
3079     sFenceRegistry.onFenceCreated(sync);
3080 }
3081 
onFenceDestroyed(GLsync sync)3082 void GLClientState::onFenceDestroyed(GLsync sync) {
3083     sFenceRegistry.onFenceDestroyed(sync);
3084 }
3085 
fenceExists(GLsync sync)3086 bool GLClientState::fenceExists(GLsync sync) {
3087     return sFenceRegistry.exists(sync);
3088 }
3089 
3090