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