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