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