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