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