1 /*
2 * Copyright 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
17 #include <GLcommon/GLEScontext.h>
18
19 #include "base/Lock.h"
20 #include "base/Lookup.h"
21 #include "base/StreamSerializing.h"
22 #include "host-common/feature_control.h"
23 #include "host-common/logging.h"
24
25 #include <GLcommon/GLconversion_macros.h>
26 #include <GLcommon/GLSnapshotSerializers.h>
27 #include <GLcommon/GLESmacros.h>
28 #include <GLcommon/TextureData.h>
29 #include <GLES/gl.h>
30 #include <GLES/glext.h>
31 #include <GLES2/gl2.h>
32 #include <GLES2/gl2ext.h>
33 #include <GLES3/gl3.h>
34 #include <GLES3/gl31.h>
35 #include <GLcommon/GLESvalidate.h>
36 #include <GLcommon/TextureUtils.h>
37 #include <GLcommon/FramebufferData.h>
38 #include <GLcommon/ScopedGLState.h>
39 #ifndef _MSC_VER
40 #include <strings.h>
41 #endif
42 #include <string.h>
43
44 #include <numeric>
45 #include <map>
46
47 //decleration
48 static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
49 static void convertFixedIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize);
50 static void convertByteDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
51 static void convertByteIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize);
52
onLoad(android::base::Stream * stream)53 void BufferBinding::onLoad(android::base::Stream* stream) {
54 buffer = stream->getBe32();
55 offset = stream->getBe32();
56 size = stream->getBe32();
57 stride = stream->getBe32();
58 divisor = stream->getBe32();
59 isBindBase = stream->getByte();
60 }
61
onSave(android::base::Stream * stream) const62 void BufferBinding::onSave(android::base::Stream* stream) const {
63 stream->putBe32(buffer);
64 stream->putBe32(offset);
65 stream->putBe32(size);
66 stream->putBe32(stride);
67 stream->putBe32(divisor);
68 stream->putByte(isBindBase);
69 }
70
VAOState(android::base::Stream * stream)71 VAOState::VAOState(android::base::Stream* stream) {
72 element_array_buffer_binding = stream->getBe32();
73
74 vertexAttribInfo.clear();
75 for (uint32_t i = 0; i < kMaxVertexAttributes; ++i) {
76 vertexAttribInfo.emplace_back(stream);
77 }
78
79 uint64_t arraysMapPtr = stream->getBe64();
80
81 if (arraysMapPtr) {
82 arraysMap.reset(new ArraysMap());
83 size_t mapSize = stream->getBe32();
84 for (size_t i = 0; i < mapSize; i++) {
85 GLuint id = stream->getBe32();
86 arraysMap->emplace(id, new GLESpointer(stream));
87 }
88 legacy = true;
89 } else {
90 arraysMap.reset();
91 }
92
93 loadContainer(stream, bindingState);
94 bufferBacked = stream->getByte();
95 everBound = stream->getByte();
96 }
97
onSave(android::base::Stream * stream) const98 void VAOState::onSave(android::base::Stream* stream) const {
99 stream->putBe32(element_array_buffer_binding);
100 for (uint32_t i = 0; i < kMaxVertexAttributes; ++i) {
101 vertexAttribInfo[i].onSave(stream);
102 }
103
104 if (arraysMap) {
105 stream->putBe64((uint64_t)(uintptr_t)arraysMap.get());
106 } else {
107 stream->putBe64(0);
108 }
109
110 if (arraysMap) {
111 stream->putBe32(arraysMap->size());
112 for (const auto& ite : *arraysMap) {
113 stream->putBe32(ite.first);
114 assert(ite.second);
115 ite.second->onSave(stream);
116 }
117 }
118
119 saveContainer(stream, bindingState);
120 stream->putByte(bufferBacked);
121 stream->putByte(everBound);
122 }
123
~GLESConversionArrays()124 GLESConversionArrays::~GLESConversionArrays() {
125 for(auto it = m_arrays.begin(); it != m_arrays.end(); ++it) {
126 if((*it).second.allocated){
127 if((*it).second.type == GL_FLOAT){
128 GLfloat* p = (GLfloat *)((*it).second.data);
129 if(p) delete[] p;
130 } else if((*it).second.type == GL_SHORT){
131 GLshort* p = (GLshort *)((*it).second.data);
132 if(p) delete[] p;
133 }
134 }
135 }
136 }
137
allocArr(unsigned int size,GLenum type)138 void GLESConversionArrays::allocArr(unsigned int size,GLenum type){
139 if(type == GL_FIXED){
140 m_arrays[m_current].data = new GLfloat[size];
141 m_arrays[m_current].type = GL_FLOAT;
142 } else if(type == GL_BYTE){
143 m_arrays[m_current].data = new GLshort[size];
144 m_arrays[m_current].type = GL_SHORT;
145 }
146 m_arrays[m_current].stride = 0;
147 m_arrays[m_current].allocated = true;
148 }
149
setArr(void * data,unsigned int stride,GLenum type)150 void GLESConversionArrays::setArr(void* data,unsigned int stride,GLenum type){
151 m_arrays[m_current].type = type;
152 m_arrays[m_current].data = data;
153 m_arrays[m_current].stride = stride;
154 m_arrays[m_current].allocated = false;
155 }
156
getCurrentData()157 void* GLESConversionArrays::getCurrentData(){
158 return m_arrays[m_current].data;
159 }
160
getCurrentArray()161 ArrayData& GLESConversionArrays::getCurrentArray(){
162 return m_arrays[m_current];
163 }
164
getCurrentIndex()165 unsigned int GLESConversionArrays::getCurrentIndex(){
166 return m_current;
167 }
168
operator [](int i)169 ArrayData& GLESConversionArrays::operator[](int i){
170 return m_arrays[i];
171 }
172
operator ++()173 void GLESConversionArrays::operator++(){
174 m_current++;
175 }
176
177 GLDispatch GLEScontext::s_glDispatch;
178 android::base::Lock GLEScontext::s_lock;
179 std::string* GLEScontext::s_glExtensionsGles1 = NULL;
180 bool GLEScontext::s_glExtensionsGles1Initialized = false;
181 std::string* GLEScontext::s_glExtensions = NULL;
182 bool GLEScontext::s_glExtensionsInitialized = false;
183 std::string GLEScontext::s_glVendorGles1;
184 std::string GLEScontext::s_glRendererGles1;
185 std::string GLEScontext::s_glVersionGles1;
186 std::string GLEScontext::s_glVendor;
187 std::string GLEScontext::s_glRenderer;
188 std::string GLEScontext::s_glVersion;
189 GLSupport GLEScontext::s_glSupport;
190
Version(int major,int minor,int release)191 Version::Version(int major,int minor,int release):m_major(major),
192 m_minor(minor),
193 m_release(release){};
194
Version(const Version & ver)195 Version::Version(const Version& ver):m_major(ver.m_major),
196 m_minor(ver.m_minor),
197 m_release(ver.m_release){}
198
Version(const char * versionString)199 Version::Version(const char* versionString){
200 m_release = 0;
201 if((!versionString) ||
202 ((!(sscanf(versionString,"%d.%d" ,&m_major,&m_minor) == 2)) &&
203 (!(sscanf(versionString,"%d.%d.%d",&m_major,&m_minor,&m_release) == 3)))){
204 m_major = m_minor = 0; // the version is not in the right format
205 }
206 }
207
operator =(const Version & ver)208 Version& Version::operator=(const Version& ver){
209 m_major = ver.m_major;
210 m_minor = ver.m_minor;
211 m_release = ver.m_release;
212 return *this;
213 }
214
operator <(const Version & ver) const215 bool Version::operator<(const Version& ver) const{
216 if(m_major < ver.m_major) return true;
217 if(m_major == ver.m_major){
218 if(m_minor < ver.m_minor) return true;
219 if(m_minor == ver.m_minor){
220 return m_release < ver.m_release;
221 }
222 }
223 return false;
224 }
225
getHostExtensionsString(GLDispatch * dispatch)226 static std::string getHostExtensionsString(GLDispatch* dispatch) {
227 // glGetString(GL_EXTENSIONS) is deprecated in GL 3.0, one has to use
228 // glGetStringi(GL_EXTENSIONS, index) instead to get individual extension
229 // names. Recent desktop drivers implement glGetStringi() but have a
230 // version of glGetString() that returns NULL, so deal with this by
231 // doing the following:
232 //
233 // - If glGetStringi() is available, and glGetIntegerv(GL_NUM_EXTENSIONS &num_exts)
234 // gives a nonzero value, use it to build the extensions
235 // string, using simple spaces to separate the names.
236 //
237 // - Otherwise, fallback to getGetString(). If it returns NULL, return
238 // an empty string.
239 //
240
241 std::string result;
242 int num_exts = 0;
243
244 if (dispatch->glGetStringi) {
245 dispatch->glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts);
246 GLenum err = dispatch->glGetError();
247 if (err == GL_NO_ERROR) {
248 for (int n = 0; n < num_exts; n++) {
249 const char* ext = reinterpret_cast<const char*>(
250 dispatch->glGetStringi(GL_EXTENSIONS, n));
251 if (ext != NULL) {
252 if (!result.empty()) {
253 result += " ";
254 }
255 result += ext;
256 }
257 }
258 }
259 }
260
261 // If glGetIntegerv does not affect the value,
262 // our system does not actually support
263 // GL 3.0 style extension getting.
264 if (!dispatch->glGetStringi || num_exts == 0) {
265 const char* extensions = reinterpret_cast<const char*>(
266 dispatch->glGetString(GL_EXTENSIONS));
267 if (extensions) {
268 result = extensions;
269 }
270 }
271
272 // For the sake of initCapsLocked() add a starting and trailing space.
273 if (!result.empty()) {
274 if (result[0] != ' ') {
275 result.insert(0, 1, ' ');
276 }
277 if (result[result.size() - 1U] != ' ') {
278 result += ' ';
279 }
280 }
281 return result;
282 }
283
getIndex(GLenum indices_type,const GLvoid * indices,unsigned int i)284 static GLuint getIndex(GLenum indices_type, const GLvoid* indices, unsigned int i) {
285 switch (indices_type) {
286 case GL_UNSIGNED_BYTE:
287 return static_cast<const GLubyte*>(indices)[i];
288 case GL_UNSIGNED_SHORT:
289 return static_cast<const GLushort*>(indices)[i];
290 case GL_UNSIGNED_INT:
291 return static_cast<const GLuint*>(indices)[i];
292 default:
293 ERR("**** ERROR unknown type 0x%x", indices_type);
294 return 0;
295 }
296 }
297
addVertexArrayObjects(GLsizei n,GLuint * arrays)298 void GLEScontext::addVertexArrayObjects(GLsizei n, GLuint* arrays) {
299 for (int i = 0; i < n; i++) {
300 addVertexArrayObject(arrays[i]);
301 }
302 }
303
removeVertexArrayObjects(GLsizei n,const GLuint * arrays)304 void GLEScontext::removeVertexArrayObjects(GLsizei n, const GLuint* arrays) {
305 for (int i = 0; i < n; i++) {
306 removeVertexArrayObject(arrays[i]);
307 }
308 }
309
addVertexArrayObject(GLuint array)310 void GLEScontext::addVertexArrayObject(GLuint array) {
311 ArraysMap* map = new ArraysMap();
312 for (int i = 0; i < s_glSupport.maxVertexAttribs; i++) {
313 map->insert(
314 ArraysMap::value_type(
315 i,
316 new GLESpointer()));
317 }
318 assert(m_vaoStateMap.count(array) == 0); // Overwriting existing entry, leaking memory
319 m_vaoStateMap[array] = VAOState(0, map, std::max(s_glSupport.maxVertexAttribs, s_glSupport.maxVertexAttribBindings));
320 }
321
removeVertexArrayObject(GLuint array)322 void GLEScontext::removeVertexArrayObject(GLuint array) {
323 if (array == 0) return;
324 if (m_vaoStateMap.find(array) == m_vaoStateMap.end())
325 return;
326 if (array == m_currVaoState.vaoId()) {
327 setVertexArrayObject(0);
328 }
329
330 auto& state = m_vaoStateMap[array];
331
332 if (state.arraysMap) {
333 for (auto elem : *(state.arraysMap)) {
334 delete elem.second;
335 }
336 }
337
338 m_vaoStateMap.erase(array);
339 }
340
setVertexArrayObject(GLuint array)341 bool GLEScontext::setVertexArrayObject(GLuint array) {
342 VAOStateMap::iterator it = m_vaoStateMap.find(array);
343 if (it != m_vaoStateMap.end()) {
344 m_currVaoState = VAOStateRef(it);
345 return true;
346 }
347 return false;
348 }
349
setVAOEverBound()350 void GLEScontext::setVAOEverBound() {
351 m_currVaoState.setEverBound();
352 }
353
getVertexArrayObject() const354 GLuint GLEScontext::getVertexArrayObject() const {
355 return m_currVaoState.vaoId();
356 }
357
vertexAttributesBufferBacked()358 bool GLEScontext::vertexAttributesBufferBacked() {
359 const auto& info = m_currVaoState.attribInfo_const();
360 for (uint32_t i = 0; i < kMaxVertexAttributes; ++i) {
361 const auto& pointerInfo = info[i];
362 if (pointerInfo.isEnable() &&
363 !m_currVaoState.bufferBindings()[pointerInfo.getBindingIndex()].buffer) {
364 return false;
365 }
366 }
367
368 return true;
369 }
370
371 static EGLiface* s_eglIface = nullptr;
372
373 // static
eglIface()374 EGLiface* GLEScontext::eglIface() {
375 return s_eglIface;
376 }
377
378 // static
initEglIface(EGLiface * iface)379 void GLEScontext::initEglIface(EGLiface* iface) {
380 if (!s_eglIface) s_eglIface = iface;
381 }
382
initGlobal(EGLiface * iface)383 void GLEScontext::initGlobal(EGLiface* iface) {
384 initEglIface(iface);
385 s_lock.lock();
386 if (!s_glExtensions) {
387 initCapsLocked(reinterpret_cast<const GLubyte*>(
388 getHostExtensionsString(&s_glDispatch).c_str()));
389 s_glExtensions = new std::string();
390 }
391 if (!s_glExtensionsGles1) {
392 s_glExtensionsGles1 = new std::string();
393 }
394 s_lock.unlock();
395 }
396
init()397 void GLEScontext::init() {
398 if (!m_initialized) {
399 initExtensionString();
400
401 m_maxTexUnits = getMaxCombinedTexUnits();
402 m_texState = new textureUnitState[m_maxTexUnits];
403 for (int i=0;i<m_maxTexUnits;++i) {
404 for (int j=0;j<NUM_TEXTURE_TARGETS;++j)
405 {
406 m_texState[i][j].texture = 0;
407 m_texState[i][j].enabled = GL_FALSE;
408 }
409 }
410
411 m_indexedTransformFeedbackBuffers.resize(getCaps()->maxTransformFeedbackSeparateAttribs);
412 m_indexedUniformBuffers.resize(getCaps()->maxUniformBufferBindings);
413 m_indexedAtomicCounterBuffers.resize(getCaps()->maxAtomicCounterBufferBindings);
414 m_indexedShaderStorageBuffers.resize(getCaps()->maxShaderStorageBufferBindings);
415 }
416 }
417
restore()418 void GLEScontext::restore() {
419 postLoadRestoreShareGroup();
420 if (m_needRestoreFromSnapshot) {
421 postLoadRestoreCtx();
422 m_needRestoreFromSnapshot = false;
423 }
424 }
425
needRestore()426 bool GLEScontext::needRestore() {
427 bool ret = m_needRestoreFromSnapshot;
428 if (m_shareGroup) {
429 ret |= m_shareGroup->needRestore();
430 }
431 return ret;
432 }
433
getGLerror()434 GLenum GLEScontext::getGLerror() {
435 return m_glError;
436 }
437
setGLerror(GLenum err)438 void GLEScontext::setGLerror(GLenum err) {
439 m_glError = err;
440 }
441
setActiveTexture(GLenum tex)442 void GLEScontext::setActiveTexture(GLenum tex) {
443 m_activeTexture = tex - GL_TEXTURE0;
444 m_maxUsedTexUnit = std::max(m_activeTexture, m_maxUsedTexUnit);
445 }
446
GLEScontext()447 GLEScontext::GLEScontext() {}
448
GLEScontext(GlobalNameSpace * globalNameSpace,android::base::Stream * stream,GlLibrary * glLib)449 GLEScontext::GLEScontext(GlobalNameSpace* globalNameSpace,
450 android::base::Stream* stream, GlLibrary* glLib) {
451 if (stream) {
452 m_initialized = stream->getByte();
453 m_glesMajorVersion = stream->getBe32();
454 m_glesMinorVersion = stream->getBe32();
455 if (m_initialized) {
456 m_activeTexture = (GLuint)stream->getBe32();
457
458 loadNameMap<VAOStateMap>(stream, m_vaoStateMap);
459 uint32_t vaoId = stream->getBe32();
460 setVertexArrayObject(vaoId);
461
462 m_copyReadBuffer = static_cast<GLuint>(stream->getBe32());
463 m_copyWriteBuffer = static_cast<GLuint>(stream->getBe32());
464 m_pixelPackBuffer = static_cast<GLuint>(stream->getBe32());
465 m_pixelUnpackBuffer = static_cast<GLuint>(stream->getBe32());
466 m_transformFeedbackBuffer = static_cast<GLuint>(stream->getBe32());
467 m_uniformBuffer = static_cast<GLuint>(stream->getBe32());
468 m_atomicCounterBuffer = static_cast<GLuint>(stream->getBe32());
469 m_dispatchIndirectBuffer = static_cast<GLuint>(stream->getBe32());
470 m_drawIndirectBuffer = static_cast<GLuint>(stream->getBe32());
471 m_shaderStorageBuffer = static_cast<GLuint>(stream->getBe32());
472
473 loadContainer(stream, m_indexedTransformFeedbackBuffers);
474 loadContainer(stream, m_indexedUniformBuffers);
475 loadContainer(stream, m_indexedAtomicCounterBuffers);
476 loadContainer(stream, m_indexedShaderStorageBuffers);
477
478 // TODO: handle the case where the loaded size and the supported
479 // side does not match
480
481 m_isViewport = stream->getByte();
482 m_viewportX = static_cast<GLint>(stream->getBe32());
483 m_viewportY = static_cast<GLint>(stream->getBe32());
484 m_viewportWidth = static_cast<GLsizei>(stream->getBe32());
485 m_viewportHeight = static_cast<GLsizei>(stream->getBe32());
486
487 m_polygonOffsetFactor = static_cast<GLfloat>(stream->getFloat());
488 m_polygonOffsetUnits = static_cast<GLfloat>(stream->getFloat());
489
490 m_isScissor = stream->getByte();
491 m_scissorX = static_cast<GLint>(stream->getBe32());
492 m_scissorY = static_cast<GLint>(stream->getBe32());
493 m_scissorWidth = static_cast<GLsizei>(stream->getBe32());
494 m_scissorHeight = static_cast<GLsizei>(stream->getBe32());
495
496 loadCollection(stream, &m_glEnableList,
497 [](android::base::Stream* stream) {
498 GLenum item = stream->getBe32();
499 bool enabled = stream->getByte();
500 return std::make_pair(item, enabled);
501 });
502
503 m_blendEquationRgb = static_cast<GLenum>(stream->getBe32());
504 m_blendEquationAlpha = static_cast<GLenum>(stream->getBe32());
505 m_blendSrcRgb = static_cast<GLenum>(stream->getBe32());
506 m_blendDstRgb = static_cast<GLenum>(stream->getBe32());
507 m_blendSrcAlpha = static_cast<GLenum>(stream->getBe32());
508 m_blendDstAlpha = static_cast<GLenum>(stream->getBe32());
509
510 loadCollection(stream, &m_glPixelStoreiList,
511 [](android::base::Stream* stream) {
512 GLenum item = stream->getBe32();
513 GLint val = stream->getBe32();
514 return std::make_pair(item, val);
515 });
516
517 m_cullFace = static_cast<GLenum>(stream->getBe32());
518 m_frontFace = static_cast<GLenum>(stream->getBe32());
519 m_depthFunc = static_cast<GLenum>(stream->getBe32());
520 m_depthMask = static_cast<GLboolean>(stream->getByte());
521 m_zNear = static_cast<GLclampf>(stream->getFloat());
522 m_zFar = static_cast<GLclampf>(stream->getFloat());
523
524 m_lineWidth = static_cast<GLclampf>(stream->getFloat());
525
526 m_sampleCoverageVal = static_cast<GLclampf>(stream->getFloat());
527 m_sampleCoverageInvert = static_cast<GLboolean>(stream->getByte());
528
529 stream->read(m_stencilStates, sizeof(m_stencilStates));
530
531 m_colorMaskR = static_cast<GLboolean>(stream->getByte());
532 m_colorMaskG = static_cast<GLboolean>(stream->getByte());
533 m_colorMaskB = static_cast<GLboolean>(stream->getByte());
534 m_colorMaskA = static_cast<GLboolean>(stream->getByte());
535
536 m_clearColorR = static_cast<GLclampf>(stream->getFloat());
537 m_clearColorG = static_cast<GLclampf>(stream->getFloat());
538 m_clearColorB = static_cast<GLclampf>(stream->getFloat());
539 m_clearColorA = static_cast<GLclampf>(stream->getFloat());
540
541 m_clearDepth = static_cast<GLclampf>(stream->getFloat());
542 m_clearStencil = static_cast<GLint>(stream->getBe32());
543
544 // share group is supposed to be loaded by EglContext and reset
545 // when loading EglContext
546 //int sharegroupId = stream->getBe32();
547 m_glError = static_cast<GLenum>(stream->getBe32());
548 m_maxTexUnits = static_cast<int>(stream->getBe32());
549 m_maxUsedTexUnit = static_cast<int>(stream->getBe32());
550 m_texState = new textureUnitState[m_maxTexUnits];
551 stream->read(m_texState, sizeof(textureUnitState) * m_maxTexUnits);
552 m_arrayBuffer = static_cast<unsigned int>(stream->getBe32());
553 m_elementBuffer = static_cast<unsigned int>(stream->getBe32());
554 m_renderbuffer = static_cast<GLuint>(stream->getBe32());
555 m_drawFramebuffer = static_cast<GLuint>(stream->getBe32());
556 m_readFramebuffer = static_cast<GLuint>(stream->getBe32());
557 m_defaultFBODrawBuffer = static_cast<GLenum>(stream->getBe32());
558 m_defaultFBOReadBuffer = static_cast<GLenum>(stream->getBe32());
559
560 m_needRestoreFromSnapshot = true;
561 }
562 }
563 ObjectData::loadObject_t loader = [this](NamedObjectType type,
564 long long unsigned int localName,
565 android::base::Stream* stream) {
566 return loadObject(type, localName, stream);
567 };
568 m_fboNameSpace = new NameSpace(NamedObjectType::FRAMEBUFFER,
569 globalNameSpace, stream, loader);
570 // do not load m_vaoNameSpace
571 m_vaoNameSpace = new NameSpace(NamedObjectType::VERTEX_ARRAY_OBJECT,
572 globalNameSpace, nullptr, loader);
573 }
574
~GLEScontext()575 GLEScontext::~GLEScontext() {
576 auto& gl = dispatcher();
577
578 if (m_blitState.program) {
579 gl.glDeleteProgram(m_blitState.program);
580 gl.glDeleteTextures(1, &m_blitState.tex);
581 gl.glDeleteVertexArrays(1, &m_blitState.vao);
582 gl.glDeleteBuffers(1, &m_blitState.vbo);
583 gl.glDeleteFramebuffers(1, &m_blitState.fbo);
584 }
585
586 if (m_textureEmulationProg) {
587 gl.glDeleteProgram(m_textureEmulationProg);
588 gl.glDeleteTextures(2, m_textureEmulationTextures);
589 gl.glDeleteFramebuffers(1, &m_textureEmulationFBO);
590 gl.glDeleteVertexArrays(1, &m_textureEmulationVAO);
591 }
592
593 if (m_defaultFBO) {
594 gl.glBindFramebuffer(GL_FRAMEBUFFER, m_defaultFBO);
595 gl.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
596 gl.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
597 gl.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
598 gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
599 gl.glDeleteFramebuffers(1, &m_defaultFBO);
600 }
601
602 if (m_defaultReadFBO && (m_defaultReadFBO != m_defaultFBO)) {
603 gl.glBindFramebuffer(GL_READ_FRAMEBUFFER, m_defaultReadFBO);
604 gl.glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
605 gl.glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
606 gl.glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
607 gl.glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
608 gl.glDeleteFramebuffers(1, &m_defaultReadFBO);
609 }
610
611 m_defaultFBO = 0;
612 m_defaultReadFBO = 0;
613
614 for (auto&& vao : m_vaoStateMap) {
615 if (vao.second.arraysMap) {
616 for (auto elem : *(vao.second.arraysMap)) {
617 delete elem.second;
618 }
619 vao.second.arraysMap.reset();
620 }
621 }
622
623 delete[] m_texState;
624 m_texState = nullptr;
625 delete m_fboNameSpace;
626 m_fboNameSpace = nullptr;
627 delete m_vaoNameSpace;
628 m_vaoNameSpace = nullptr;
629 }
630
postLoad()631 void GLEScontext::postLoad() {
632 m_fboNameSpace->postLoad(
633 [this](NamedObjectType p_type, ObjectLocalName p_localName) {
634 if (p_type == NamedObjectType::FRAMEBUFFER) {
635 return this->getFBODataPtr(p_localName);
636 } else {
637 return m_shareGroup->getObjectDataPtr(p_type, p_localName);
638 }
639 });
640 }
641
onSave(android::base::Stream * stream) const642 void GLEScontext::onSave(android::base::Stream* stream) const {
643 stream->putByte(m_initialized);
644 stream->putBe32(m_glesMajorVersion);
645 stream->putBe32(m_glesMinorVersion);
646 if (m_initialized) {
647 stream->putBe32(m_activeTexture);
648
649 saveNameMap(stream, m_vaoStateMap);
650 stream->putBe32(getVertexArrayObject());
651
652 stream->putBe32(m_copyReadBuffer);
653 stream->putBe32(m_copyWriteBuffer);
654 stream->putBe32(m_pixelPackBuffer);
655 stream->putBe32(m_pixelUnpackBuffer);
656 stream->putBe32(m_transformFeedbackBuffer);
657 stream->putBe32(m_uniformBuffer);
658 stream->putBe32(m_atomicCounterBuffer);
659 stream->putBe32(m_dispatchIndirectBuffer);
660 stream->putBe32(m_drawIndirectBuffer);
661 stream->putBe32(m_shaderStorageBuffer);
662
663 saveContainer(stream, m_indexedTransformFeedbackBuffers);
664 saveContainer(stream, m_indexedUniformBuffers);
665 saveContainer(stream, m_indexedAtomicCounterBuffers);
666 saveContainer(stream, m_indexedShaderStorageBuffers);
667
668 stream->putByte(m_isViewport);
669 stream->putBe32(m_viewportX);
670 stream->putBe32(m_viewportY);
671 stream->putBe32(m_viewportWidth);
672 stream->putBe32(m_viewportHeight);
673
674 stream->putFloat(m_polygonOffsetFactor);
675 stream->putFloat(m_polygonOffsetUnits);
676
677 stream->putByte(m_isScissor);
678 stream->putBe32(m_scissorX);
679 stream->putBe32(m_scissorY);
680 stream->putBe32(m_scissorWidth);
681 stream->putBe32(m_scissorHeight);
682
683 saveCollection(stream, m_glEnableList, [](android::base::Stream* stream,
684 const std::pair<const GLenum, bool>& enableItem) {
685 stream->putBe32(enableItem.first);
686 stream->putByte(enableItem.second);
687 });
688
689 stream->putBe32(m_blendEquationRgb);
690 stream->putBe32(m_blendEquationAlpha);
691 stream->putBe32(m_blendSrcRgb);
692 stream->putBe32(m_blendDstRgb);
693 stream->putBe32(m_blendSrcAlpha);
694 stream->putBe32(m_blendDstAlpha);
695
696 saveCollection(stream, m_glPixelStoreiList, [](android::base::Stream* stream,
697 const std::pair<const GLenum, GLint>& pixelStore) {
698 stream->putBe32(pixelStore.first);
699 stream->putBe32(pixelStore.second);
700 });
701
702 stream->putBe32(m_cullFace);
703 stream->putBe32(m_frontFace);
704 stream->putBe32(m_depthFunc);
705 stream->putByte(m_depthMask);
706 stream->putFloat(m_zNear);
707 stream->putFloat(m_zFar);
708
709 stream->putFloat(m_lineWidth);
710
711 stream->putFloat(m_sampleCoverageVal);
712 stream->putByte(m_sampleCoverageInvert);
713
714 stream->write(m_stencilStates, sizeof(m_stencilStates));
715
716 stream->putByte(m_colorMaskR);
717 stream->putByte(m_colorMaskG);
718 stream->putByte(m_colorMaskB);
719 stream->putByte(m_colorMaskA);
720
721 stream->putFloat(m_clearColorR);
722 stream->putFloat(m_clearColorG);
723 stream->putFloat(m_clearColorB);
724 stream->putFloat(m_clearColorA);
725
726 stream->putFloat(m_clearDepth);
727 stream->putBe32(m_clearStencil);
728
729 // share group is supposed to be saved / loaded by EglContext
730 stream->putBe32(m_glError);
731 stream->putBe32(m_maxTexUnits);
732 stream->putBe32(m_maxUsedTexUnit);
733 stream->write(m_texState, sizeof(textureUnitState) * m_maxTexUnits);
734 stream->putBe32(m_arrayBuffer);
735 stream->putBe32(m_elementBuffer);
736 stream->putBe32(m_renderbuffer);
737 stream->putBe32(m_drawFramebuffer);
738 stream->putBe32(m_readFramebuffer);
739 stream->putBe32(m_defaultFBODrawBuffer);
740 stream->putBe32(m_defaultFBOReadBuffer);
741 }
742 m_fboNameSpace->onSave(stream);
743 // do not save m_vaoNameSpace
744 }
745
postSave(android::base::Stream * stream) const746 void GLEScontext::postSave(android::base::Stream* stream) const {
747 (void)stream;
748 // We need to mark the textures dirty, for those that has been bound to
749 // a potential render target.
750 for (ObjectDataMap::const_iterator it = m_fboNameSpace->objDataMapBegin();
751 it != m_fboNameSpace->objDataMapEnd();
752 it ++) {
753 FramebufferData* fbData = (FramebufferData*)it->second.get();
754 fbData->makeTextureDirty([this](NamedObjectType p_type,
755 ObjectLocalName p_localName) {
756 if (p_type == NamedObjectType::FRAMEBUFFER) {
757 return this->getFBODataPtr(p_localName);
758 } else {
759 return m_shareGroup->getObjectDataPtr(p_type, p_localName);
760 }
761 });
762 }
763 }
764
postLoadRestoreShareGroup()765 void GLEScontext::postLoadRestoreShareGroup() {
766 m_shareGroup->postLoadRestore();
767 }
768
postLoadRestoreCtx()769 void GLEScontext::postLoadRestoreCtx() {
770 GLDispatch& dispatcher = GLEScontext::dispatcher();
771
772 assert(!m_shareGroup->needRestore());
773 m_fboNameSpace->postLoadRestore(
774 [this](NamedObjectType p_type, ObjectLocalName p_localName) {
775 if (p_type == NamedObjectType::FRAMEBUFFER) {
776 return getFBOGlobalName(p_localName);
777 } else {
778 return m_shareGroup->getGlobalName(p_type, p_localName);
779 }
780 }
781 );
782
783 // buffer bindings
784 auto bindBuffer = [this](GLenum target, GLuint buffer) {
785 this->dispatcher().glBindBuffer(target,
786 m_shareGroup->getGlobalName(NamedObjectType::VERTEXBUFFER, buffer));
787 };
788 bindBuffer(GL_ARRAY_BUFFER, m_arrayBuffer);
789 bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_currVaoState.iboId());
790
791 // framebuffer binding
792 auto bindFrameBuffer = [this](GLenum target, GLuint buffer) {
793 this->dispatcher().glBindFramebuffer(target,
794 getFBOGlobalName(buffer));
795 };
796 bindFrameBuffer(GL_READ_FRAMEBUFFER, m_readFramebuffer);
797 bindFrameBuffer(GL_DRAW_FRAMEBUFFER, m_drawFramebuffer);
798
799 for (unsigned int i = 0; i <= m_maxUsedTexUnit; i++) {
800 for (unsigned int j = 0; j < NUM_TEXTURE_TARGETS; j++) {
801 textureTargetState& texState = m_texState[i][j];
802 if (texState.texture || texState.enabled) {
803 this->dispatcher().glActiveTexture(i + GL_TEXTURE0);
804 GLenum texTarget = GL_TEXTURE_2D;
805 switch (j) {
806 case TEXTURE_2D:
807 texTarget = GL_TEXTURE_2D;
808 break;
809 case TEXTURE_CUBE_MAP:
810 texTarget = GL_TEXTURE_CUBE_MAP;
811 break;
812 case TEXTURE_2D_ARRAY:
813 texTarget = GL_TEXTURE_2D_ARRAY;
814 break;
815 case TEXTURE_3D:
816 texTarget = GL_TEXTURE_3D;
817 break;
818 case TEXTURE_2D_MULTISAMPLE:
819 texTarget = GL_TEXTURE_2D_MULTISAMPLE;
820 break;
821 default:
822 fprintf(stderr,
823 "Warning: unsupported texture target 0x%x.\n",
824 j);
825 break;
826 }
827 // TODO: refactor the following line since it is duplicated in
828 // GLESv2Imp and GLEScmImp as well
829 ObjectLocalName texName = texState.texture != 0 ?
830 texState.texture : getDefaultTextureName(texTarget);
831 this->dispatcher().glBindTexture(
832 texTarget,
833 m_shareGroup->getGlobalName(
834 NamedObjectType::TEXTURE, texName));
835 if (!isCoreProfile() && texState.enabled) {
836 dispatcher.glEnable(texTarget);
837 }
838 }
839 }
840 }
841 dispatcher.glActiveTexture(m_activeTexture + GL_TEXTURE0);
842
843 // viewport & scissor
844 if (m_isViewport) {
845 dispatcher.glViewport(m_viewportX, m_viewportY,
846 m_viewportWidth, m_viewportHeight);
847 }
848 if (m_isScissor) {
849 dispatcher.glScissor(m_scissorX, m_scissorY,
850 m_scissorWidth, m_scissorHeight);
851 }
852 dispatcher.glPolygonOffset(m_polygonOffsetFactor,
853 m_polygonOffsetUnits);
854
855 for (auto item : m_glEnableList) {
856 if (item.first == GL_TEXTURE_2D
857 || item.first == GL_TEXTURE_CUBE_MAP_OES) {
858 continue;
859 }
860 std::function<void(GLenum)> enableFunc = item.second ? dispatcher.glEnable :
861 dispatcher.glDisable;
862 if (item.first==GL_TEXTURE_GEN_STR_OES) {
863 enableFunc(GL_TEXTURE_GEN_S);
864 enableFunc(GL_TEXTURE_GEN_T);
865 enableFunc(GL_TEXTURE_GEN_R);
866 } else {
867 enableFunc(item.first);
868 }
869 }
870 dispatcher.glBlendEquationSeparate(m_blendEquationRgb,
871 m_blendEquationAlpha);
872 dispatcher.glBlendFuncSeparate(m_blendSrcRgb, m_blendDstRgb,
873 m_blendSrcAlpha, m_blendDstAlpha);
874 for (const auto& pixelStore : m_glPixelStoreiList) {
875 dispatcher.glPixelStorei(pixelStore.first, pixelStore.second);
876 }
877
878 dispatcher.glCullFace(m_cullFace);
879 dispatcher.glFrontFace(m_frontFace);
880 dispatcher.glDepthFunc(m_depthFunc);
881 dispatcher.glDepthMask(m_depthMask);
882
883 dispatcher.glLineWidth(m_lineWidth);
884
885 dispatcher.glSampleCoverage(m_sampleCoverageVal, m_sampleCoverageInvert);
886
887 for (int i = 0; i < 2; i++) {
888 GLenum face = i == StencilFront ? GL_FRONT
889 : GL_BACK;
890 dispatcher.glStencilFuncSeparate(face, m_stencilStates[i].m_func,
891 m_stencilStates[i].m_ref, m_stencilStates[i].m_funcMask);
892 dispatcher.glStencilMaskSeparate(face, m_stencilStates[i].m_writeMask);
893 dispatcher.glStencilOpSeparate(face, m_stencilStates[i].m_sfail,
894 m_stencilStates[i].m_dpfail, m_stencilStates[i].m_dppass);
895 }
896
897 dispatcher.glClearColor(m_clearColorR, m_clearColorG, m_clearColorB,
898 m_clearColorA);
899 if (isGles2Gles()) {
900 dispatcher.glClearDepthf(m_clearDepth);
901 dispatcher.glDepthRangef(m_zNear, m_zFar);
902 } else {
903 dispatcher.glClearDepth(m_clearDepth);
904 dispatcher.glDepthRange(m_zNear, m_zFar);
905 }
906 dispatcher.glClearStencil(m_clearStencil);
907 dispatcher.glColorMask(m_colorMaskR, m_colorMaskG, m_colorMaskB,
908 m_colorMaskA);
909
910 // report any GL errors when loading from a snapshot
911 GLenum err = 0;
912 do {
913 err = dispatcher.glGetError();
914 #ifdef _DEBUG
915 if (err) {
916 ERR("warning: get GL error %d while restoring a snapshot", err);
917 }
918 #endif
919 } while (err != 0);
920 }
921
loadObject(NamedObjectType type,ObjectLocalName localName,android::base::Stream * stream) const922 ObjectDataPtr GLEScontext::loadObject(NamedObjectType type,
923 ObjectLocalName localName, android::base::Stream* stream) const {
924 switch (type) {
925 case NamedObjectType::VERTEXBUFFER:
926 return ObjectDataPtr(new GLESbuffer(stream));
927 case NamedObjectType::TEXTURE:
928 return ObjectDataPtr(new TextureData(stream));
929 case NamedObjectType::FRAMEBUFFER:
930 return ObjectDataPtr(new FramebufferData(stream));
931 case NamedObjectType::RENDERBUFFER:
932 return ObjectDataPtr(new RenderbufferData(stream));
933 default:
934 return {};
935 }
936 }
937
setPointer(GLenum arrType,GLint size,GLenum type,GLsizei stride,const GLvoid * data,GLsizei dataSize,bool normalize,bool isInt)938 const GLvoid* GLEScontext::setPointer(GLenum arrType,GLint size,GLenum type,GLsizei stride,const GLvoid* data, GLsizei dataSize, bool normalize, bool isInt) {
939 GLuint bufferName = m_arrayBuffer;
940 GLESpointer* glesPointer = nullptr;
941
942 if (m_currVaoState.it->second.legacy) {
943 auto vertexAttrib = m_currVaoState.find(arrType);
944 if (vertexAttrib == m_currVaoState.end()) {
945 return nullptr;
946 }
947 glesPointer = m_currVaoState[arrType];
948 } else {
949 uint32_t attribIndex = (uint32_t)arrType;
950 if (attribIndex > kMaxVertexAttributes) return nullptr;
951 glesPointer = m_currVaoState.attribInfo().data() + (uint32_t)arrType;
952 }
953
954 if(bufferName) {
955 unsigned int offset = SafeUIntFromPointer(data);
956 GLESbuffer* vbo = static_cast<GLESbuffer*>(
957 m_shareGroup
958 ->getObjectData(NamedObjectType::VERTEXBUFFER,
959 bufferName));
960 if(offset >= vbo->getSize() || vbo->getSize() - offset < size) {
961 #ifdef _DEBUG
962 ERR("Warning: Invalid pointer offset %u, arrType %d, type %d", offset, arrType, type);
963 #endif
964 return nullptr;
965 }
966
967 glesPointer->setBuffer(size,type,stride,vbo,bufferName,offset,normalize, isInt);
968
969 return static_cast<const unsigned char*>(vbo->getData()) + offset;
970 }
971 glesPointer->setArray(size,type,stride,data,dataSize,normalize,isInt);
972 return data;
973 }
974
enableArr(GLenum arr,bool enable)975 void GLEScontext::enableArr(GLenum arr,bool enable) {
976 auto vertexAttrib = m_currVaoState.find(arr);
977 if (vertexAttrib != m_currVaoState.end()) {
978 vertexAttrib->second->enable(enable);
979 }
980 }
981
isArrEnabled(GLenum arr)982 bool GLEScontext::isArrEnabled(GLenum arr) {
983 if (m_currVaoState.it->second.legacy) {
984 return m_currVaoState[arr]->isEnable();
985 } else {
986 if ((uint32_t)arr > kMaxVertexAttributes) return false;
987 return m_currVaoState.attribInfo()[(uint32_t)arr].isEnable();
988 }
989 }
990
getPointer(GLenum arrType)991 const GLESpointer* GLEScontext::getPointer(GLenum arrType) {
992 const auto it = m_currVaoState.find(arrType);
993 return it != m_currVaoState.end() ? it->second : nullptr;
994 }
995
convertFixedDirectLoop(const char * dataIn,unsigned int strideIn,void * dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize)996 static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize) {
997
998 for(unsigned int i = 0; i < nBytes;i+=strideOut) {
999 const GLfixed* fixed_data = (const GLfixed *)dataIn;
1000 //filling attrib
1001 for(int j=0;j<attribSize;j++) {
1002 reinterpret_cast<GLfloat*>(&static_cast<unsigned char*>(dataOut)[i])[j] = X2F(fixed_data[j]);
1003 }
1004 dataIn += strideIn;
1005 }
1006 }
1007
convertFixedIndirectLoop(const char * dataIn,unsigned int strideIn,void * dataOut,GLsizei count,GLenum indices_type,const GLvoid * indices,unsigned int strideOut,int attribSize)1008 static void convertFixedIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize) {
1009 for(int i = 0 ;i < count ;i++) {
1010 GLuint index = getIndex(indices_type, indices, i);
1011
1012 const GLfixed* fixed_data = (GLfixed *)(dataIn + index*strideIn);
1013 GLfloat* float_data = reinterpret_cast<GLfloat*>(static_cast<unsigned char*>(dataOut) + index*strideOut);
1014
1015 for(int j=0;j<attribSize;j++) {
1016 float_data[j] = X2F(fixed_data[j]);
1017 }
1018 }
1019 }
1020
convertByteDirectLoop(const char * dataIn,unsigned int strideIn,void * dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize)1021 static void convertByteDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize) {
1022
1023 for(unsigned int i = 0; i < nBytes;i+=strideOut) {
1024 const GLbyte* byte_data = (const GLbyte *)dataIn;
1025 //filling attrib
1026 for(int j=0;j<attribSize;j++) {
1027 reinterpret_cast<GLshort*>(&static_cast<unsigned char*>(dataOut)[i])[j] = B2S(byte_data[j]);
1028 }
1029 dataIn += strideIn;
1030 }
1031 }
1032
convertByteIndirectLoop(const char * dataIn,unsigned int strideIn,void * dataOut,GLsizei count,GLenum indices_type,const GLvoid * indices,unsigned int strideOut,int attribSize)1033 static void convertByteIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize) {
1034 for(int i = 0 ;i < count ;i++) {
1035 GLuint index = getIndex(indices_type, indices, i);
1036 const GLbyte* bytes_data = (GLbyte *)(dataIn + index*strideIn);
1037 GLshort* short_data = reinterpret_cast<GLshort*>(static_cast<unsigned char*>(dataOut) + index*strideOut);
1038
1039 for(int j=0;j<attribSize;j++) {
1040 short_data[j] = B2S(bytes_data[j]);
1041 }
1042 }
1043 }
directToBytesRanges(GLint first,GLsizei count,GLESpointer * p,RangeList & list)1044 static void directToBytesRanges(GLint first,GLsizei count,GLESpointer* p,RangeList& list) {
1045
1046 int attribSize = p->getSize()*4; //4 is the sizeof GLfixed or GLfloat in bytes
1047 int stride = p->getStride()?p->getStride():attribSize;
1048 int start = p->getBufferOffset()+first*stride;
1049 if(!p->getStride()) {
1050 list.addRange(Range(start,count*attribSize));
1051 } else {
1052 for(int i = 0 ;i < count; i++,start+=stride) {
1053 list.addRange(Range(start,attribSize));
1054 }
1055 }
1056 }
1057
indirectToBytesRanges(const GLvoid * indices,GLenum indices_type,GLsizei count,GLESpointer * p,RangeList & list)1058 static void indirectToBytesRanges(const GLvoid* indices,GLenum indices_type,GLsizei count,GLESpointer* p,RangeList& list) {
1059
1060 int attribSize = p->getSize() * 4; //4 is the sizeof GLfixed or GLfloat in bytes
1061 int stride = p->getStride()?p->getStride():attribSize;
1062 int start = p->getBufferOffset();
1063 for(int i=0 ; i < count; i++) {
1064 GLuint index = getIndex(indices_type, indices, i);
1065 list.addRange(Range(start+index*stride,attribSize));
1066
1067 }
1068 }
1069
bytesRangesToIndices(RangeList & ranges,GLESpointer * p,GLuint * indices)1070 int bytesRangesToIndices(RangeList& ranges,GLESpointer* p,GLuint* indices) {
1071
1072 int attribSize = p->getSize() * 4; //4 is the sizeof GLfixed or GLfloat in bytes
1073 int stride = p->getStride()?p->getStride():attribSize;
1074 int offset = p->getBufferOffset();
1075
1076 int n = 0;
1077 for(int i=0;i<ranges.size();i++) {
1078 int startIndex = (ranges[i].getStart() - offset) / stride;
1079 int nElements = ranges[i].getSize()/attribSize;
1080 for(int j=0;j<nElements;j++) {
1081 indices[n++] = startIndex+j;
1082 }
1083 }
1084 return n;
1085 }
1086
convertDirect(GLESConversionArrays & cArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer * p)1087 void GLEScontext::convertDirect(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p) {
1088
1089 GLenum type = p->getType();
1090 int attribSize = p->getSize();
1091 unsigned int size = attribSize*count + first;
1092 unsigned int bytes = type == GL_FIXED ? sizeof(GLfixed):sizeof(GLbyte);
1093 cArrs.allocArr(size,type);
1094 int stride = p->getStride()?p->getStride():bytes*attribSize;
1095 const char* data = (const char*)p->getArrayData() + (first*stride);
1096
1097 if(type == GL_FIXED) {
1098 convertFixedDirectLoop(data,stride,cArrs.getCurrentData(),size*sizeof(GLfloat),attribSize*sizeof(GLfloat),attribSize);
1099 } else if(type == GL_BYTE) {
1100 convertByteDirectLoop(data,stride,cArrs.getCurrentData(),size*sizeof(GLshort),attribSize*sizeof(GLshort),attribSize);
1101 }
1102 }
1103
convertDirectVBO(GLESConversionArrays & cArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer * p)1104 void GLEScontext::convertDirectVBO(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p) {
1105
1106 RangeList ranges;
1107 RangeList conversions;
1108 GLuint* indices = NULL;
1109 int attribSize = p->getSize();
1110 int stride = p->getStride()?p->getStride():sizeof(GLfixed)*attribSize;
1111 char* data = (char*)p->getBufferData();
1112
1113 if(p->bufferNeedConversion()) {
1114 directToBytesRanges(first,count,p,ranges); //converting indices range to buffer bytes ranges by offset
1115 p->getBufferConversions(ranges,conversions); // getting from the buffer the relevant ranges that still needs to be converted
1116
1117 if(conversions.size()) { // there are some elements to convert
1118 indices = new GLuint[count];
1119 int nIndices = bytesRangesToIndices(conversions,p,indices); //converting bytes ranges by offset to indices in this array
1120 convertFixedIndirectLoop(data,stride,data,nIndices,GL_UNSIGNED_INT,indices,stride,attribSize);
1121 }
1122 }
1123 if(indices) delete[] indices;
1124 cArrs.setArr(data,p->getStride(),GL_FLOAT);
1125 }
1126
findMaxIndex(GLsizei count,GLenum type,const GLvoid * indices)1127 unsigned int GLEScontext::findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices) {
1128 //finding max index
1129 unsigned int max = 0;
1130 if(type == GL_UNSIGNED_BYTE) {
1131 GLubyte* b_indices =(GLubyte *)indices;
1132 for(int i=0;i<count;i++) {
1133 if(b_indices[i] > max) max = b_indices[i];
1134 }
1135 } else if (type == GL_UNSIGNED_SHORT) {
1136 GLushort* us_indices =(GLushort *)indices;
1137 for(int i=0;i<count;i++) {
1138 if(us_indices[i] > max) max = us_indices[i];
1139 }
1140 } else { // type == GL_UNSIGNED_INT
1141 GLuint* ui_indices =(GLuint *)indices;
1142 for(int i=0;i<count;i++) {
1143 if(ui_indices[i] > max) max = ui_indices[i];
1144 }
1145 }
1146 return max;
1147 }
1148
convertIndirect(GLESConversionArrays & cArrs,GLsizei count,GLenum indices_type,const GLvoid * indices,GLenum array_id,GLESpointer * p)1149 void GLEScontext::convertIndirect(GLESConversionArrays& cArrs,GLsizei count,GLenum indices_type,const GLvoid* indices,GLenum array_id,GLESpointer* p) {
1150 GLenum type = p->getType();
1151 int maxElements = findMaxIndex(count,indices_type,indices) + 1;
1152
1153 int attribSize = p->getSize();
1154 int size = attribSize * maxElements;
1155 unsigned int bytes = type == GL_FIXED ? sizeof(GLfixed):sizeof(GLbyte);
1156 cArrs.allocArr(size,type);
1157 int stride = p->getStride()?p->getStride():bytes*attribSize;
1158
1159 const char* data = (const char*)p->getArrayData();
1160 if(type == GL_FIXED) {
1161 convertFixedIndirectLoop(data,stride,cArrs.getCurrentData(),count,indices_type,indices,attribSize*sizeof(GLfloat),attribSize);
1162 } else if(type == GL_BYTE){
1163 convertByteIndirectLoop(data,stride,cArrs.getCurrentData(),count,indices_type,indices,attribSize*sizeof(GLshort),attribSize);
1164 }
1165 }
1166
convertIndirectVBO(GLESConversionArrays & cArrs,GLsizei count,GLenum indices_type,const GLvoid * indices,GLenum array_id,GLESpointer * p)1167 void GLEScontext::convertIndirectVBO(GLESConversionArrays& cArrs,GLsizei count,GLenum indices_type,const GLvoid* indices,GLenum array_id,GLESpointer* p) {
1168 RangeList ranges;
1169 RangeList conversions;
1170 GLuint* conversionIndices = NULL;
1171 int attribSize = p->getSize();
1172 int stride = p->getStride()?p->getStride():sizeof(GLfixed)*attribSize;
1173 char* data = static_cast<char*>(p->getBufferData());
1174 if(p->bufferNeedConversion()) {
1175 indirectToBytesRanges(indices,indices_type,count,p,ranges); //converting indices range to buffer bytes ranges by offset
1176 p->getBufferConversions(ranges,conversions); // getting from the buffer the relevant ranges that still needs to be converted
1177 if(conversions.size()) { // there are some elements to convert
1178 conversionIndices = new GLuint[count];
1179 int nIndices = bytesRangesToIndices(conversions,p,conversionIndices); //converting bytes ranges by offset to indices in this array
1180 convertFixedIndirectLoop(data,stride,data,nIndices,GL_UNSIGNED_INT,conversionIndices,stride,attribSize);
1181 }
1182 }
1183 if(conversionIndices) delete[] conversionIndices;
1184 cArrs.setArr(data,p->getStride(),GL_FLOAT);
1185 }
1186
bindBuffer(GLenum target,GLuint buffer)1187 GLuint GLEScontext::bindBuffer(GLenum target,GLuint buffer) {
1188 switch(target) {
1189 case GL_ARRAY_BUFFER:
1190 m_arrayBuffer = buffer;
1191 break;
1192 case GL_ELEMENT_ARRAY_BUFFER:
1193 m_currVaoState.iboId() = buffer;
1194 break;
1195 case GL_COPY_READ_BUFFER:
1196 m_copyReadBuffer = buffer;
1197 break;
1198 case GL_COPY_WRITE_BUFFER:
1199 m_copyWriteBuffer = buffer;
1200 break;
1201 case GL_PIXEL_PACK_BUFFER:
1202 m_pixelPackBuffer = buffer;
1203 break;
1204 case GL_PIXEL_UNPACK_BUFFER:
1205 m_pixelUnpackBuffer = buffer;
1206 break;
1207 case GL_TRANSFORM_FEEDBACK_BUFFER:
1208 m_transformFeedbackBuffer = buffer;
1209 break;
1210 case GL_UNIFORM_BUFFER:
1211 m_uniformBuffer = buffer;
1212 break;
1213 case GL_ATOMIC_COUNTER_BUFFER:
1214 m_atomicCounterBuffer = buffer;
1215 break;
1216 case GL_DISPATCH_INDIRECT_BUFFER:
1217 m_dispatchIndirectBuffer = buffer;
1218 break;
1219 case GL_DRAW_INDIRECT_BUFFER:
1220 m_drawIndirectBuffer = buffer;
1221 break;
1222 case GL_SHADER_STORAGE_BUFFER:
1223 m_shaderStorageBuffer = buffer;
1224 break;
1225 default:
1226 m_arrayBuffer = buffer;
1227 break;
1228 }
1229
1230 if (!buffer) return 0;
1231
1232 auto sg = m_shareGroup.get();
1233
1234 if (!sg) return 0;
1235
1236 return sg->ensureObjectOnBind(NamedObjectType::VERTEXBUFFER, buffer);
1237 }
1238
bindIndexedBuffer(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size,GLintptr stride,bool isBindBase)1239 void GLEScontext::bindIndexedBuffer(GLenum target, GLuint index, GLuint buffer,
1240 GLintptr offset, GLsizeiptr size, GLintptr stride, bool isBindBase) {
1241 VertexAttribBindingVector* bindings = nullptr;
1242 switch (target) {
1243 case GL_UNIFORM_BUFFER:
1244 bindings = &m_indexedUniformBuffers;
1245 break;
1246 case GL_ATOMIC_COUNTER_BUFFER:
1247 bindings = &m_indexedAtomicCounterBuffers;
1248 break;
1249 case GL_SHADER_STORAGE_BUFFER:
1250 bindings = &m_indexedShaderStorageBuffers;
1251 break;
1252 default:
1253 bindings = &m_currVaoState.bufferBindings();
1254 break;
1255 }
1256 if (index >= bindings->size()) {
1257 return;
1258 }
1259 auto& bufferBinding = (*bindings)[index];
1260 bufferBinding.buffer = buffer;
1261 bufferBinding.offset = offset;
1262 bufferBinding.size = size;
1263 bufferBinding.stride = stride;
1264 bufferBinding.isBindBase = isBindBase;
1265 }
1266
bindIndexedBuffer(GLenum target,GLuint index,GLuint buffer)1267 void GLEScontext::bindIndexedBuffer(GLenum target, GLuint index, GLuint buffer) {
1268 GLint sz;
1269 getBufferSizeById(buffer, &sz);
1270 bindIndexedBuffer(target, index, buffer, 0, sz, 0, true);
1271 }
1272
sClearIndexedBufferBinding(GLuint id,std::vector<BufferBinding> & bindings)1273 static void sClearIndexedBufferBinding(GLuint id, std::vector<BufferBinding>& bindings) {
1274 for (size_t i = 0; i < bindings.size(); i++) {
1275 if (bindings[i].buffer == id) {
1276 bindings[i].offset = 0;
1277 bindings[i].size = 0;
1278 bindings[i].stride = 0;
1279 bindings[i].buffer = 0;
1280 bindings[i].isBindBase = false;
1281 }
1282 }
1283 }
1284
unbindBuffer(GLuint buffer)1285 void GLEScontext::unbindBuffer(GLuint buffer) {
1286 if (m_arrayBuffer == buffer)
1287 m_arrayBuffer = 0;
1288 if (m_currVaoState.iboId() == buffer)
1289 m_currVaoState.iboId() = 0;
1290 if (m_copyReadBuffer == buffer)
1291 m_copyReadBuffer = 0;
1292 if (m_copyWriteBuffer == buffer)
1293 m_copyWriteBuffer = 0;
1294 if (m_pixelPackBuffer == buffer)
1295 m_pixelPackBuffer = 0;
1296 if (m_pixelUnpackBuffer == buffer)
1297 m_pixelUnpackBuffer = 0;
1298 if (m_transformFeedbackBuffer == buffer)
1299 m_transformFeedbackBuffer = 0;
1300 if (m_uniformBuffer == buffer)
1301 m_uniformBuffer = 0;
1302 if (m_atomicCounterBuffer == buffer)
1303 m_atomicCounterBuffer = 0;
1304 if (m_dispatchIndirectBuffer == buffer)
1305 m_dispatchIndirectBuffer = 0;
1306 if (m_drawIndirectBuffer == buffer)
1307 m_drawIndirectBuffer = 0;
1308 if (m_shaderStorageBuffer == buffer)
1309 m_shaderStorageBuffer = 0;
1310
1311 // One might think that indexed buffer bindings for transform feedbacks
1312 // must be cleared as well, but transform feedbacks are
1313 // considered GL objects with attachments, so even if the buffer is
1314 // deleted (unbindBuffer is called), the state query with
1315 // glGetIntegeri_v must still return the deleted name [1].
1316 // sClearIndexedBufferBinding(buffer, m_indexedTransformFeedbackBuffers);
1317 // [1] OpenGL ES 3.0.5 spec Appendix D.1.3
1318 sClearIndexedBufferBinding(buffer, m_indexedUniformBuffers);
1319 sClearIndexedBufferBinding(buffer, m_indexedAtomicCounterBuffers);
1320 sClearIndexedBufferBinding(buffer, m_indexedShaderStorageBuffers);
1321 sClearIndexedBufferBinding(buffer, m_currVaoState.bufferBindings());
1322 }
1323
1324 //checks if any buffer is binded to target
isBindedBuffer(GLenum target)1325 bool GLEScontext::isBindedBuffer(GLenum target) {
1326 switch(target) {
1327 case GL_ARRAY_BUFFER:
1328 return m_arrayBuffer != 0;
1329 case GL_ELEMENT_ARRAY_BUFFER:
1330 return m_currVaoState.iboId() != 0;
1331 case GL_COPY_READ_BUFFER:
1332 return m_copyReadBuffer != 0;
1333 case GL_COPY_WRITE_BUFFER:
1334 return m_copyWriteBuffer != 0;
1335 case GL_PIXEL_PACK_BUFFER:
1336 return m_pixelPackBuffer != 0;
1337 case GL_PIXEL_UNPACK_BUFFER:
1338 return m_pixelUnpackBuffer != 0;
1339 case GL_TRANSFORM_FEEDBACK_BUFFER:
1340 return m_transformFeedbackBuffer != 0;
1341 case GL_UNIFORM_BUFFER:
1342 return m_uniformBuffer != 0;
1343 case GL_ATOMIC_COUNTER_BUFFER:
1344 return m_atomicCounterBuffer != 0;
1345 case GL_DISPATCH_INDIRECT_BUFFER:
1346 return m_dispatchIndirectBuffer != 0;
1347 case GL_DRAW_INDIRECT_BUFFER:
1348 return m_drawIndirectBuffer != 0;
1349 case GL_SHADER_STORAGE_BUFFER:
1350 return m_shaderStorageBuffer != 0;
1351 default:
1352 return m_arrayBuffer != 0;
1353 }
1354 }
1355
getBuffer(GLenum target)1356 GLuint GLEScontext::getBuffer(GLenum target) {
1357 switch(target) {
1358 case GL_ARRAY_BUFFER:
1359 return m_arrayBuffer;
1360 case GL_ELEMENT_ARRAY_BUFFER:
1361 return m_currVaoState.iboId();
1362 case GL_COPY_READ_BUFFER:
1363 return m_copyReadBuffer;
1364 case GL_COPY_WRITE_BUFFER:
1365 return m_copyWriteBuffer;
1366 case GL_PIXEL_PACK_BUFFER:
1367 return m_pixelPackBuffer;
1368 case GL_PIXEL_UNPACK_BUFFER:
1369 return m_pixelUnpackBuffer;
1370 case GL_TRANSFORM_FEEDBACK_BUFFER:
1371 return m_transformFeedbackBuffer;
1372 case GL_UNIFORM_BUFFER:
1373 return m_uniformBuffer;
1374 case GL_ATOMIC_COUNTER_BUFFER:
1375 return m_atomicCounterBuffer;
1376 case GL_DISPATCH_INDIRECT_BUFFER:
1377 return m_dispatchIndirectBuffer;
1378 case GL_DRAW_INDIRECT_BUFFER:
1379 return m_drawIndirectBuffer;
1380 case GL_SHADER_STORAGE_BUFFER:
1381 return m_shaderStorageBuffer;
1382 default:
1383 return m_arrayBuffer;
1384 }
1385 }
1386
getIndexedBuffer(GLenum target,GLuint index)1387 GLuint GLEScontext::getIndexedBuffer(GLenum target, GLuint index) {
1388 switch (target) {
1389 case GL_UNIFORM_BUFFER:
1390 return m_indexedUniformBuffers[index].buffer;
1391 case GL_ATOMIC_COUNTER_BUFFER:
1392 return m_indexedAtomicCounterBuffers[index].buffer;
1393 case GL_SHADER_STORAGE_BUFFER:
1394 return m_indexedShaderStorageBuffers[index].buffer;
1395 default:
1396 return m_currVaoState.bufferBindings()[index].buffer;
1397 }
1398 }
1399
1400
getBindedBuffer(GLenum target)1401 GLvoid* GLEScontext::getBindedBuffer(GLenum target) {
1402 GLuint bufferName = getBuffer(target);
1403 if(!bufferName) return NULL;
1404
1405 GLESbuffer* vbo = static_cast<GLESbuffer*>(
1406 m_shareGroup
1407 ->getObjectData(NamedObjectType::VERTEXBUFFER, bufferName));
1408 return vbo->getData();
1409 }
1410
getBufferSize(GLenum target,GLint * param)1411 void GLEScontext::getBufferSize(GLenum target,GLint* param) {
1412 GLuint bufferName = getBuffer(target);
1413 getBufferSizeById(bufferName, param);
1414 }
1415
getBufferSizeById(GLuint bufferName,GLint * param)1416 void GLEScontext::getBufferSizeById(GLuint bufferName, GLint* param) {
1417 if (!bufferName) { *param = 0; return; }
1418 GLESbuffer* vbo = static_cast<GLESbuffer*>(
1419 m_shareGroup
1420 ->getObjectData(NamedObjectType::VERTEXBUFFER, bufferName));
1421 *param = vbo->getSize();
1422 }
1423
getBufferUsage(GLenum target,GLint * param)1424 void GLEScontext::getBufferUsage(GLenum target,GLint* param) {
1425 GLuint bufferName = getBuffer(target);
1426 GLESbuffer* vbo = static_cast<GLESbuffer*>(
1427 m_shareGroup
1428 ->getObjectData(NamedObjectType::VERTEXBUFFER, bufferName));
1429 *param = vbo->getUsage();
1430 }
1431
setBufferData(GLenum target,GLsizeiptr size,const GLvoid * data,GLenum usage)1432 bool GLEScontext::setBufferData(GLenum target,GLsizeiptr size,const GLvoid* data,GLenum usage) {
1433 GLuint bufferName = getBuffer(target);
1434 if(!bufferName) return false;
1435 GLESbuffer* vbo = static_cast<GLESbuffer*>(
1436 m_shareGroup
1437 ->getObjectData(NamedObjectType::VERTEXBUFFER, bufferName));
1438 return vbo->setBuffer(size,usage,data);
1439 }
1440
setBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid * data)1441 bool GLEScontext::setBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid* data) {
1442
1443 GLuint bufferName = getBuffer(target);
1444 if(!bufferName) return false;
1445 GLESbuffer* vbo = static_cast<GLESbuffer*>(
1446 m_shareGroup
1447 ->getObjectData(NamedObjectType::VERTEXBUFFER, bufferName));
1448 return vbo->setSubBuffer(offset,size,data);
1449 }
1450
setViewport(GLint x,GLint y,GLsizei width,GLsizei height)1451 void GLEScontext::setViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
1452 m_isViewport = true;
1453 m_viewportX = x;
1454 m_viewportY = y;
1455 m_viewportWidth = width;
1456 m_viewportHeight = height;
1457 }
1458
getViewport(GLint * params)1459 void GLEScontext::getViewport(GLint* params) {
1460 if (!m_isViewport) {
1461 dispatcher().glGetIntegerv(GL_VIEWPORT, params);
1462 } else {
1463 params[0] = m_viewportX;
1464 params[1] = m_viewportY;
1465 params[2] = m_viewportWidth;
1466 params[3] = m_viewportHeight;
1467 }
1468 }
1469
setScissor(GLint x,GLint y,GLsizei width,GLsizei height)1470 void GLEScontext::setScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
1471 m_isScissor = true;
1472 m_scissorX = x;
1473 m_scissorY = y;
1474 m_scissorWidth = width;
1475 m_scissorHeight = height;
1476 }
1477
setPolygonOffset(GLfloat factor,GLfloat units)1478 void GLEScontext::setPolygonOffset(GLfloat factor, GLfloat units) {
1479 m_polygonOffsetFactor = factor;
1480 m_polygonOffsetUnits = units;
1481 }
1482
setEnable(GLenum item,bool isEnable)1483 void GLEScontext::setEnable(GLenum item, bool isEnable) {
1484 switch (item) {
1485 case GL_TEXTURE_2D:
1486 case GL_TEXTURE_CUBE_MAP_OES:
1487 case GL_TEXTURE_3D:
1488 case GL_TEXTURE_2D_ARRAY:
1489 case GL_TEXTURE_2D_MULTISAMPLE:
1490 setTextureEnabled(item,true);
1491 break;
1492 default:
1493 m_glEnableList[item] = isEnable;
1494 break;
1495 }
1496 }
1497
isEnabled(GLenum item) const1498 bool GLEScontext::isEnabled(GLenum item) const {
1499 switch (item) {
1500 case GL_TEXTURE_2D:
1501 case GL_TEXTURE_CUBE_MAP_OES:
1502 case GL_TEXTURE_3D:
1503 case GL_TEXTURE_2D_ARRAY:
1504 case GL_TEXTURE_2D_MULTISAMPLE:
1505 return m_texState[m_activeTexture][GLTextureTargetToLocal(item)].enabled;
1506 default:
1507 return android::base::findOrDefault(m_glEnableList, item, false);
1508 }
1509 }
1510
setBlendEquationSeparate(GLenum modeRGB,GLenum modeAlpha)1511 void GLEScontext::setBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
1512 m_blendEquationRgb = modeRGB;
1513 m_blendEquationAlpha = modeAlpha;
1514 }
1515
setBlendFuncSeparate(GLenum srcRGB,GLenum dstRGB,GLenum srcAlpha,GLenum dstAlpha)1516 void GLEScontext::setBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB,
1517 GLenum srcAlpha, GLenum dstAlpha) {
1518 m_blendSrcRgb = srcRGB;
1519 m_blendDstRgb = dstRGB;
1520 m_blendSrcAlpha = srcAlpha;
1521 m_blendDstAlpha = dstAlpha;
1522 }
1523
setPixelStorei(GLenum pname,GLint param)1524 void GLEScontext::setPixelStorei(GLenum pname, GLint param) {
1525 m_glPixelStoreiList[pname] = param;
1526 }
1527
setCullFace(GLenum mode)1528 void GLEScontext::setCullFace(GLenum mode) {
1529 m_cullFace = mode;
1530 }
1531
setFrontFace(GLenum mode)1532 void GLEScontext::setFrontFace(GLenum mode) {
1533 m_frontFace = mode;
1534 }
1535
setDepthFunc(GLenum func)1536 void GLEScontext::setDepthFunc(GLenum func) {
1537 m_depthFunc = func;
1538 }
1539
setDepthMask(GLboolean flag)1540 void GLEScontext::setDepthMask(GLboolean flag) {
1541 m_depthMask = flag;
1542 }
1543
setDepthRangef(GLclampf zNear,GLclampf zFar)1544 void GLEScontext::setDepthRangef(GLclampf zNear, GLclampf zFar) {
1545 m_zNear = zNear;
1546 m_zFar = zFar;
1547 }
1548
setLineWidth(GLfloat lineWidth)1549 void GLEScontext::setLineWidth(GLfloat lineWidth) {
1550 m_lineWidth = lineWidth;
1551 }
1552
setSampleCoverage(GLclampf value,GLboolean invert)1553 void GLEScontext::setSampleCoverage(GLclampf value, GLboolean invert) {
1554 m_sampleCoverageVal = value;
1555 m_sampleCoverageInvert = invert;
1556 }
setStencilFuncSeparate(GLenum face,GLenum func,GLint ref,GLuint mask)1557 void GLEScontext::setStencilFuncSeparate(GLenum face, GLenum func, GLint ref,
1558 GLuint mask) {
1559 if (face == GL_FRONT_AND_BACK) {
1560 setStencilFuncSeparate(GL_FRONT, func, ref, mask);
1561 setStencilFuncSeparate(GL_BACK, func, ref, mask);
1562 return;
1563 }
1564 int idx = 0;
1565 switch (face) {
1566 case GL_FRONT:
1567 idx = StencilFront;
1568 break;
1569 case GL_BACK:
1570 idx = StencilBack;
1571 break;
1572 default:
1573 return;
1574 }
1575 m_stencilStates[idx].m_func = func;
1576 m_stencilStates[idx].m_ref = ref;
1577 m_stencilStates[idx].m_funcMask = mask;
1578 }
1579
setStencilMaskSeparate(GLenum face,GLuint mask)1580 void GLEScontext::setStencilMaskSeparate(GLenum face, GLuint mask) {
1581 if (face == GL_FRONT_AND_BACK) {
1582 setStencilMaskSeparate(GL_FRONT, mask);
1583 setStencilMaskSeparate(GL_BACK, mask);
1584 return;
1585 }
1586 int idx = 0;
1587 switch (face) {
1588 case GL_FRONT:
1589 idx = StencilFront;
1590 break;
1591 case GL_BACK:
1592 idx = StencilBack;
1593 break;
1594 default:
1595 return;
1596 }
1597 m_stencilStates[idx].m_writeMask = mask;
1598 }
1599
setStencilOpSeparate(GLenum face,GLenum fail,GLenum zfail,GLenum zpass)1600 void GLEScontext::setStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail,
1601 GLenum zpass) {
1602 if (face == GL_FRONT_AND_BACK) {
1603 setStencilOpSeparate(GL_FRONT, fail, zfail, zpass);
1604 setStencilOpSeparate(GL_BACK, fail, zfail, zpass);
1605 return;
1606 }
1607 int idx = 0;
1608 switch (face) {
1609 case GL_FRONT:
1610 idx = StencilFront;
1611 break;
1612 case GL_BACK:
1613 idx = StencilBack;
1614 break;
1615 default:
1616 return;
1617 }
1618 m_stencilStates[idx].m_sfail = fail;
1619 m_stencilStates[idx].m_dpfail = zfail;
1620 m_stencilStates[idx].m_dppass = zpass;
1621 }
1622
setColorMask(GLboolean red,GLboolean green,GLboolean blue,GLboolean alpha)1623 void GLEScontext::setColorMask(GLboolean red, GLboolean green, GLboolean blue,
1624 GLboolean alpha) {
1625 m_colorMaskR = red;
1626 m_colorMaskG = green;
1627 m_colorMaskB = blue;
1628 m_colorMaskA = alpha;
1629 }
1630
setClearColor(GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha)1631 void GLEScontext::setClearColor(GLclampf red, GLclampf green, GLclampf blue,
1632 GLclampf alpha) {
1633 m_clearColorR = red;
1634 m_clearColorG = green;
1635 m_clearColorB = blue;
1636 m_clearColorA = alpha;
1637 }
1638
setClearDepth(GLclampf depth)1639 void GLEScontext::setClearDepth(GLclampf depth) {
1640 m_clearDepth = depth;
1641 }
1642
setClearStencil(GLint s)1643 void GLEScontext::setClearStencil(GLint s) {
1644 m_clearStencil = s;
1645 }
1646
getExtensionString(bool isGles1)1647 const char * GLEScontext::getExtensionString(bool isGles1) {
1648 const char * ret;
1649 s_lock.lock();
1650 if (isGles1) {
1651 if (s_glExtensionsGles1)
1652 ret = s_glExtensionsGles1->c_str();
1653 else
1654 ret="";
1655 } else {
1656 if (s_glExtensions)
1657 ret = s_glExtensions->c_str();
1658 else
1659 ret="";
1660 }
1661 s_lock.unlock();
1662 return ret;
1663 }
1664
getVendorString(bool isGles1) const1665 const char * GLEScontext::getVendorString(bool isGles1) const {
1666 return isGles1 ? s_glVendorGles1.c_str() : s_glVendor.c_str();
1667 }
1668
getRendererString(bool isGles1) const1669 const char * GLEScontext::getRendererString(bool isGles1) const {
1670 return isGles1 ? s_glRendererGles1.c_str() : s_glRenderer.c_str();
1671 }
1672
getVersionString(bool isGles1) const1673 const char * GLEScontext::getVersionString(bool isGles1) const {
1674 return isGles1 ? s_glVersionGles1.c_str() : s_glVersion.c_str();
1675 }
1676
getGlobalLock()1677 void GLEScontext::getGlobalLock() {
1678 s_lock.lock();
1679 }
1680
releaseGlobalLock()1681 void GLEScontext::releaseGlobalLock() {
1682 s_lock.unlock();
1683 }
1684
initCapsLocked(const GLubyte * extensionString)1685 void GLEScontext::initCapsLocked(const GLubyte * extensionString)
1686 {
1687 const char* cstring = (const char*)extensionString;
1688
1689 s_glDispatch.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,&s_glSupport.maxVertexAttribs);
1690
1691 if (s_glSupport.maxVertexAttribs > kMaxVertexAttributes) {
1692 s_glSupport.maxVertexAttribs = kMaxVertexAttributes;
1693 }
1694
1695 s_glDispatch.glGetIntegerv(GL_MAX_CLIP_PLANES,&s_glSupport.maxClipPlane);
1696 s_glDispatch.glGetIntegerv(GL_MAX_LIGHTS,&s_glSupport.maxLights);
1697 s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_SIZE,&s_glSupport.maxTexSize);
1698 s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_UNITS,&s_glSupport.maxTexUnits);
1699 // Core profile lacks a fixed-function pipeline with texture units,
1700 // but we still want glDrawTexOES to work in core profile.
1701 // So, set it to 8.
1702 if ((::isCoreProfile() || isGles2Gles()) &&
1703 !s_glSupport.maxTexUnits) {
1704 s_glSupport.maxTexUnits = 8;
1705 }
1706 s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&s_glSupport.maxTexImageUnits);
1707 s_glDispatch.glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &s_glSupport.maxCombinedTexImageUnits);
1708
1709 s_glDispatch.glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &s_glSupport.maxTransformFeedbackSeparateAttribs);
1710 s_glDispatch.glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &s_glSupport.maxUniformBufferBindings);
1711 s_glDispatch.glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &s_glSupport.maxAtomicCounterBufferBindings);
1712 s_glDispatch.glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &s_glSupport.maxShaderStorageBufferBindings);
1713 s_glDispatch.glGetIntegerv(GL_MAX_DRAW_BUFFERS, &s_glSupport.maxDrawBuffers);
1714 s_glDispatch.glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &s_glSupport.maxVertexAttribBindings);
1715
1716 // Compressed texture format query
1717 if(feature_is_enabled(kFeature_NativeTextureDecompression)) {
1718 bool hasEtc2Support = false;
1719 bool hasAstcSupport = false;
1720 int numCompressedFormats = 0;
1721 s_glDispatch.glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numCompressedFormats);
1722 if (numCompressedFormats > 0) {
1723 int numEtc2Formats = 0;
1724 int numAstcFormats = 0;
1725 int numEtc2FormatsSupported = 0;
1726 int numAstcFormatsSupported = 0;
1727
1728 std::map<GLint, bool> found;
1729 forEachEtc2Format([&numEtc2Formats, &found](GLint format) { ++numEtc2Formats; found[format] = false;});
1730 forEachAstcFormat([&numAstcFormats, &found](GLint format) { ++numAstcFormats; found[format] = false;});
1731
1732 std::vector<GLint> formats(numCompressedFormats);
1733 s_glDispatch.glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats.data());
1734
1735 for (int i = 0; i < numCompressedFormats; ++i) {
1736 GLint format = formats[i];
1737 if (isEtc2Format(format)) {
1738 ++numEtc2FormatsSupported;
1739 found[format] = true;
1740 } else if (isAstcFormat(format)) {
1741 ++numAstcFormatsSupported;
1742 found[format] = true;
1743 }
1744 }
1745
1746 if (numEtc2Formats == numEtc2FormatsSupported) {
1747 hasEtc2Support = true; // Supports ETC2 underneath
1748 } else {
1749 // It is unusual to support only some. Record what happened.
1750 ERR("Not supporting etc2: %d vs %d",
1751 numEtc2FormatsSupported, numEtc2Formats);
1752 for (auto it : found) {
1753 if (!it.second) {
1754 ERR("Not found: 0x%x", it.first);
1755 }
1756 }
1757 }
1758
1759 if (numAstcFormats == numAstcFormatsSupported) {
1760 hasAstcSupport = true; // Supports ASTC underneath
1761 } else {
1762 // It is unusual to support only some. Record what happened.
1763 ERR("Not supporting astc: %d vs %d",
1764 numAstcFormatsSupported, numAstcFormats);
1765 for (auto it : found) {
1766 if (!it.second) {
1767 ERR("Not found: 0x%x", it.first);
1768 }
1769 }
1770 }
1771 }
1772 s_glSupport.hasEtc2Support = hasEtc2Support;
1773 s_glSupport.hasAstcSupport = hasAstcSupport;
1774 }
1775
1776 // Clear GL error in case these enums not supported.
1777 s_glDispatch.glGetError();
1778
1779 const GLubyte* glslVersion = s_glDispatch.glGetString(GL_SHADING_LANGUAGE_VERSION);
1780 s_glSupport.glslVersion = Version((const char*)(glslVersion));
1781 const GLubyte* glVersion = s_glDispatch.glGetString(GL_VERSION);
1782
1783 // fprintf(stderr, "%s: vendor renderer version [%s] [%s] [%s]\n", __func__,
1784 // s_glDispatch.glGetString(GL_VENDOR),
1785 // s_glDispatch.glGetString(GL_RENDERER),
1786 // s_glDispatch.glGetString(GL_VERSION));
1787
1788 if (strstr(cstring,"GL_EXT_bgra ")!=NULL ||
1789 (isGles2Gles() && strstr(cstring, "GL_EXT_texture_format_BGRA8888")) ||
1790 (!isGles2Gles() && !(Version((const char*)glVersion) < Version("1.2"))))
1791 s_glSupport.GL_EXT_TEXTURE_FORMAT_BGRA8888 = true;
1792
1793 if (::isCoreProfile() ||
1794 strstr(cstring,"GL_EXT_framebuffer_object ")!=NULL)
1795 s_glSupport.GL_EXT_FRAMEBUFFER_OBJECT = true;
1796
1797 if (strstr(cstring,"GL_ARB_vertex_blend ")!=NULL)
1798 s_glSupport.GL_ARB_VERTEX_BLEND = true;
1799
1800 if (strstr(cstring,"GL_ARB_matrix_palette ")!=NULL)
1801 s_glSupport.GL_ARB_MATRIX_PALETTE = true;
1802
1803 if (strstr(cstring,"GL_EXT_packed_depth_stencil ")!=NULL ||
1804 strstr(cstring,"GL_OES_packed_depth_stencil ")!=NULL)
1805 s_glSupport.GL_EXT_PACKED_DEPTH_STENCIL = true;
1806
1807 if (strstr(cstring,"GL_OES_read_format ")!=NULL)
1808 s_glSupport.GL_OES_READ_FORMAT = true;
1809
1810 if (strstr(cstring,"GL_ARB_half_float_pixel ")!=NULL ||
1811 strstr(cstring,"GL_OES_texture_half_float ")!=NULL)
1812 s_glSupport.GL_ARB_HALF_FLOAT_PIXEL = true;
1813
1814 if (strstr(cstring,"GL_NV_half_float ")!=NULL)
1815 s_glSupport.GL_NV_HALF_FLOAT = true;
1816
1817 if (strstr(cstring,"GL_ARB_half_float_vertex ")!=NULL ||
1818 strstr(cstring,"GL_OES_vertex_half_float ")!=NULL)
1819 s_glSupport.GL_ARB_HALF_FLOAT_VERTEX = true;
1820
1821 if (strstr(cstring,"GL_SGIS_generate_mipmap ")!=NULL)
1822 s_glSupport.GL_SGIS_GENERATE_MIPMAP = true;
1823
1824 if (strstr(cstring,"GL_ARB_ES2_compatibility ")!=NULL
1825 || isGles2Gles())
1826 s_glSupport.GL_ARB_ES2_COMPATIBILITY = true;
1827
1828 if (strstr(cstring,"GL_OES_standard_derivatives ")!=NULL)
1829 s_glSupport.GL_OES_STANDARD_DERIVATIVES = true;
1830
1831 if (::isCoreProfile() ||
1832 strstr(cstring,"GL_ARB_texture_non_power_of_two")!=NULL ||
1833 strstr(cstring,"GL_OES_texture_npot")!=NULL)
1834 s_glSupport.GL_OES_TEXTURE_NPOT = true;
1835
1836 if (::isCoreProfile() ||
1837 strstr(cstring,"GL_ARB_color_buffer_float")!=NULL ||
1838 strstr(cstring,"GL_EXT_color_buffer_float")!=NULL)
1839 s_glSupport.ext_GL_EXT_color_buffer_float = true;
1840
1841 if (::isCoreProfile() ||
1842 strstr(cstring,"GL_EXT_color_buffer_half_float")!=NULL)
1843 s_glSupport.ext_GL_EXT_color_buffer_half_float = true;
1844
1845 if (strstr(cstring,"GL_EXT_shader_framebuffer_fetch")!=NULL) {
1846 s_glSupport.ext_GL_EXT_shader_framebuffer_fetch = true;
1847 }
1848
1849 if (!(Version((const char*)glVersion) < Version("3.0")) || strstr(cstring,"GL_OES_rgb8_rgba8")!=NULL)
1850 s_glSupport.GL_OES_RGB8_RGBA8 = true;
1851
1852 if (strstr(cstring, "GL_EXT_memory_object") != NULL) {
1853 s_glSupport.ext_GL_EXT_memory_object = true;
1854 }
1855
1856 if (strstr(cstring, "GL_EXT_semaphore") != NULL) {
1857 s_glSupport.ext_GL_EXT_semaphore = true;
1858 }
1859
1860 // ASTC
1861 if (strstr(cstring, "GL_KHR_texture_compression_astc_ldr") != NULL) {
1862 s_glSupport.ext_GL_KHR_texture_compression_astc_ldr = true;
1863 }
1864
1865 // BPTC extension detection
1866 if (feature_is_enabled(kFeature_BptcTextureSupport)) {
1867 if ((strstr(cstring, "GL_EXT_texture_compression_bptc") != NULL) ||
1868 (strstr(cstring, "GL_ARB_texture_compression_bptc") != NULL)) {
1869 s_glSupport.hasBptcSupport = true;
1870 }
1871 }
1872
1873 if (feature_is_enabled(kFeature_S3tcTextureSupport)) {
1874 if (strstr(cstring, "GL_EXT_texture_compression_s3tc") != NULL) {
1875 s_glSupport.hasS3tcSupport = true;
1876 }
1877 }
1878
1879 if (feature_is_enabled(kFeature_RgtcTextureSupport)) {
1880 if (strstr(cstring, "GL_EXT_texture_compression_rgtc") != NULL) {
1881 s_glSupport.hasRgtcSupport = true;
1882 }
1883 }
1884 }
1885
buildStrings(bool isGles1,const char * baseVendor,const char * baseRenderer,const char * baseVersion,const char * version)1886 void GLEScontext::buildStrings(bool isGles1, const char* baseVendor,
1887 const char* baseRenderer, const char* baseVersion, const char* version)
1888 {
1889 static const char VENDOR[] = {"Google ("};
1890 static const char RENDERER[] = {"Android Emulator OpenGL ES Translator ("};
1891 const size_t VENDOR_LEN = sizeof(VENDOR) - 1;
1892 const size_t RENDERER_LEN = sizeof(RENDERER) - 1;
1893
1894 // Sanitize the strings as some OpenGL implementations return NULL
1895 // when asked the basic questions (this happened at least once on a client
1896 // machine)
1897 if (!baseVendor) {
1898 baseVendor = "N/A";
1899 }
1900 if (!baseRenderer) {
1901 baseRenderer = "N/A";
1902 }
1903 if (!baseVersion) {
1904 baseVersion = "N/A";
1905 }
1906 if (!version) {
1907 version = "N/A";
1908 }
1909
1910 std::string& vendorString = isGles1 ? s_glVendorGles1 : s_glVendor;
1911 std::string& rendererString = isGles1 ? s_glRendererGles1 : s_glRenderer;
1912 std::string& versionString = isGles1 ? s_glVersionGles1 : s_glVersion;
1913
1914 size_t baseVendorLen = strlen(baseVendor);
1915 vendorString.clear();
1916 vendorString.reserve(baseVendorLen + VENDOR_LEN + 1);
1917 vendorString.append(VENDOR, VENDOR_LEN);
1918 vendorString.append(baseVendor, baseVendorLen);
1919 vendorString.append(")", 1);
1920
1921 size_t baseRendererLen = strlen(baseRenderer);
1922 rendererString.clear();
1923 rendererString.reserve(baseRendererLen + RENDERER_LEN + 1);
1924 rendererString.append(RENDERER, RENDERER_LEN);
1925 rendererString.append(baseRenderer, baseRendererLen);
1926 rendererString.append(")", 1);
1927
1928 size_t baseVersionLen = strlen(baseVersion);
1929 size_t versionLen = strlen(version);
1930 versionString.clear();
1931 versionString.reserve(baseVersionLen + versionLen + 3);
1932 versionString.append(version, versionLen);
1933 versionString.append(" (", 2);
1934 versionString.append(baseVersion, baseVersionLen);
1935 versionString.append(")", 1);
1936 }
1937
isTextureUnitEnabled(GLenum unit)1938 bool GLEScontext::isTextureUnitEnabled(GLenum unit) {
1939 for (int i=0;i<NUM_TEXTURE_TARGETS;++i) {
1940 if (m_texState[unit-GL_TEXTURE0][i].enabled)
1941 return true;
1942 }
1943 return false;
1944 }
1945
glGetBooleanv(GLenum pname,GLboolean * params)1946 bool GLEScontext::glGetBooleanv(GLenum pname, GLboolean *params)
1947 {
1948 GLint iParam;
1949
1950 if(glGetIntegerv(pname, &iParam))
1951 {
1952 *params = (iParam != 0);
1953 return true;
1954 }
1955
1956 return false;
1957 }
1958
glGetFixedv(GLenum pname,GLfixed * params)1959 bool GLEScontext::glGetFixedv(GLenum pname, GLfixed *params)
1960 {
1961 bool result = false;
1962 GLint numParams = 1;
1963
1964 GLint* iParams = new GLint[numParams];
1965 if (numParams>0 && glGetIntegerv(pname,iParams)) {
1966 while(numParams >= 0)
1967 {
1968 params[numParams] = I2X(iParams[numParams]);
1969 numParams--;
1970 }
1971 result = true;
1972 }
1973 delete [] iParams;
1974
1975 return result;
1976 }
1977
glGetFloatv(GLenum pname,GLfloat * params)1978 bool GLEScontext::glGetFloatv(GLenum pname, GLfloat *params)
1979 {
1980 bool result = false;
1981 GLint numParams = 1;
1982
1983 GLint* iParams = new GLint[numParams];
1984 if (numParams>0 && glGetIntegerv(pname,iParams)) {
1985 while(numParams >= 0)
1986 {
1987 params[numParams] = (GLfloat)iParams[numParams];
1988 numParams--;
1989 }
1990 result = true;
1991 }
1992 delete [] iParams;
1993
1994 return result;
1995 }
1996
glGetIntegerv(GLenum pname,GLint * params)1997 bool GLEScontext::glGetIntegerv(GLenum pname, GLint *params)
1998 {
1999 switch(pname)
2000 {
2001 case GL_ARRAY_BUFFER_BINDING:
2002 *params = m_arrayBuffer;
2003 break;
2004
2005 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
2006 *params = m_currVaoState.iboId();
2007 break;
2008
2009 case GL_TEXTURE_BINDING_CUBE_MAP:
2010 *params = m_texState[m_activeTexture][TEXTURE_CUBE_MAP].texture;
2011 break;
2012
2013 case GL_TEXTURE_BINDING_2D:
2014 *params = m_texState[m_activeTexture][TEXTURE_2D].texture;
2015 break;
2016
2017 case GL_ACTIVE_TEXTURE:
2018 *params = m_activeTexture+GL_TEXTURE0;
2019 break;
2020
2021 case GL_MAX_TEXTURE_SIZE:
2022 *params = getMaxTexSize();
2023 break;
2024 default:
2025 return false;
2026 }
2027
2028 return true;
2029 }
2030
GLTextureTargetToLocal(GLenum target)2031 TextureTarget GLEScontext::GLTextureTargetToLocal(GLenum target) {
2032 TextureTarget value=TEXTURE_2D;
2033 switch (target) {
2034 case GL_TEXTURE_CUBE_MAP:
2035 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2036 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2037 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2038 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2039 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2040 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2041 value = TEXTURE_CUBE_MAP;
2042 break;
2043 case GL_TEXTURE_2D:
2044 value = TEXTURE_2D;
2045 break;
2046 case GL_TEXTURE_2D_ARRAY:
2047 value = TEXTURE_2D_ARRAY;
2048 break;
2049 case GL_TEXTURE_3D:
2050 value = TEXTURE_3D;
2051 break;
2052 case GL_TEXTURE_2D_MULTISAMPLE:
2053 value = TEXTURE_2D_MULTISAMPLE;
2054 break;
2055 }
2056 return value;
2057 }
2058
getBindedTexture(GLenum target)2059 unsigned int GLEScontext::getBindedTexture(GLenum target) {
2060 TextureTarget pos = GLTextureTargetToLocal(target);
2061 return m_texState[m_activeTexture][pos].texture;
2062 }
2063
getBindedTexture(GLenum unit,GLenum target)2064 unsigned int GLEScontext::getBindedTexture(GLenum unit, GLenum target) {
2065 TextureTarget pos = GLTextureTargetToLocal(target);
2066 return m_texState[unit-GL_TEXTURE0][pos].texture;
2067 }
2068
setBindedTexture(GLenum target,unsigned int tex)2069 void GLEScontext::setBindedTexture(GLenum target, unsigned int tex) {
2070 TextureTarget pos = GLTextureTargetToLocal(target);
2071 m_texState[m_activeTexture][pos].texture = tex;
2072 }
2073
setTextureEnabled(GLenum target,GLenum enable)2074 void GLEScontext::setTextureEnabled(GLenum target, GLenum enable) {
2075 TextureTarget pos = GLTextureTargetToLocal(target);
2076 m_texState[m_activeTexture][pos].enabled = enable;
2077 }
2078
2079 #define INTERNAL_NAME(x) (x +0x100000000ll);
2080
getDefaultTextureName(GLenum target)2081 ObjectLocalName GLEScontext::getDefaultTextureName(GLenum target) {
2082 ObjectLocalName name = 0;
2083 switch (GLTextureTargetToLocal(target)) {
2084 case TEXTURE_2D:
2085 name = INTERNAL_NAME(0);
2086 break;
2087 case TEXTURE_CUBE_MAP:
2088 name = INTERNAL_NAME(1);
2089 break;
2090 case TEXTURE_2D_ARRAY:
2091 name = INTERNAL_NAME(2);
2092 break;
2093 case TEXTURE_3D:
2094 name = INTERNAL_NAME(3);
2095 break;
2096 case TEXTURE_2D_MULTISAMPLE:
2097 name = INTERNAL_NAME(4);
2098 break;
2099 default:
2100 name = 0;
2101 break;
2102 }
2103 return name;
2104 }
2105
getTextureLocalName(GLenum target,unsigned int tex)2106 ObjectLocalName GLEScontext::getTextureLocalName(GLenum target,
2107 unsigned int tex) {
2108 return (tex!=0? tex : getDefaultTextureName(target));
2109 }
2110
drawValidate(void)2111 void GLEScontext::drawValidate(void)
2112 {
2113 if(m_drawFramebuffer == 0)
2114 return;
2115
2116 auto fbObj = getFBOData(m_drawFramebuffer);
2117 if (!fbObj)
2118 return;
2119
2120 fbObj->validate(this);
2121 }
2122
initEmulatedEGLSurface(GLint width,GLint height,GLint colorFormat,GLint depthstencilFormat,GLint multisamples,GLuint rboColor,GLuint rboDepth)2123 void GLEScontext::initEmulatedEGLSurface(GLint width, GLint height,
2124 GLint colorFormat, GLint depthstencilFormat, GLint multisamples,
2125 GLuint rboColor, GLuint rboDepth) {
2126 dispatcher().glBindRenderbuffer(GL_RENDERBUFFER, rboColor);
2127 if (multisamples) {
2128 dispatcher().glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisamples, colorFormat, width, height);
2129 GLint err = dispatcher().glGetError();
2130 if (err != GL_NO_ERROR) {
2131 ERR("error setting up multisampled RBO! 0x%x", err);
2132 }
2133 } else {
2134 dispatcher().glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, width, height);
2135 }
2136
2137 dispatcher().glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
2138 if (multisamples) {
2139 dispatcher().glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisamples, depthstencilFormat, width, height);
2140 GLint err = dispatcher().glGetError();
2141 if (err != GL_NO_ERROR) {
2142 ERR("error setting up multisampled RBO! 0x%x", err);
2143 }
2144 } else {
2145 dispatcher().glRenderbufferStorage(GL_RENDERBUFFER, depthstencilFormat, width, height);
2146 }
2147 }
2148
initDefaultFBO(GLint width,GLint height,GLint colorFormat,GLint depthstencilFormat,GLint multisamples,GLuint * eglSurfaceRBColorId,GLuint * eglSurfaceRBDepthId,GLuint readWidth,GLint readHeight,GLint readColorFormat,GLint readDepthStencilFormat,GLint readMultisamples,GLuint * eglReadSurfaceRBColorId,GLuint * eglReadSurfaceRBDepthId)2149 void GLEScontext::initDefaultFBO(
2150 GLint width, GLint height, GLint colorFormat, GLint depthstencilFormat, GLint multisamples,
2151 GLuint* eglSurfaceRBColorId, GLuint* eglSurfaceRBDepthId,
2152 GLuint readWidth, GLint readHeight, GLint readColorFormat, GLint readDepthStencilFormat, GLint readMultisamples,
2153 GLuint* eglReadSurfaceRBColorId, GLuint* eglReadSurfaceRBDepthId) {
2154
2155 if (!m_defaultFBO) {
2156 dispatcher().glGenFramebuffers(1, &m_defaultFBO);
2157 m_defaultReadFBO = m_defaultFBO;
2158 }
2159
2160 bool needReallocateRbo = false;
2161 bool separateReadRbo = false;
2162 bool needReallocateReadRbo = false;
2163
2164 separateReadRbo =
2165 eglReadSurfaceRBColorId !=
2166 eglSurfaceRBColorId;
2167
2168 if (separateReadRbo && (m_defaultReadFBO == m_defaultFBO)) {
2169 dispatcher().glGenFramebuffers(1, &m_defaultReadFBO);
2170 }
2171
2172 if (!(*eglSurfaceRBColorId)) {
2173 dispatcher().glGenRenderbuffers(1, eglSurfaceRBColorId);
2174 dispatcher().glGenRenderbuffers(1, eglSurfaceRBDepthId);
2175 needReallocateRbo = true;
2176 }
2177
2178 if (!(*eglReadSurfaceRBColorId) && separateReadRbo) {
2179 dispatcher().glGenRenderbuffers(1, eglReadSurfaceRBColorId);
2180 dispatcher().glGenRenderbuffers(1, eglReadSurfaceRBDepthId);
2181 needReallocateReadRbo = true;
2182 }
2183
2184 m_defaultFBOColorFormat = colorFormat;
2185 m_defaultFBOWidth = width;
2186 m_defaultFBOHeight = height;
2187 m_defaultFBOSamples = multisamples;
2188
2189 GLint prevRbo;
2190 dispatcher().glGetIntegerv(GL_RENDERBUFFER_BINDING, &prevRbo);
2191
2192 // OS X in legacy opengl mode does not actually support GL_RGB565 as a renderbuffer.
2193 // Just replace it with GL_RGB8 for now.
2194 // TODO: Re-enable GL_RGB565 for OS X when we move to core profile.
2195 #ifdef __APPLE__
2196 if (colorFormat == GL_RGB565)
2197 colorFormat = GL_RGB8;
2198 if (readColorFormat == GL_RGB565)
2199 readColorFormat = GL_RGB8;
2200 #endif
2201
2202 if (needReallocateRbo) {
2203 initEmulatedEGLSurface(width, height, colorFormat, depthstencilFormat, multisamples,
2204 *eglSurfaceRBColorId, *eglSurfaceRBDepthId);
2205 }
2206
2207 if (needReallocateReadRbo) {
2208 initEmulatedEGLSurface(readWidth, readHeight, readColorFormat, readDepthStencilFormat, readMultisamples,
2209 *eglReadSurfaceRBColorId, *eglReadSurfaceRBDepthId);
2210 }
2211
2212 dispatcher().glBindFramebuffer(GL_FRAMEBUFFER, m_defaultFBO);
2213
2214 dispatcher().glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *eglSurfaceRBColorId);
2215 dispatcher().glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *eglSurfaceRBDepthId);
2216 dispatcher().glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, *eglSurfaceRBDepthId);
2217
2218 if (m_defaultFBODrawBuffer != GL_COLOR_ATTACHMENT0) {
2219 dispatcher().glDrawBuffers(1, &m_defaultFBODrawBuffer);
2220 }
2221 if (m_defaultFBOReadBuffer != GL_COLOR_ATTACHMENT0) {
2222 dispatcher().glReadBuffer(m_defaultFBOReadBuffer);
2223 }
2224
2225 if (separateReadRbo) {
2226 dispatcher().glBindFramebuffer(GL_READ_FRAMEBUFFER, m_defaultReadFBO);
2227 dispatcher().glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *eglReadSurfaceRBColorId);
2228 dispatcher().glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *eglReadSurfaceRBDepthId);
2229 dispatcher().glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, *eglReadSurfaceRBDepthId);
2230 }
2231
2232 dispatcher().glBindRenderbuffer(GL_RENDERBUFFER, prevRbo);
2233 GLuint prevDrawFBOBinding = getFramebufferBinding(GL_FRAMEBUFFER);
2234 GLuint prevReadFBOBinding = getFramebufferBinding(GL_READ_FRAMEBUFFER);
2235
2236 if (prevDrawFBOBinding)
2237 dispatcher().glBindFramebuffer(GL_FRAMEBUFFER, getFBOGlobalName(prevDrawFBOBinding));
2238 if (prevReadFBOBinding)
2239 dispatcher().glBindFramebuffer(GL_READ_FRAMEBUFFER, getFBOGlobalName(prevReadFBOBinding));
2240
2241 // We might be initializing a surfaceless context underneath
2242 // where the viewport is initialized to 0x0 width and height.
2243 // Set to our wanted pbuffer dimensions if this is the first time
2244 // the viewport has been set.
2245 if (!m_isViewport) {
2246 setViewport(0, 0, width, height);
2247 dispatcher().glViewport(0, 0, width, height);
2248 }
2249 // same for the scissor
2250 if (!m_isScissor) {
2251 setScissor(0, 0, width, height);
2252 dispatcher().glScissor(0, 0, width, height);
2253 }
2254 }
2255
2256
prepareCoreProfileEmulatedTexture(TextureData * texData,bool is3d,GLenum target,GLenum format,GLenum type,GLint * internalformat_out,GLenum * format_out)2257 void GLEScontext::prepareCoreProfileEmulatedTexture(TextureData* texData, bool is3d, GLenum target,
2258 GLenum format, GLenum type,
2259 GLint* internalformat_out, GLenum* format_out) {
2260 if (format != GL_ALPHA &&
2261 format != GL_LUMINANCE &&
2262 format != GL_LUMINANCE_ALPHA) {
2263 return;
2264 }
2265
2266 if (isCubeMapFaceTarget(target)) {
2267 target = is3d ? GL_TEXTURE_CUBE_MAP_ARRAY_EXT : GL_TEXTURE_CUBE_MAP;
2268 }
2269
2270 // Set up the swizzle from the underlying supported
2271 // host format to the emulated format.
2272 // Make sure to re-apply any user-specified custom swizlz
2273 TextureSwizzle userSwz; // initialized to identity map
2274
2275 if (texData) {
2276 userSwz.toRed = texData->getSwizzle(GL_TEXTURE_SWIZZLE_R);
2277 userSwz.toGreen = texData->getSwizzle(GL_TEXTURE_SWIZZLE_G);
2278 userSwz.toBlue = texData->getSwizzle(GL_TEXTURE_SWIZZLE_B);
2279 userSwz.toAlpha = texData->getSwizzle(GL_TEXTURE_SWIZZLE_A);
2280 }
2281
2282 TextureSwizzle swz =
2283 concatSwizzles(getSwizzleForEmulatedFormat(format),
2284 userSwz);
2285
2286 dispatcher().glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, swz.toRed);
2287 dispatcher().glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, swz.toGreen);
2288 dispatcher().glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, swz.toBlue);
2289 dispatcher().glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, swz.toAlpha);
2290
2291 // Change the format/internalformat communicated to GL.
2292 GLenum emulatedFormat =
2293 getCoreProfileEmulatedFormat(format);
2294 GLint emulatedInternalFormat =
2295 getCoreProfileEmulatedInternalFormat(format, type);
2296
2297 if (format_out) *format_out = emulatedFormat;
2298 if (internalformat_out) *internalformat_out = emulatedInternalFormat;
2299 }
2300
isFBO(ObjectLocalName p_localName)2301 bool GLEScontext::isFBO(ObjectLocalName p_localName) {
2302 return m_fboNameSpace->isObject(p_localName);
2303 }
2304
genFBOName(ObjectLocalName p_localName,bool genLocal)2305 ObjectLocalName GLEScontext::genFBOName(ObjectLocalName p_localName,
2306 bool genLocal) {
2307 return m_fboNameSpace->genName(GenNameInfo(NamedObjectType::FRAMEBUFFER),
2308 p_localName, genLocal);
2309 }
2310
setFBOData(ObjectLocalName p_localName,ObjectDataPtr data)2311 void GLEScontext::setFBOData(ObjectLocalName p_localName, ObjectDataPtr data) {
2312 m_fboNameSpace->setObjectData(p_localName, data);
2313 }
2314
deleteFBO(ObjectLocalName p_localName)2315 void GLEScontext::deleteFBO(ObjectLocalName p_localName) {
2316 m_fboNameSpace->deleteName(p_localName);
2317 }
2318
getFBOData(ObjectLocalName p_localName) const2319 FramebufferData* GLEScontext::getFBOData(ObjectLocalName p_localName) const {
2320 return (FramebufferData*)getFBODataPtr(p_localName).get();
2321 }
2322
getFBODataPtr(ObjectLocalName p_localName) const2323 ObjectDataPtr GLEScontext::getFBODataPtr(ObjectLocalName p_localName) const {
2324 return m_fboNameSpace->getObjectDataPtr(p_localName);
2325 }
2326
getFBOGlobalName(ObjectLocalName p_localName) const2327 unsigned int GLEScontext::getFBOGlobalName(ObjectLocalName p_localName) const {
2328 return m_fboNameSpace->getGlobalName(p_localName);
2329 }
2330
getFBOLocalName(unsigned int p_globalName) const2331 ObjectLocalName GLEScontext::getFBOLocalName(unsigned int p_globalName) const {
2332 return m_fboNameSpace->getLocalName(p_globalName);
2333 }
2334
queryCurrFboBits(ObjectLocalName localFboName,GLenum pname)2335 int GLEScontext::queryCurrFboBits(ObjectLocalName localFboName, GLenum pname) {
2336 GLint colorInternalFormat = 0;
2337 GLint depthInternalFormat = 0;
2338 GLint stencilInternalFormat = 0;
2339 bool combinedDepthStencil = false;
2340
2341 if (!localFboName) {
2342 colorInternalFormat = m_defaultFBOColorFormat;
2343 // FBO 0 defaulting to d24s8
2344 depthInternalFormat =
2345 m_defaultFBODepthFormat ? m_defaultFBODepthFormat : GL_DEPTH24_STENCIL8;
2346 stencilInternalFormat =
2347 m_defaultFBOStencilFormat ? m_defaultFBOStencilFormat : GL_DEPTH24_STENCIL8;
2348 } else {
2349 FramebufferData* fbData = getFBOData(localFboName);
2350
2351 std::vector<GLenum> colorAttachments(getCaps()->maxDrawBuffers);
2352 std::iota(colorAttachments.begin(), colorAttachments.end(), GL_COLOR_ATTACHMENT0);
2353
2354 bool hasColorAttachment = false;
2355 for (auto attachment : colorAttachments) {
2356 GLint internalFormat =
2357 fbData->getAttachmentInternalFormat(this, attachment);
2358
2359 // Only defined if all used color attachments are the same
2360 // internal format.
2361 if (internalFormat) {
2362 if (hasColorAttachment &&
2363 colorInternalFormat != internalFormat) {
2364 colorInternalFormat = 0;
2365 break;
2366 }
2367 colorInternalFormat = internalFormat;
2368 hasColorAttachment = true;
2369 }
2370 }
2371
2372 GLint depthStencilFormat =
2373 fbData->getAttachmentInternalFormat(this, GL_DEPTH_STENCIL_ATTACHMENT);
2374
2375 if (depthStencilFormat) {
2376 combinedDepthStencil = true;
2377 depthInternalFormat = depthStencilFormat;
2378 stencilInternalFormat = depthStencilFormat;
2379 }
2380
2381 if (!combinedDepthStencil) {
2382 depthInternalFormat =
2383 fbData->getAttachmentInternalFormat(this, GL_DEPTH_ATTACHMENT);
2384 stencilInternalFormat =
2385 fbData->getAttachmentInternalFormat(this, GL_STENCIL_ATTACHMENT);
2386 }
2387 }
2388
2389 FramebufferChannelBits res =
2390 glFormatToChannelBits(colorInternalFormat,
2391 depthInternalFormat,
2392 stencilInternalFormat);
2393
2394 switch (pname) {
2395 case GL_RED_BITS:
2396 return res.red;
2397 case GL_GREEN_BITS:
2398 return res.green;
2399 case GL_BLUE_BITS:
2400 return res.blue;
2401 case GL_ALPHA_BITS:
2402 return res.alpha;
2403 case GL_DEPTH_BITS:
2404 return res.depth;
2405 case GL_STENCIL_BITS:
2406 return res.stencil;
2407 }
2408
2409 return 0;
2410 }
2411
2412 static const char kTexImageEmulationVShaderSrc[] = R"(
2413 precision highp float;
2414 out vec2 v_texcoord;
2415 void main() {
2416 const vec2 quad_pos[6] = vec2[6](
2417 vec2(0.0, 0.0),
2418 vec2(0.0, 1.0),
2419 vec2(1.0, 0.0),
2420 vec2(0.0, 1.0),
2421 vec2(1.0, 0.0),
2422 vec2(1.0, 1.0));
2423
2424 gl_Position = vec4((quad_pos[gl_VertexID] * 2.0) - 1.0, 0.0, 1.0);
2425 v_texcoord = quad_pos[gl_VertexID];
2426 })";
2427
2428 static const char kTexImageEmulationVShaderSrcFlipped[] = R"(
2429 precision highp float;
2430 layout (location = 0) in vec2 a_pos;
2431 out vec2 v_texcoord;
2432 void main() {
2433 gl_Position = vec4((a_pos.xy) * 2.0 - 1.0, 0.0, 1.0);
2434 v_texcoord = a_pos;
2435 v_texcoord.y = 1.0 - v_texcoord.y;
2436 })";
2437
2438 static const char kTexImageEmulationFShaderSrc[] = R"(
2439 precision highp float;
2440 uniform sampler2D source_tex;
2441 in vec2 v_texcoord;
2442 out vec4 color;
2443 void main() {
2444 color = texture(source_tex, v_texcoord);
2445 })";
2446
initTexImageEmulation()2447 void GLEScontext::initTexImageEmulation() {
2448 if (m_textureEmulationProg) return;
2449
2450 auto& gl = dispatcher();
2451
2452 std::string vshaderSrc = isCoreProfile() ? "#version 330 core\n" : "#version 300 es\n";
2453 vshaderSrc += kTexImageEmulationVShaderSrc;
2454 std::string fshaderSrc = isCoreProfile() ? "#version 330 core\n" : "#version 300 es\n";
2455 fshaderSrc += kTexImageEmulationFShaderSrc;
2456
2457 GLuint vshader =
2458 compileAndValidateCoreShader(GL_VERTEX_SHADER,
2459 vshaderSrc.c_str());
2460 GLuint fshader =
2461 compileAndValidateCoreShader(GL_FRAGMENT_SHADER,
2462 fshaderSrc.c_str());
2463 m_textureEmulationProg = linkAndValidateProgram(vshader, fshader);
2464 m_textureEmulationSamplerLoc =
2465 gl.glGetUniformLocation(m_textureEmulationProg, "source_tex");
2466
2467 gl.glGenFramebuffers(1, &m_textureEmulationFBO);
2468 gl.glGenTextures(2, m_textureEmulationTextures);
2469 gl.glGenVertexArrays(1, &m_textureEmulationVAO);
2470 }
2471
copyTexImageWithEmulation(TextureData * texData,bool isSubImage,GLenum target,GLint level,GLenum internalformat,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)2472 void GLEScontext::copyTexImageWithEmulation(
2473 TextureData* texData,
2474 bool isSubImage,
2475 GLenum target,
2476 GLint level,
2477 GLenum internalformat,
2478 GLint xoffset, GLint yoffset,
2479 GLint x, GLint y,
2480 GLsizei width, GLsizei height,
2481 GLint border) {
2482
2483 // Create objects used for emulation if they don't exist already.
2484 initTexImageEmulation();
2485 auto& gl = dispatcher();
2486
2487 // Save all affected state.
2488 ScopedGLState state;
2489 state.pushForCoreProfileTextureEmulation();
2490
2491 // render to an intermediate texture with the same format:
2492 // 1. Get the format
2493 FramebufferData* fbData =
2494 getFBOData(getFramebufferBinding(GL_READ_FRAMEBUFFER));
2495 GLint readFbInternalFormat =
2496 fbData ? fbData->getAttachmentInternalFormat(this, GL_COLOR_ATTACHMENT0) :
2497 m_defaultFBOColorFormat;
2498
2499 // 2. Create the texture for textures[0] with this format, and initialize
2500 // it to the current FBO read buffer.
2501 gl.glBindTexture(GL_TEXTURE_2D, m_textureEmulationTextures[0]);
2502 gl.glCopyTexImage2D(GL_TEXTURE_2D, 0, readFbInternalFormat,
2503 x, y, width, height, 0);
2504
2505 // 3. Set swizzle of textures[0] so they are read in the right way
2506 // when drawing to textures[1].
2507 TextureSwizzle swz = getInverseSwizzleForEmulatedFormat(texData->format);
2508 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, swz.toRed);
2509 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, swz.toGreen);
2510 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, swz.toBlue);
2511 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, swz.toAlpha);
2512 // Also, nearest filtering
2513 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2514 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2515
2516 // 4. Initialize textures[1] with same width/height, and use it to back
2517 // the FBO that holds the swizzled results.
2518 gl.glBindTexture(GL_TEXTURE_2D, m_textureEmulationTextures[1]);
2519 gl.glTexImage2D(GL_TEXTURE_2D, 0, readFbInternalFormat, width, height, 0,
2520 baseFormatOfInternalFormat(readFbInternalFormat),
2521 accurateTypeOfInternalFormat(readFbInternalFormat),
2522 nullptr);
2523 // Also, nearest filtering
2524 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2525 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2526
2527 gl.glBindFramebuffer(GL_FRAMEBUFFER, m_textureEmulationFBO);
2528 gl.glFramebufferTexture2D(
2529 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
2530 m_textureEmulationTextures[1], 0);
2531
2532 // 5. Draw textures[0] to our FBO, making sure all state is compatible.
2533 gl.glDisable(GL_BLEND);
2534 gl.glDisable(GL_SCISSOR_TEST);
2535 gl.glDisable(GL_DEPTH_TEST);
2536 gl.glDisable(GL_STENCIL_TEST);
2537 gl.glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
2538 gl.glDisable(GL_SAMPLE_COVERAGE);
2539 gl.glDisable(GL_CULL_FACE);
2540 gl.glDisable(GL_POLYGON_OFFSET_FILL);
2541 gl.glDisable(GL_RASTERIZER_DISCARD);
2542
2543 gl.glViewport(0, 0, width, height);
2544
2545 if (isGles2Gles()) {
2546 gl.glDepthRangef(0.0f, 1.0f);
2547 } else {
2548 gl.glDepthRange(0.0f, 1.0f);
2549 }
2550
2551 gl.glColorMask(1, 1, 1, 1);
2552
2553 gl.glBindTexture(GL_TEXTURE_2D, m_textureEmulationTextures[0]);
2554 GLint texUnit; gl.glGetIntegerv(GL_ACTIVE_TEXTURE, &texUnit);
2555
2556 gl.glUseProgram(m_textureEmulationProg);
2557 gl.glUniform1i(m_textureEmulationSamplerLoc, texUnit - GL_TEXTURE0);
2558
2559 gl.glBindVertexArray(m_textureEmulationVAO);
2560
2561 gl.glDrawArrays(GL_TRIANGLES, 0, 6);
2562
2563 // now the emulated version has been rendered and written to the read FBO
2564 // with the correct swizzle.
2565 if (isCubeMapFaceTarget(target)) {
2566 gl.glBindTexture(GL_TEXTURE_CUBE_MAP, texData->getGlobalName());
2567 } else {
2568 gl.glBindTexture(target, texData->getGlobalName());
2569 }
2570
2571 if (isSubImage) {
2572 gl.glCopyTexSubImage2D(target, level, xoffset, yoffset, 0, 0, width, height);
2573 } else {
2574 gl.glCopyTexImage2D(target, level, internalformat, 0, 0, width, height, border);
2575 }
2576 }
2577
2578 // static
compileAndValidateCoreShader(GLenum shaderType,const char * src)2579 GLuint GLEScontext::compileAndValidateCoreShader(GLenum shaderType, const char* src) {
2580 GLDispatch& gl = dispatcher();
2581
2582 GLuint shader = gl.glCreateShader(shaderType);
2583 gl.glShaderSource(shader, 1, (const GLchar* const*)&src, nullptr);
2584 gl.glCompileShader(shader);
2585
2586 GLint compileStatus;
2587 gl.glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
2588
2589 if (compileStatus != GL_TRUE) {
2590 GLsizei infoLogLength = 0;
2591 gl.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
2592 std::vector<char> infoLog(infoLogLength + 1, 0);
2593 gl.glGetShaderInfoLog(shader, infoLogLength, nullptr, &infoLog[0]);
2594 ERR("fail to compile. infolog %s", &infoLog[0]);
2595 }
2596
2597 return shader;
2598 }
2599
2600 // static
linkAndValidateProgram(GLuint vshader,GLuint fshader)2601 GLuint GLEScontext::linkAndValidateProgram(GLuint vshader, GLuint fshader) {
2602 GLDispatch& gl = dispatcher();
2603
2604 GLuint program = gl.glCreateProgram();
2605 gl.glAttachShader(program, vshader);
2606 gl.glAttachShader(program, fshader);
2607 gl.glLinkProgram(program);
2608
2609 GLint linkStatus;
2610 gl.glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
2611
2612 if (linkStatus != GL_TRUE) {
2613 GLsizei infoLogLength = 0;
2614 gl.glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
2615 std::vector<char> infoLog(infoLogLength + 1, 0);
2616 gl.glGetProgramInfoLog(program, infoLogLength, nullptr, &infoLog[0]);
2617 ERR("fail to link program. infolog: %s", &infoLog[0]);
2618 }
2619
2620 gl.glDeleteShader(vshader);
2621 gl.glDeleteShader(fshader);
2622
2623 return program;
2624 }
2625
getReadBufferSamples()2626 int GLEScontext::getReadBufferSamples() {
2627 GLuint readFboBinding = getFramebufferBinding(GL_READ_FRAMEBUFFER);
2628 bool defaultFboReadBufferBound = readFboBinding == 0;
2629 if (defaultFboReadBufferBound) {
2630 return m_defaultFBOSamples;
2631 } else {
2632 FramebufferData* fbData = (FramebufferData*)(getFBODataPtr(readFboBinding).get());
2633 return fbData ? fbData->getAttachmentSamples(this, fbData->getReadBuffer()) : 0;
2634 }
2635 }
2636
getReadBufferInternalFormat()2637 int GLEScontext::getReadBufferInternalFormat() {
2638 GLuint readFboBinding = getFramebufferBinding(GL_READ_FRAMEBUFFER);
2639 bool defaultFboReadBufferBound = readFboBinding == 0;
2640 if (defaultFboReadBufferBound) {
2641 return m_defaultFBOColorFormat;
2642 } else {
2643 FramebufferData* fbData = (FramebufferData*)(getFBODataPtr(readFboBinding).get());
2644 return fbData ? fbData->getAttachmentInternalFormat(this, fbData->getReadBuffer()) : 0;
2645 }
2646 }
2647
getReadBufferDimensions(GLint * width,GLint * height)2648 void GLEScontext::getReadBufferDimensions(GLint* width, GLint* height) {
2649 GLuint readFboBinding = getFramebufferBinding(GL_READ_FRAMEBUFFER);
2650 bool defaultFboReadBufferBound = readFboBinding == 0;
2651 if (defaultFboReadBufferBound) {
2652 *width = m_defaultFBOWidth;
2653 *height = m_defaultFBOHeight;
2654 } else {
2655 FramebufferData* fbData = (FramebufferData*)(getFBODataPtr(readFboBinding).get());
2656 if (fbData) {
2657 fbData->getAttachmentDimensions(
2658 this, fbData->getReadBuffer(), width, height);
2659 }
2660 }
2661 }
2662
setupImageBlitState()2663 void GLEScontext::setupImageBlitState() {
2664 auto& gl = dispatcher();
2665 m_blitState.prevSamples = m_blitState.samples;
2666 m_blitState.samples = getReadBufferSamples();
2667
2668 if (m_blitState.program) return;
2669
2670 std::string vshaderSrc =
2671 isCoreProfile() ? "#version 330 core\n" : "#version 300 es\n";
2672 vshaderSrc += kTexImageEmulationVShaderSrcFlipped;
2673
2674 std::string fshaderSrc =
2675 isCoreProfile() ? "#version 330 core\n" : "#version 300 es\n";
2676 fshaderSrc += kTexImageEmulationFShaderSrc;
2677
2678 GLuint vshader =
2679 compileAndValidateCoreShader(GL_VERTEX_SHADER, vshaderSrc.c_str());
2680 GLuint fshader =
2681 compileAndValidateCoreShader(GL_FRAGMENT_SHADER, fshaderSrc.c_str());
2682
2683 m_blitState.program = linkAndValidateProgram(vshader, fshader);
2684 m_blitState.samplerLoc =
2685 gl.glGetUniformLocation(m_blitState.program, "source_tex");
2686
2687 gl.glGenFramebuffers(1, &m_blitState.fbo);
2688 gl.glGenFramebuffers(1, &m_blitState.resolveFbo);
2689 gl.glGenTextures(1, &m_blitState.tex);
2690 gl.glGenVertexArrays(1, &m_blitState.vao);
2691
2692 gl.glGenBuffers(1, &m_blitState.vbo);
2693 float blitVbo[] = {
2694 0.0f, 0.0f,
2695 1.0f, 0.0f,
2696 0.0f, 1.0f,
2697 1.0f, 0.0f,
2698 1.0f, 1.0f,
2699 0.0f, 1.0f,
2700 };
2701
2702 GLint buf;
2703 gl.glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &buf);
2704
2705 gl.glBindBuffer(GL_ARRAY_BUFFER, m_blitState.vbo);
2706 gl.glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), blitVbo, GL_STATIC_DRAW);
2707
2708 gl.glBindVertexArray(m_blitState.vao);
2709 gl.glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);
2710 gl.glEnableVertexAttribArray(0);
2711
2712 gl.glBindBuffer(GL_ARRAY_BUFFER, buf);
2713 }
2714
setupImageBlitForTexture(uint32_t width,uint32_t height,GLint internalFormat)2715 bool GLEScontext::setupImageBlitForTexture(uint32_t width,
2716 uint32_t height,
2717 GLint internalFormat) {
2718 GLint sizedInternalFormat = GL_RGBA8;
2719 if (internalFormat != GL_RGBA8 &&
2720 internalFormat != GL_RGB8 &&
2721 internalFormat != GL_RGB565) {
2722 switch (internalFormat) {
2723 case GL_RGB:
2724 sizedInternalFormat = GL_RGB8;
2725 break;
2726 case GL_RGBA:
2727 sizedInternalFormat = GL_RGBA8;
2728 break;
2729 default:
2730 break;
2731 }
2732 }
2733
2734 auto& gl = dispatcher();
2735 gl.glBindTexture(GL_TEXTURE_2D, m_blitState.tex);
2736
2737 GLint read_iformat = getReadBufferInternalFormat();
2738 GLint read_format = baseFormatOfInternalFormat(read_iformat);
2739
2740 if (isIntegerInternalFormat(read_iformat) ||
2741 read_iformat == GL_RGB10_A2) {
2742 // Is not a blittable format. Just create the texture for now to
2743 // make image blit state consistent.
2744 gl.glTexImage2D(GL_TEXTURE_2D, 0, sizedInternalFormat, width, height, 0,
2745 baseFormatOfInternalFormat(internalFormat), GL_UNSIGNED_BYTE, 0);
2746 return false;
2747 }
2748
2749 if (width != m_blitState.width || height != m_blitState.height ||
2750 internalFormat != m_blitState.internalFormat ||
2751 m_blitState.samples != m_blitState.prevSamples) {
2752
2753 m_blitState.width = width;
2754 m_blitState.height = height;
2755 m_blitState.internalFormat = internalFormat;
2756
2757 gl.glTexImage2D(GL_TEXTURE_2D, 0,
2758 read_iformat, width, height, 0, read_format, GL_UNSIGNED_BYTE, 0);
2759 if (m_blitState.samples > 0) {
2760 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_blitState.resolveFbo);
2761 gl.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2762 GL_TEXTURE_2D, m_blitState.tex, 0);
2763 }
2764
2765 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2766 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2767 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2768 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2769 }
2770
2771 // In eglSwapBuffers, the surface must be bound as the draw surface of
2772 // the current context, which corresponds to m_defaultFBO here.
2773 //
2774 // EGL 1.4 spec:
2775 //
2776 // 3.9.3 Posting Semantics surface must be bound to the draw surface of the
2777 // calling thread’s current context, for the current rendering API. This
2778 // restriction may be lifted in future EGL revisions.
2779 //
2780 const GLuint readFboBinding = getFramebufferBinding(GL_READ_FRAMEBUFFER);
2781 if (readFboBinding != 0) {
2782 gl.glBindFramebuffer(GL_READ_FRAMEBUFFER, m_defaultFBO);
2783 }
2784
2785 if (m_blitState.samples > 0) {
2786 GLint rWidth = width;
2787 GLint rHeight = height;
2788 getReadBufferDimensions(&rWidth, &rHeight);
2789 gl.glBindTexture(GL_TEXTURE_2D, 0);
2790 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_blitState.resolveFbo);
2791 gl.glBlitFramebuffer(0, 0, rWidth, rHeight, 0, 0, rWidth, rHeight,
2792 GL_COLOR_BUFFER_BIT, GL_NEAREST);
2793 gl.glBindTexture(GL_TEXTURE_2D, m_blitState.tex);
2794 } else {
2795 gl.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
2796 }
2797
2798 return true;
2799 }
2800
blitFromReadBufferToTextureFlipped(GLuint globalTexObj,GLuint width,GLuint height,GLint internalFormat,GLenum format,GLenum type)2801 void GLEScontext::blitFromReadBufferToTextureFlipped(GLuint globalTexObj,
2802 GLuint width,
2803 GLuint height,
2804 GLint internalFormat,
2805 GLenum format,
2806 GLenum type) {
2807 // TODO: these might also matter
2808 (void)format;
2809 (void)type;
2810
2811 auto& gl = dispatcher();
2812 GLint prevViewport[4];
2813 getViewport(prevViewport);
2814
2815 setupImageBlitState();
2816 bool shouldBlit = setupImageBlitForTexture(width, height, internalFormat);
2817
2818 if (!shouldBlit) return;
2819
2820 // b/159670873: The texture to blit doesn't necessarily match the display
2821 // size. If it doesn't match, then we might not be using the right mipmap
2822 // level, which can result in a black screen. Set to always use level 0.
2823 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
2824 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
2825
2826 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2827 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2828 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2829 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2830
2831 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_blitState.fbo);
2832 gl.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2833 GL_TEXTURE_2D, globalTexObj, 0);
2834
2835 gl.glDisable(GL_BLEND);
2836 gl.glDisable(GL_SCISSOR_TEST);
2837 gl.glDisable(GL_DEPTH_TEST);
2838 gl.glDisable(GL_STENCIL_TEST);
2839 gl.glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
2840 gl.glDisable(GL_SAMPLE_COVERAGE);
2841 gl.glDisable(GL_CULL_FACE);
2842 gl.glDisable(GL_POLYGON_OFFSET_FILL);
2843 gl.glDisable(GL_RASTERIZER_DISCARD);
2844
2845 gl.glViewport(0, 0, width, height);
2846 if (isGles2Gles()) {
2847 gl.glDepthRangef(0.0f, 1.0f);
2848 } else {
2849 gl.glDepthRange(0.0f, 1.0f);
2850 }
2851 gl.glColorMask(1, 1, 1, 1);
2852
2853 gl.glUseProgram(m_blitState.program);
2854 gl.glUniform1i(m_blitState.samplerLoc, m_activeTexture);
2855
2856 gl.glBindVertexArray(m_blitState.vao);
2857 gl.glDrawArrays(GL_TRIANGLES, 0, 6);
2858
2859 // state restore
2860 const GLuint globalProgramName = shareGroup()->getGlobalName(
2861 NamedObjectType::SHADER_OR_PROGRAM, m_useProgram);
2862 gl.glUseProgram(globalProgramName);
2863
2864 gl.glBindVertexArray(getVAOGlobalName(m_currVaoState.vaoId()));
2865
2866 gl.glBindTexture(
2867 GL_TEXTURE_2D,
2868 shareGroup()->getGlobalName(
2869 NamedObjectType::TEXTURE,
2870 getTextureLocalName(GL_TEXTURE_2D,
2871 getBindedTexture(GL_TEXTURE_2D))));
2872
2873 GLuint drawFboBinding = getFramebufferBinding(GL_DRAW_FRAMEBUFFER);
2874 GLuint readFboBinding = getFramebufferBinding(GL_READ_FRAMEBUFFER);
2875
2876 gl.glBindFramebuffer(
2877 GL_DRAW_FRAMEBUFFER,
2878 drawFboBinding ? getFBOGlobalName(drawFboBinding) : m_defaultFBO);
2879 gl.glBindFramebuffer(
2880 GL_READ_FRAMEBUFFER,
2881 readFboBinding ? getFBOGlobalName(readFboBinding) : m_defaultReadFBO);
2882
2883 if (isEnabled(GL_BLEND)) gl.glEnable(GL_BLEND);
2884 if (isEnabled(GL_SCISSOR_TEST)) gl.glEnable(GL_SCISSOR_TEST);
2885 if (isEnabled(GL_DEPTH_TEST)) gl.glEnable(GL_DEPTH_TEST);
2886 if (isEnabled(GL_STENCIL_TEST)) gl.glEnable(GL_STENCIL_TEST);
2887 if (isEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)) gl.glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
2888 if (isEnabled(GL_SAMPLE_COVERAGE)) gl.glEnable(GL_SAMPLE_COVERAGE);
2889 if (isEnabled(GL_CULL_FACE)) gl.glEnable(GL_CULL_FACE);
2890 if (isEnabled(GL_POLYGON_OFFSET_FILL)) gl.glEnable(GL_POLYGON_OFFSET_FILL);
2891 if (isEnabled(GL_RASTERIZER_DISCARD)) gl.glEnable(GL_RASTERIZER_DISCARD);
2892
2893 gl.glViewport(prevViewport[0], prevViewport[1],
2894 prevViewport[2], prevViewport[3]);
2895
2896 if (isGles2Gles()) {
2897 gl.glDepthRangef(m_zNear, m_zFar);
2898 } else {
2899 gl.glDepthRange(m_zNear, m_zFar);
2900 }
2901
2902 gl.glColorMask(m_colorMaskR, m_colorMaskG, m_colorMaskB, m_colorMaskA);
2903
2904 gl.glFlush();
2905 }
2906
blitFromReadBufferToEGLImage(EGLImage image,GLint internalFormat,int width,int height)2907 void GLEScontext::blitFromReadBufferToEGLImage(EGLImage image, GLint internalFormat, int width, int height) {
2908
2909 auto& gl = dispatcher();
2910 GLint prevViewport[4];
2911 getViewport(prevViewport);
2912
2913 setupImageBlitState();
2914 bool shouldBlit = setupImageBlitForTexture(width, height, internalFormat);
2915
2916 if (!shouldBlit) return;
2917
2918 // b/159670873: The texture to blit doesn't necessarily match the display
2919 // size. If it doesn't match, then we might not be using the right mipmap
2920 // level, which can result in a black screen. Set to always use level 0.
2921 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
2922 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
2923
2924 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2925 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2926 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2927 gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2928
2929 if (!m_blitState.eglImageTex) {
2930 gl.glGenTextures(1, &m_blitState.eglImageTex);
2931 }
2932
2933 gl.glBindTexture(GL_TEXTURE_2D, m_blitState.eglImageTex);
2934 gl.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
2935 gl.glBindTexture(GL_TEXTURE_2D, m_blitState.tex);
2936 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_blitState.fbo);
2937 gl.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2938 GL_TEXTURE_2D, m_blitState.eglImageTex, 0);
2939
2940 gl.glDisable(GL_BLEND);
2941 gl.glDisable(GL_SCISSOR_TEST);
2942 gl.glDisable(GL_DEPTH_TEST);
2943 gl.glDisable(GL_STENCIL_TEST);
2944 gl.glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
2945 gl.glDisable(GL_SAMPLE_COVERAGE);
2946 gl.glDisable(GL_CULL_FACE);
2947 gl.glDisable(GL_POLYGON_OFFSET_FILL);
2948 gl.glDisable(GL_RASTERIZER_DISCARD);
2949
2950 gl.glViewport(0, 0, width, height);
2951 if (isGles2Gles()) {
2952 gl.glDepthRangef(0.0f, 1.0f);
2953 } else {
2954 gl.glDepthRange(0.0f, 1.0f);
2955 }
2956 gl.glColorMask(1, 1, 1, 1);
2957
2958 gl.glUseProgram(m_blitState.program);
2959 gl.glUniform1i(m_blitState.samplerLoc, m_activeTexture);
2960
2961 gl.glBindVertexArray(m_blitState.vao);
2962 gl.glDrawArrays(GL_TRIANGLES, 0, 6);
2963
2964 // state restore
2965 const GLuint globalProgramName = shareGroup()->getGlobalName(
2966 NamedObjectType::SHADER_OR_PROGRAM, m_useProgram);
2967 gl.glUseProgram(globalProgramName);
2968
2969 gl.glBindVertexArray(getVAOGlobalName(m_currVaoState.vaoId()));
2970
2971 gl.glBindTexture(
2972 GL_TEXTURE_2D,
2973 shareGroup()->getGlobalName(
2974 NamedObjectType::TEXTURE,
2975 getTextureLocalName(GL_TEXTURE_2D,
2976 getBindedTexture(GL_TEXTURE_2D))));
2977
2978 GLuint drawFboBinding = getFramebufferBinding(GL_DRAW_FRAMEBUFFER);
2979 GLuint readFboBinding = getFramebufferBinding(GL_READ_FRAMEBUFFER);
2980
2981 gl.glBindFramebuffer(
2982 GL_DRAW_FRAMEBUFFER,
2983 drawFboBinding ? getFBOGlobalName(drawFboBinding) : m_defaultFBO);
2984 gl.glBindFramebuffer(
2985 GL_READ_FRAMEBUFFER,
2986 readFboBinding ? getFBOGlobalName(readFboBinding) : m_defaultReadFBO);
2987
2988 if (isEnabled(GL_BLEND)) gl.glEnable(GL_BLEND);
2989 if (isEnabled(GL_SCISSOR_TEST)) gl.glEnable(GL_SCISSOR_TEST);
2990 if (isEnabled(GL_DEPTH_TEST)) gl.glEnable(GL_DEPTH_TEST);
2991 if (isEnabled(GL_STENCIL_TEST)) gl.glEnable(GL_STENCIL_TEST);
2992 if (isEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)) gl.glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
2993 if (isEnabled(GL_SAMPLE_COVERAGE)) gl.glEnable(GL_SAMPLE_COVERAGE);
2994 if (isEnabled(GL_CULL_FACE)) gl.glEnable(GL_CULL_FACE);
2995 if (isEnabled(GL_POLYGON_OFFSET_FILL)) gl.glEnable(GL_POLYGON_OFFSET_FILL);
2996 if (isEnabled(GL_RASTERIZER_DISCARD)) gl.glEnable(GL_RASTERIZER_DISCARD);
2997
2998 gl.glViewport(prevViewport[0], prevViewport[1],
2999 prevViewport[2], prevViewport[3]);
3000
3001 if (isGles2Gles()) {
3002 gl.glDepthRangef(m_zNear, m_zFar);
3003 } else {
3004 gl.glDepthRange(m_zNear, m_zFar);
3005 }
3006
3007 gl.glColorMask(m_colorMaskR, m_colorMaskG, m_colorMaskB, m_colorMaskA);
3008
3009 gl.glFlush();
3010 }
3011
3012 // Primitive restart emulation
3013 #define GL_PRIMITIVE_RESTART 0x8F9D
3014 #define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
3015
setPrimitiveRestartEnabled(bool enabled)3016 void GLEScontext::setPrimitiveRestartEnabled(bool enabled) {
3017 auto& gl = dispatcher();
3018
3019 if (enabled) {
3020 gl.glEnable(GL_PRIMITIVE_RESTART);
3021 } else {
3022 gl.glDisable(GL_PRIMITIVE_RESTART);
3023 }
3024
3025 m_primitiveRestartEnabled = enabled;
3026 }
3027
updatePrimitiveRestartIndex(GLenum type)3028 void GLEScontext::updatePrimitiveRestartIndex(GLenum type) {
3029 auto& gl = dispatcher();
3030 switch (type) {
3031 case GL_UNSIGNED_BYTE:
3032 gl.glPrimitiveRestartIndex(0xff);
3033 break;
3034 case GL_UNSIGNED_SHORT:
3035 gl.glPrimitiveRestartIndex(0xffff);
3036 break;
3037 case GL_UNSIGNED_INT:
3038 gl.glPrimitiveRestartIndex(0xffffffff);
3039 break;
3040 }
3041 }
3042
isVAO(ObjectLocalName p_localName)3043 bool GLEScontext::isVAO(ObjectLocalName p_localName) {
3044 VAOStateMap::iterator it = m_vaoStateMap.find(p_localName);
3045 if (it == m_vaoStateMap.end()) return false;
3046 VAOStateRef vao(it);
3047 return vao.isEverBound();
3048 }
3049
genVAOName(ObjectLocalName p_localName,bool genLocal)3050 ObjectLocalName GLEScontext::genVAOName(ObjectLocalName p_localName,
3051 bool genLocal) {
3052 return m_vaoNameSpace->genName(GenNameInfo(NamedObjectType::VERTEX_ARRAY_OBJECT),
3053 p_localName, genLocal);
3054 }
3055
deleteVAO(ObjectLocalName p_localName)3056 void GLEScontext::deleteVAO(ObjectLocalName p_localName) {
3057 m_vaoNameSpace->deleteName(p_localName);
3058 }
3059
getVAOGlobalName(ObjectLocalName p_localName)3060 unsigned int GLEScontext::getVAOGlobalName(ObjectLocalName p_localName) {
3061 return m_vaoNameSpace->getGlobalName(p_localName);
3062 }
3063
getVAOLocalName(unsigned int p_globalName)3064 ObjectLocalName GLEScontext::getVAOLocalName(unsigned int p_globalName) {
3065 return m_vaoNameSpace->getLocalName(p_globalName);
3066 }
3067
setDefaultFBODrawBuffer(GLenum buffer)3068 void GLEScontext::setDefaultFBODrawBuffer(GLenum buffer) {
3069 m_defaultFBODrawBuffer = buffer;
3070 }
3071
setDefaultFBOReadBuffer(GLenum buffer)3072 void GLEScontext::setDefaultFBOReadBuffer(GLenum buffer) {
3073 m_defaultFBOReadBuffer = buffer;
3074 }
3075