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), ¤tSamples);
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, ¤tSamples);
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, ¤tSamples);
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