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