• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17 #include "GLESv2Context.h"
18 
19 #include "ProgramData.h"
20 #include "SamplerData.h"
21 #include "ShaderParser.h"
22 #include "TransformFeedbackData.h"
23 #include "base/Lock.h"
24 #include "base/StreamSerializing.h"
25 
26 #include "host-common/crash_reporter.h"
27 
28 #include <string.h>
29 
30 static const char kGLES20StringPart[] = "OpenGL ES 2.0";
31 static const char kGLES30StringPart[] = "OpenGL ES 3.0";
32 static const char kGLES31StringPart[] = "OpenGL ES 3.1";
33 static const char kGLES32StringPart[] = "OpenGL ES 3.2";
34 
35 static GLESVersion s_maxGlesVersion = GLES_2_0;
36 
sPickVersionStringPart(int maj,int min)37 static const char* sPickVersionStringPart(int maj, int min) {
38     switch (maj) {
39         case 2:
40             return kGLES20StringPart;
41         case 3:
42             switch (min) {
43                 case 0:
44                     return kGLES30StringPart;
45                 case 1:
46                     return kGLES31StringPart;
47                 case 2:
48                     return kGLES32StringPart;
49                 default:
50                     return nullptr;
51             }
52         default:
53             return nullptr;
54     }
55     return nullptr;
56 }
57 
setMaxGlesVersion(GLESVersion version)58 void GLESv2Context::setMaxGlesVersion(GLESVersion version) {
59     s_maxGlesVersion = version;
60 }
61 
initGlobal(EGLiface * iface)62 void GLESv2Context::initGlobal(EGLiface* iface) {
63     s_glDispatch.dispatchFuncs(s_maxGlesVersion, iface->eglGetGlLibrary(), iface->getProcAddress);
64     GLEScontext::initGlobal(iface);
65 }
66 
init()67 void GLESv2Context::init() {
68     android::base::AutoLock mutex(s_lock);
69     if(!m_initialized) {
70         GLEScontext::init();
71         addVertexArrayObject(0);
72         setVertexArrayObject(0);
73         setAttribute0value(0.0, 0.0, 0.0, 1.0);
74 
75         buildStrings(false /* not gles1 */,
76                      (const char*)dispatcher().glGetString(GL_VENDOR),
77                      (const char*)dispatcher().glGetString(GL_RENDERER),
78                      (const char*)dispatcher().glGetString(GL_VERSION),
79                      sPickVersionStringPart(m_glesMajorVersion, m_glesMinorVersion));
80         if (m_glesMajorVersion > 2 && !isGles2Gles()) {
81             // OpenGL ES assumes that colors computed by / given to shaders will be converted to / from SRGB automatically
82             // by the underlying implementation.
83             // Desktop OpenGL makes no such assumption, and requires glEnable(GL_FRAMEBUFFER_SRGB) for the automatic conversion
84             // to work.
85             // This should work in most cases: just glEnable(GL_FRAMEBUFFER_SRGB) for every context.
86             // But, that's not the whole story:
87             // TODO: For dEQP tests standalone, we can just glEnable GL_FRAMEBUFFER_SRGB from the beginning and
88             // pass all the framebuffer blit tests. However with CTS dEQP, EGL gets failures in color clear
89             // and some dEQP-GLES3 framebuffer blit tests fail.
90             // So we need to start out each context with GL_FRAMEBUFFER_SRGB disabled, and then enable it depending on
91             // whether or not the current draw or read framebuffer has a SRGB texture color attachment.
92             dispatcher().glDisable(GL_FRAMEBUFFER_SRGB);
93             // Desktop OpenGL allows one to make cube maps seamless _or not_, but
94             // OpenGL ES assumes seamless cubemaps are activated 100% of the time.
95             // Many dEQP cube map tests fail without this enable.
96             dispatcher().glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
97         }
98 
99         initEmulatedVAO();
100         initEmulatedBuffers();
101         // init emulated transform feedback
102         if (m_glesMajorVersion >= 3) {
103             m_transformFeedbackNameSpace->genName(
104                     GenNameInfo(NamedObjectType::TRANSFORM_FEEDBACK), 0, false);
105             TransformFeedbackData* tf = new TransformFeedbackData();
106             tf->setMaxSize(getCaps()->maxTransformFeedbackSeparateAttribs);
107             m_transformFeedbackNameSpace->setObjectData(0, ObjectDataPtr(tf));
108         }
109     }
110     m_initialized = true;
111 }
112 
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)113 void GLESv2Context::initDefaultFBO(
114         GLint width, GLint height, GLint colorFormat, GLint depthstencilFormat, GLint multisamples,
115         GLuint* eglSurfaceRBColorId, GLuint* eglSurfaceRBDepthId,
116         GLuint readWidth, GLint readHeight, GLint readColorFormat, GLint readDepthstencilFormat, GLint readMultisamples,
117         GLuint* eglReadSurfaceRBColorId, GLuint* eglReadSurfaceRBDepthId) {
118     GLEScontext::initDefaultFBO(
119             width, height, colorFormat, depthstencilFormat, multisamples,
120             eglSurfaceRBColorId, eglSurfaceRBDepthId,
121             readWidth, readHeight, readColorFormat, readDepthstencilFormat, readMultisamples,
122             eglReadSurfaceRBColorId, eglReadSurfaceRBDepthId
123             );
124 }
125 
126 
initEmulatedVAO()127 void GLESv2Context::initEmulatedVAO() {
128     if (!isCoreProfile()) return;
129 
130     // Create emulated default VAO
131     genVAOName(0, false);
132     dispatcher().glBindVertexArray(getVAOGlobalName(0));
133 }
134 
initEmulatedBuffers()135 void GLESv2Context::initEmulatedBuffers() {
136     if (m_emulatedClientVBOs.empty()) {
137         // Create emulated client VBOs
138         GLint neededClientVBOs = 0;
139         dispatcher().glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &neededClientVBOs);
140 
141         // Spec minimum: 16 attribs. Some drivers won't report the right values.
142         neededClientVBOs = std::max(neededClientVBOs, 16);
143 
144         m_emulatedClientVBOs.resize(neededClientVBOs, 0);
145         dispatcher().glGenBuffers(neededClientVBOs, &m_emulatedClientVBOs[0]);
146     }
147 
148     if (!m_emulatedClientIBO) {
149         // Create emulated IBO
150         dispatcher().glGenBuffers(1, &m_emulatedClientIBO);
151     }
152 }
153 
GLESv2Context(int maj,int min,GlobalNameSpace * globalNameSpace,android::base::Stream * stream,GlLibrary * glLib)154 GLESv2Context::GLESv2Context(int maj, int min, GlobalNameSpace* globalNameSpace,
155         android::base::Stream* stream, GlLibrary* glLib)
156         : GLEScontext(globalNameSpace, stream, glLib) {
157     if (stream) {
158         assert(maj == m_glesMajorVersion);
159         assert(min == m_glesMinorVersion);
160         stream->read(m_attribute0value, sizeof(m_attribute0value));
161         m_attribute0valueChanged = stream->getByte();
162         m_att0ArrayLength = stream->getBe32();
163         if (m_att0ArrayLength != 0) {
164             m_att0Array.reset(new GLfloat[4 * m_att0ArrayLength]);
165             stream->read(m_att0Array.get(), sizeof(GLfloat) * 4 * m_att0ArrayLength);
166         }
167         m_att0NeedsDisable = stream->getByte();
168         m_useProgram = stream->getBe32();
169         android::base::loadCollection(stream, &m_bindSampler,
170                 [](android::base::Stream* stream) {
171                     GLuint idx = stream->getBe32();
172                     GLuint val = stream->getBe32();
173                     return std::make_pair(idx, val);
174                 });
175     } else {
176         m_glesMajorVersion = maj;
177         m_glesMinorVersion = min;
178     }
179     ObjectData::loadObject_t loader = [this](NamedObjectType type,
180                                              long long unsigned int localName,
181                                              android::base::Stream* stream) {
182         return loadObject(type, localName, stream);
183     };
184     m_transformFeedbackNameSpace =
185             new NameSpace(NamedObjectType::TRANSFORM_FEEDBACK, globalNameSpace,
186                           stream, loader);
187 }
188 
~GLESv2Context()189 GLESv2Context::~GLESv2Context() {
190     if (m_emulatedClientIBO) {
191         s_glDispatch.glDeleteBuffers(1, &m_emulatedClientIBO);
192     }
193 
194     if (!m_emulatedClientVBOs.empty()) {
195         s_glDispatch.glDeleteBuffers(
196             m_emulatedClientVBOs.size(),
197             &m_emulatedClientVBOs[0]);
198     }
199 
200     deleteVAO(0);
201     delete m_transformFeedbackNameSpace;
202 }
203 
onSave(android::base::Stream * stream) const204 void GLESv2Context::onSave(android::base::Stream* stream) const {
205     GLEScontext::onSave(stream);
206     stream->write(m_attribute0value, sizeof(m_attribute0value));
207     stream->putByte(m_attribute0valueChanged);
208     stream->putBe32(m_att0ArrayLength);
209     stream->write(m_att0Array.get(), sizeof(GLfloat) * 4 * m_att0ArrayLength);
210     stream->putByte(m_att0NeedsDisable);
211     stream->putBe32(m_useProgram);
212     android::base::saveCollection(stream, m_bindSampler,
213             [](android::base::Stream* stream,
214                 const std::pair<const GLenum, GLuint>& item) {
215                 stream->putBe32(item.first);
216                 stream->putBe32(item.second);
217             });
218     m_transformFeedbackNameSpace->onSave(stream);
219 }
220 
addVertexArrayObject(GLuint array)221 void GLESv2Context::addVertexArrayObject(GLuint array) {
222     m_vaoStateMap[array] = VAOState(0, nullptr, kMaxVertexAttributes);
223 }
224 
enableArr(GLenum arrType,bool enable)225 void GLESv2Context::enableArr(GLenum arrType, bool enable) {
226     uint32_t index = (uint32_t)arrType;
227     if (index > kMaxVertexAttributes) return;
228     m_currVaoState.attribInfo()[index].enable(enable);
229 }
230 
getPointer(GLenum arrType)231 const GLESpointer* GLESv2Context::getPointer(GLenum arrType) {
232     uint32_t index = (uint32_t)arrType;
233     if (index > kMaxVertexAttributes) return nullptr;
234     return m_currVaoState.attribInfo().data() + index;
235 }
236 
postLoadRestoreCtx()237 void GLESv2Context::postLoadRestoreCtx() {
238     GLDispatch& dispatcher = GLEScontext::dispatcher();
239     m_useProgramData = shareGroup()->getObjectDataPtr(
240             NamedObjectType::SHADER_OR_PROGRAM, m_useProgram);
241     const GLuint globalProgramName = shareGroup()->getGlobalName(
242             NamedObjectType::SHADER_OR_PROGRAM, m_useProgram);
243     dispatcher.glUseProgram(globalProgramName);
244 
245     initEmulatedBuffers();
246     initEmulatedVAO();
247 
248     // vertex attribute pointers
249     for (const auto& vaoIte : m_vaoStateMap) {
250         if (vaoIte.first != 0) {
251             genVAOName(vaoIte.first, false);
252         }
253         dispatcher.glBindVertexArray(getVAOGlobalName(vaoIte.first));
254         for (uint32_t i = 0; i < kMaxVertexAttributes; ++i) {
255             GLESpointer* glesPointer =
256                 (GLESpointer*)(vaoIte.second.vertexAttribInfo.data() + i);
257 
258             // don't skip enabling if the guest assumes it was enabled.
259             if (glesPointer->isEnable()) {
260                 dispatcher.glEnableVertexAttribArray(i);
261             }
262 
263             // attribute 0 are bound right before draw, no need to bind it here
264             if (glesPointer->getAttribType() == GLESpointer::VALUE
265                     && i == 0) {
266                 continue;
267             }
268             switch (glesPointer->getAttribType()) {
269                 case GLESpointer::BUFFER: {
270                     const GLuint globalBufferName = shareGroup()
271                             ->getGlobalName(NamedObjectType::VERTEXBUFFER,
272                                             glesPointer->getBufferName());
273                     if (!globalBufferName) {
274                         continue;
275                     }
276                     glesPointer->restoreBufferObj(getBufferObj);
277                     dispatcher.glBindBuffer(GL_ARRAY_BUFFER,
278                             globalBufferName);
279                     if (glesPointer->isIntPointer()) {
280                         dispatcher.glVertexAttribIPointer(i,
281                                 glesPointer->getSize(),
282                                 glesPointer->getType(),
283                                 glesPointer->getStride(),
284                                 (GLvoid*)(size_t)glesPointer->getBufferOffset());
285                     } else {
286                         dispatcher.glVertexAttribPointer(i,
287                                 glesPointer->getSize(),
288                                 glesPointer->getType(), glesPointer->isNormalize(),
289                                 glesPointer->getStride(),
290                                 (GLvoid*)(size_t)glesPointer->getBufferOffset());
291                     }
292                     break;
293                 }
294                 case GLESpointer::VALUE:
295                     switch (glesPointer->getValueCount()) {
296                         case 1:
297                             dispatcher.glVertexAttrib1fv(i,
298                                     glesPointer->getValues());
299                             break;
300                         case 2:
301                             dispatcher.glVertexAttrib2fv(i,
302                                     glesPointer->getValues());
303                             break;
304                         case 3:
305                             dispatcher.glVertexAttrib3fv(i,
306                                     glesPointer->getValues());
307                             break;
308                         case 4:
309                             dispatcher.glVertexAttrib4fv(i,
310                                     glesPointer->getValues());
311                             break;
312                     }
313                     break;
314                 case GLESpointer::ARRAY:
315                     // client arrays are set up right before draw calls
316                     // so we do nothing here
317                     break;
318             }
319         }
320         for (size_t i = 0; i < vaoIte.second.bindingState.size(); i++) {
321             const BufferBinding& bufferBinding = vaoIte.second.bindingState[i];
322             if (bufferBinding.divisor) {
323                 dispatcher.glVertexAttribDivisor(i, bufferBinding.divisor);
324             }
325         }
326     }
327     dispatcher.glBindVertexArray(getVAOGlobalName(m_currVaoState.vaoId()));
328     if (m_glesMajorVersion >= 3) {
329         auto bindBufferRangeFunc =
330                 [this](GLenum target,
331                     const std::vector<BufferBinding>& bufferBindings) {
332                     for (unsigned int i = 0; i < bufferBindings.size(); i++) {
333                         const BufferBinding& bd = bufferBindings[i];
334                         GLuint globalName = this->shareGroup()->getGlobalName(
335                                 NamedObjectType::VERTEXBUFFER,
336                                 bd.buffer);
337                         assert(bd.buffer == 0 || globalName != 0);
338                         if (bd.isBindBase || bd.buffer == 0) {
339                             this->dispatcher().glBindBufferBase(target,
340                                     i, globalName);
341                         } else {
342                             this->dispatcher().glBindBufferRange(target,
343                                     i, globalName, bd.offset, bd.size);
344                         }
345                     }
346                 };
347         bindBufferRangeFunc(GL_TRANSFORM_FEEDBACK_BUFFER,
348                 m_indexedTransformFeedbackBuffers);
349         bindBufferRangeFunc(GL_UNIFORM_BUFFER,
350                 m_indexedUniformBuffers);
351 
352         if (m_glesMinorVersion >= 1) {
353             bindBufferRangeFunc(GL_ATOMIC_COUNTER_BUFFER,
354                     m_indexedAtomicCounterBuffers);
355             bindBufferRangeFunc(GL_SHADER_STORAGE_BUFFER,
356                     m_indexedShaderStorageBuffers);
357         }
358 
359         // buffer bindings
360         auto bindBuffer = [this](GLenum target, GLuint buffer) {
361             this->dispatcher().glBindBuffer(target,
362                     m_shareGroup->getGlobalName(NamedObjectType::VERTEXBUFFER, buffer));
363         };
364         bindBuffer(GL_COPY_READ_BUFFER, m_copyReadBuffer);
365         bindBuffer(GL_COPY_WRITE_BUFFER, m_copyWriteBuffer);
366         bindBuffer(GL_PIXEL_PACK_BUFFER, m_pixelPackBuffer);
367         bindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pixelUnpackBuffer);
368         bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transformFeedbackBuffer);
369         bindBuffer(GL_UNIFORM_BUFFER, m_uniformBuffer);
370 
371         if (m_glesMinorVersion >= 1) {
372             bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterBuffer);
373             bindBuffer(GL_DISPATCH_INDIRECT_BUFFER, m_dispatchIndirectBuffer);
374             bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_drawIndirectBuffer);
375             bindBuffer(GL_SHADER_STORAGE_BUFFER, m_shaderStorageBuffer);
376         }
377 
378         for (const auto& bindSampler : m_bindSampler) {
379             dispatcher.glBindSampler(bindSampler.first,
380                     shareGroup()->getGlobalName(NamedObjectType::SAMPLER,
381                         bindSampler.second));
382         }
383         m_transformFeedbackNameSpace->postLoadRestore(
384                 [this](NamedObjectType p_type, ObjectLocalName p_localName) {
385                     switch (p_type) {
386                         case NamedObjectType::FRAMEBUFFER:
387                             return getFBOGlobalName(p_localName);
388                         case NamedObjectType::TRANSFORM_FEEDBACK:
389                             return getTransformFeedbackGlobalName(p_localName);
390                         default:
391                             return m_shareGroup->getGlobalName(p_type,
392                                                                p_localName);
393                     }
394                 });
395         dispatcher.glBindTransformFeedback(
396                 GL_TRANSFORM_FEEDBACK,
397                 getTransformFeedbackGlobalName(m_transformFeedbackBuffer));
398     }
399 
400     GLEScontext::postLoadRestoreCtx();
401 }
402 
loadObject(NamedObjectType type,ObjectLocalName localName,android::base::Stream * stream) const403 ObjectDataPtr GLESv2Context::loadObject(NamedObjectType type,
404             ObjectLocalName localName, android::base::Stream* stream) const {
405     switch (type) {
406         case NamedObjectType::VERTEXBUFFER:
407         case NamedObjectType::TEXTURE:
408         case NamedObjectType::FRAMEBUFFER:
409         case NamedObjectType::RENDERBUFFER:
410             return GLEScontext::loadObject(type, localName, stream);
411         case NamedObjectType::SAMPLER:
412             return ObjectDataPtr(new SamplerData(stream));
413         case NamedObjectType::SHADER_OR_PROGRAM:
414             // load the first bit to see if it is a program or shader
415             switch (stream->getByte()) {
416                 case LOAD_PROGRAM:
417                     return ObjectDataPtr(new ProgramData(stream));
418                 case LOAD_SHADER:
419                     return ObjectDataPtr(new ShaderParser(stream));
420                 default:
421                     fprintf(stderr, "corrupted snapshot\n");
422                     assert(false);
423                     return nullptr;
424             }
425         case NamedObjectType::TRANSFORM_FEEDBACK:
426             return ObjectDataPtr(new TransformFeedbackData(stream));
427         default:
428             return nullptr;
429     }
430 }
431 
setAttribValue(int idx,unsigned int count,const GLfloat * val)432 void GLESv2Context::setAttribValue(int idx, unsigned int count,
433         const GLfloat* val) {
434     m_currVaoState.attribInfo()[idx].setValue(count, val);
435 }
436 
setAttribute0value(float x,float y,float z,float w)437 void GLESv2Context::setAttribute0value(float x, float y, float z, float w)
438 {
439     m_attribute0valueChanged |=
440             x != m_attribute0value[0] || y != m_attribute0value[1] ||
441             z != m_attribute0value[2] || w != m_attribute0value[3];
442     m_attribute0value[0] = x;
443     m_attribute0value[1] = y;
444     m_attribute0value[2] = z;
445     m_attribute0value[3] = w;
446 }
447 
needAtt0PreDrawValidation()448 bool GLESv2Context::needAtt0PreDrawValidation()
449 {
450     m_att0NeedsDisable = false;
451 
452     // We could go into the driver here and call
453     //      s_glDispatch.glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled)
454     // ... but it's too much for a simple check that runs on almost every draw
455     // call.
456     return !isArrEnabled(0);
457 }
458 
validateAtt0PreDraw(unsigned int count)459 void GLESv2Context::validateAtt0PreDraw(unsigned int count)
460 {
461     if (count == 0) {
462         return;
463     }
464 
465     if (count > m_att0ArrayLength) {
466         const unsigned newLen = std::max(count, 2 * m_att0ArrayLength);
467         m_att0Array.reset(new GLfloat[4 * newLen]);
468         m_att0ArrayLength = newLen;
469         m_attribute0valueChanged = true;
470     }
471     if (m_attribute0valueChanged) {
472         for(unsigned int i = 0; i<m_att0ArrayLength; i++) {
473             memcpy(m_att0Array.get()+i*4, m_attribute0value,
474                     sizeof(m_attribute0value));
475         }
476         m_attribute0valueChanged = false;
477     }
478 
479     GLuint prevArrayBuffer;
480     s_glDispatch.glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&prevArrayBuffer);
481 
482     s_glDispatch.glBindBuffer(GL_ARRAY_BUFFER, m_emulatedClientVBOs[0]);
483     s_glDispatch.glBufferData(GL_ARRAY_BUFFER, m_att0ArrayLength * sizeof(GLfloat), m_att0Array.get(), GL_STREAM_DRAW);
484 
485     s_glDispatch.glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
486     s_glDispatch.glEnableVertexAttribArray(0);
487 
488     s_glDispatch.glBindBuffer(GL_ARRAY_BUFFER, prevArrayBuffer);
489 
490     m_att0NeedsDisable = true;
491 }
492 
validateAtt0PostDraw(void)493 void GLESv2Context::validateAtt0PostDraw(void)
494 {
495     if (m_att0NeedsDisable) {
496         s_glDispatch.glDisableVertexAttribArray(0);
497         m_att0NeedsDisable = false;
498     }
499 }
500 
drawWithEmulations(DrawCallCmd cmd,GLenum mode,GLint first,GLsizei count,GLenum type,const GLvoid * indices,GLsizei primcount,GLuint start,GLuint end)501 void GLESv2Context::drawWithEmulations(
502     DrawCallCmd cmd,
503     GLenum mode,
504     GLint first,
505     GLsizei count,
506     GLenum type,
507     const GLvoid* indices,
508     GLsizei primcount,
509     GLuint start,
510     GLuint end) {
511 
512     if (getMajorVersion() < 3) {
513         drawValidate();
514     }
515 
516     bool needClientVBOSetup = !vertexAttributesBufferBacked();
517 
518     bool needClientIBOSetup =
519         (cmd != DrawCallCmd::Arrays &&
520          cmd != DrawCallCmd::ArraysInstanced) &&
521         !isBindedBuffer(GL_ELEMENT_ARRAY_BUFFER);
522     bool needPointEmulation = mode == GL_POINTS && !isGles2Gles();
523 
524 #ifdef __APPLE__
525     if (primitiveRestartEnabled() && type) {
526         updatePrimitiveRestartIndex(type);
527     }
528 #endif
529 
530     if (needPointEmulation) {
531         s_glDispatch.glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
532         if (!isCoreProfile()) {
533             // Enable texture generation for GL_POINTS and gl_PointSize shader variable
534             // GLES2 assumes this is enabled by default, we need to set this state for GL
535             s_glDispatch.glEnable(GL_POINT_SPRITE);
536         }
537     }
538 
539     bool needEnablingPostDraw[kMaxVertexAttributes];
540     memset(needEnablingPostDraw, 0, sizeof(needEnablingPostDraw));
541 
542     if (needClientVBOSetup) {
543         GLESConversionArrays tmpArrs;
544         setupArraysPointers(tmpArrs, 0, count, type, indices, false, needEnablingPostDraw);
545         if (needAtt0PreDrawValidation()) {
546             if (indices) {
547                 validateAtt0PreDraw(findMaxIndex(count, type, indices));
548             } else {
549                 validateAtt0PreDraw(count);
550             }
551         }
552     }
553 
554     GLuint prevIBO;
555     if (needClientIBOSetup) {
556         int bpv = 2;
557         switch (type) {
558             case GL_UNSIGNED_BYTE:
559                 bpv = 1;
560                 break;
561             case GL_UNSIGNED_SHORT:
562                 bpv = 2;
563                 break;
564             case GL_UNSIGNED_INT:
565                 bpv = 4;
566                 break;
567         }
568 
569         size_t dataSize = bpv * count;
570 
571         s_glDispatch.glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint*)&prevIBO);
572         s_glDispatch.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_emulatedClientIBO);
573         s_glDispatch.glBufferData(GL_ELEMENT_ARRAY_BUFFER, dataSize, indices, GL_STREAM_DRAW);
574     }
575 
576     const GLvoid* indicesOrOffset =
577         needClientIBOSetup ? nullptr : indices;
578 
579     switch (cmd) {
580         case DrawCallCmd::Elements:
581             s_glDispatch.glDrawElements(mode, count, type, indicesOrOffset);
582             break;
583         case DrawCallCmd::ElementsInstanced:
584             s_glDispatch.glDrawElementsInstanced(mode, count, type,
585                                                  indicesOrOffset,
586                                                  primcount);
587             break;
588         case DrawCallCmd::RangeElements:
589             s_glDispatch.glDrawRangeElements(mode, start, end, count, type,
590                                              indicesOrOffset);
591             break;
592         case DrawCallCmd::Arrays:
593             s_glDispatch.glDrawArrays(mode, first, count);
594             break;
595         case DrawCallCmd::ArraysInstanced:
596             s_glDispatch.glDrawArraysInstanced(mode, first, count, primcount);
597             break;
598         default:
599             emugl_crash_reporter(
600                 "drawWithEmulations has corrupt call parameters!");
601     }
602 
603     if (needClientIBOSetup) {
604         s_glDispatch.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prevIBO);
605     }
606 
607     if (needClientVBOSetup) {
608         validateAtt0PostDraw();
609     }
610 
611     if (needPointEmulation) {
612         s_glDispatch.glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
613         if (!isCoreProfile()) {
614             s_glDispatch.glDisable(GL_POINT_SPRITE);
615         }
616     }
617 
618     for (int i = 0; i < kMaxVertexAttributes; ++i) {
619         if (needEnablingPostDraw[i]) {
620             s_glDispatch.glEnableVertexAttribArray(i);
621         }
622     }
623 }
624 
setupArraysPointers(GLESConversionArrays & cArrs,GLint first,GLsizei count,GLenum type,const GLvoid * indices,bool direct,bool * needEnablingPostDraw)625 void GLESv2Context::setupArraysPointers(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct, bool* needEnablingPostDraw) {
626     //going over all clients arrays Pointers
627     for (uint32_t i = 0; i < kMaxVertexAttributes; ++i) {
628         GLESpointer* p = m_currVaoState.attribInfo().data() + i;
629         if (!p->isEnable() || p->getAttribType() == GLESpointer::VALUE) {
630             continue;
631         }
632 
633         setupArrWithDataSize(
634             p->getDataSize(),
635             p->getArrayData(),
636             i,
637             p->getType(),
638             p->getSize(),
639             p->getStride(),
640             p->getNormalized(),
641             -1,
642             p->isIntPointer(),
643             p->getBufferName(),
644             needEnablingPostDraw);
645     }
646 }
647 
648 //setting client side arr
setupArrWithDataSize(GLsizei datasize,const GLvoid * arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized,int index,bool isInt,GLuint ptrBufferName,bool * needEnablingPostDraw)649 void GLESv2Context::setupArrWithDataSize(GLsizei datasize, const GLvoid* arr,
650                                          GLenum arrayType, GLenum dataType,
651                                          GLint size, GLsizei stride, GLboolean normalized, int index, bool isInt, GLuint ptrBufferName, bool* needEnablingPostDraw){
652     // is not really a client side arr.
653     if (arr == NULL) {
654         GLint isEnabled;
655         s_glDispatch.glGetVertexAttribiv((int)arrayType, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &isEnabled);
656         if (isEnabled && !ptrBufferName) {
657             s_glDispatch.glDisableVertexAttribArray(arrayType);
658             if (needEnablingPostDraw)
659                 needEnablingPostDraw[arrayType] = true;
660         }
661 
662         return;
663     }
664 
665     GLuint prevArrayBuffer;
666     s_glDispatch.glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&prevArrayBuffer);
667 
668     if (arrayType < m_emulatedClientVBOs.size()) {
669         s_glDispatch.glBindBuffer(GL_ARRAY_BUFFER, m_emulatedClientVBOs[arrayType]);
670     } else {
671         fprintf(stderr, "%s: invalid attribute index: %d\n", __func__, (int)arrayType);
672     }
673 
674     s_glDispatch.glBufferData(GL_ARRAY_BUFFER, datasize, arr, GL_STREAM_DRAW);
675 
676     if (isInt) {
677         s_glDispatch.glVertexAttribIPointer(arrayType, size, dataType, stride, 0);
678     } else {
679         s_glDispatch.glVertexAttribPointer(arrayType, size, dataType, normalized, stride, 0);
680     }
681 
682     s_glDispatch.glBindBuffer(GL_ARRAY_BUFFER, prevArrayBuffer);
683 }
684 
setVertexAttribDivisor(GLuint bindingindex,GLuint divisor)685 void GLESv2Context::setVertexAttribDivisor(GLuint bindingindex, GLuint divisor) {
686     if (bindingindex >= m_currVaoState.bufferBindings().size()) {
687         return;
688     }
689     m_currVaoState.bufferBindings()[bindingindex].divisor = divisor;
690 }
691 
setVertexAttribBindingIndex(GLuint attribindex,GLuint bindingindex)692 void GLESv2Context::setVertexAttribBindingIndex(GLuint attribindex, GLuint bindingindex) {
693     if (attribindex > kMaxVertexAttributes) return;
694 
695     m_currVaoState.attribInfo()[attribindex].setBindingIndex(bindingindex);
696 }
697 
setVertexAttribFormat(GLuint attribindex,GLint size,GLenum type,GLboolean normalized,GLuint reloffset,bool isInt)698 void GLESv2Context::setVertexAttribFormat(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt) {
699     if (attribindex > kMaxVertexAttributes) return;
700     m_currVaoState.attribInfo()[attribindex].setFormat(size, type, normalized == GL_TRUE, reloffset, isInt);
701 }
702 
setBindSampler(GLuint unit,GLuint sampler)703 void GLESv2Context::setBindSampler(GLuint unit, GLuint sampler) {
704     m_bindSampler[unit] = sampler;
705 }
706 
needConvert(GLESConversionArrays & cArrs,GLint first,GLsizei count,GLenum type,const GLvoid * indices,bool direct,GLESpointer * p,GLenum array_id)707 bool GLESv2Context::needConvert(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id) {
708 
709     bool usingVBO = p->getAttribType() == GLESpointer::BUFFER;
710     GLenum arrType = p->getType();
711 
712     /*
713      conversion is not necessary in the following cases:
714       (*) array type is not fixed
715     */
716     if(arrType != GL_FIXED) return false;
717 
718     if(!usingVBO) {
719         if (direct) {
720             convertDirect(cArrs,first,count,array_id,p);
721         } else {
722             convertIndirect(cArrs,count,type,indices,array_id,p);
723         }
724     } else {
725         if (direct) {
726             convertDirectVBO(cArrs,first,count,array_id,p);
727         } else {
728             convertIndirectVBO(cArrs,count,type,indices,array_id,p);
729         }
730     }
731     return true;
732 }
733 
setUseProgram(GLuint program,const ObjectDataPtr & programData)734 void GLESv2Context::setUseProgram(GLuint program,
735         const ObjectDataPtr& programData) {
736     m_useProgram = program;
737     assert(!programData ||
738             programData->getDataType() == ObjectDataType::PROGRAM_DATA);
739     m_useProgramData = programData;
740 }
741 
getCurrentProgram() const742 GLuint GLESv2Context::getCurrentProgram() const {
743     return m_useProgram;
744 }
745 
getUseProgram()746 ProgramData* GLESv2Context::getUseProgram() {
747     return (ProgramData*)m_useProgramData.get();
748 }
749 
initExtensionString()750 void GLESv2Context::initExtensionString() {
751     if (s_glExtensionsInitialized) return;
752 
753     *s_glExtensions = "GL_OES_EGL_sync GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_depth24 GL_OES_depth32 GL_OES_element_index_uint "
754                       "GL_OES_texture_float GL_OES_texture_float_linear "
755                       "GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture GL_OES_depth_texture ";
756     if (s_glSupport.GL_ARB_HALF_FLOAT_PIXEL || s_glSupport.GL_NV_HALF_FLOAT)
757         *s_glExtensions+="GL_OES_texture_half_float GL_OES_texture_half_float_linear ";
758     if (s_glSupport.GL_EXT_PACKED_DEPTH_STENCIL)
759         *s_glExtensions+="GL_OES_packed_depth_stencil ";
760     if (s_glSupport.GL_ARB_HALF_FLOAT_VERTEX)
761         *s_glExtensions+="GL_OES_vertex_half_float ";
762     if (s_glSupport.GL_OES_STANDARD_DERIVATIVES)
763         *s_glExtensions+="GL_OES_standard_derivatives ";
764     if (s_glSupport.GL_OES_TEXTURE_NPOT)
765         *s_glExtensions+="GL_OES_texture_npot ";
766     if (s_glSupport.GL_OES_RGB8_RGBA8)
767         *s_glExtensions+="GL_OES_rgb8_rgba8 ";
768     if (s_glSupport.ext_GL_EXT_color_buffer_float)
769         *s_glExtensions+="GL_EXT_color_buffer_float ";
770     if (s_glSupport.ext_GL_EXT_color_buffer_half_float)
771         *s_glExtensions+="GL_EXT_color_buffer_half_float ";
772     if (s_glSupport.ext_GL_EXT_shader_framebuffer_fetch)
773         *s_glExtensions+="GL_EXT_shader_framebuffer_fetch ";
774     if (s_glSupport.GL_EXT_TEXTURE_FORMAT_BGRA8888) {
775         *s_glExtensions+="GL_EXT_texture_format_BGRA8888 GL_APPLE_texture_format_BGRA8888 ";
776     }
777 
778     s_glExtensionsInitialized = true;
779 }
780 
getMaxTexUnits()781 int GLESv2Context::getMaxTexUnits() {
782     return getCaps()->maxTexImageUnits;
783 }
784 
getMaxCombinedTexUnits()785 int GLESv2Context::getMaxCombinedTexUnits() {
786     return getCaps()->maxCombinedTexImageUnits;
787 }
788 
getTransformFeedbackGlobalName(ObjectLocalName p_localName)789 unsigned int GLESv2Context::getTransformFeedbackGlobalName(
790         ObjectLocalName p_localName) {
791     return m_transformFeedbackNameSpace->getGlobalName(p_localName);
792 }
793 
hasBoundTransformFeedback(ObjectLocalName transformFeedback)794 bool GLESv2Context::hasBoundTransformFeedback(
795         ObjectLocalName transformFeedback) {
796     return transformFeedback &&
797            m_transformFeedbackNameSpace->getObjectDataPtr(transformFeedback)
798                    .get();
799 }
800 
genTransformFeedbackName(ObjectLocalName p_localName,bool genLocal)801 ObjectLocalName GLESv2Context::genTransformFeedbackName(
802         ObjectLocalName p_localName,
803         bool genLocal) {
804     return m_transformFeedbackNameSpace->genName(
805             GenNameInfo(NamedObjectType::TRANSFORM_FEEDBACK), p_localName,
806             genLocal);
807 }
808 
bindTransformFeedback(ObjectLocalName p_localName)809 void GLESv2Context::bindTransformFeedback(ObjectLocalName p_localName) {
810     if (m_transformFeedbackDeletePending &&
811         m_bindTransformFeedback != p_localName) {
812         m_transformFeedbackNameSpace->deleteName(m_bindTransformFeedback);
813         m_transformFeedbackDeletePending = false;
814     }
815     m_bindTransformFeedback = p_localName;
816     if (p_localName &&
817         !m_transformFeedbackNameSpace->getGlobalName(p_localName)) {
818         genTransformFeedbackName(p_localName, false);
819     }
820     if (p_localName &&
821         !m_transformFeedbackNameSpace->getObjectDataPtr(p_localName).get()) {
822         TransformFeedbackData* tf = new TransformFeedbackData();
823         tf->setMaxSize(getCaps()->maxTransformFeedbackSeparateAttribs);
824         m_transformFeedbackNameSpace->setObjectData(p_localName,
825                                                     ObjectDataPtr(tf));
826     }
827 }
828 
getTransformFeedbackBinding()829 ObjectLocalName GLESv2Context::getTransformFeedbackBinding() {
830     return m_bindTransformFeedback;
831 }
832 
deleteTransformFeedback(ObjectLocalName p_localName)833 void GLESv2Context::deleteTransformFeedback(ObjectLocalName p_localName) {
834     // Note: GLES3.0 says it should be pending for delete if it is active
835     // GLES3.2 says report error in this situation
836     if (m_bindTransformFeedback == p_localName) {
837         m_transformFeedbackDeletePending = true;
838         return;
839     }
840     m_transformFeedbackNameSpace->deleteName(p_localName);
841 }
842 
boundTransformFeedback()843 TransformFeedbackData* GLESv2Context::boundTransformFeedback() {
844     return (TransformFeedbackData*)m_transformFeedbackNameSpace
845             ->getObjectDataPtr(m_bindTransformFeedback)
846             .get();
847 }
848 
getIndexedBuffer(GLenum target,GLuint index)849 GLuint GLESv2Context::getIndexedBuffer(GLenum target, GLuint index) {
850     switch (target) {
851         case GL_TRANSFORM_FEEDBACK_BUFFER:
852             return boundTransformFeedback()->getIndexedBuffer(index);
853         default:
854             return GLEScontext::getIndexedBuffer(target, index);
855     }
856 }
857 
bindIndexedBuffer(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size,GLintptr stride,bool isBindBase)858 void GLESv2Context::bindIndexedBuffer(GLenum target,
859                                       GLuint index,
860                                       GLuint buffer,
861                                       GLintptr offset,
862                                       GLsizeiptr size,
863                                       GLintptr stride,
864                                       bool isBindBase) {
865     switch (target) {
866         case GL_TRANSFORM_FEEDBACK_BUFFER: {
867             TransformFeedbackData* tf = boundTransformFeedback();
868             tf->bindIndexedBuffer(index, buffer, offset, size, stride,
869                                   isBindBase);
870             break;
871         }
872         default:
873             GLEScontext::bindIndexedBuffer(target, index, buffer, offset, size,
874                                            stride, isBindBase);
875     }
876 }
877 
bindIndexedBuffer(GLenum target,GLuint index,GLuint buffer)878 void GLESv2Context::bindIndexedBuffer(GLenum target,
879                                       GLuint index,
880                                       GLuint buffer) {
881     GLEScontext::bindIndexedBuffer(target, index, buffer);
882 }
883 
unbindBuffer(GLuint buffer)884 void GLESv2Context::unbindBuffer(GLuint buffer) {
885     if (m_glesMajorVersion >= 3) {
886         boundTransformFeedback()->unbindBuffer(buffer);
887     }
888     GLEScontext::unbindBuffer(buffer);
889 }
890