• 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     s_glDispatch.glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0,
480             m_att0Array.get());
481     s_glDispatch.glEnableVertexAttribArray(0);
482 
483     m_att0NeedsDisable = true;
484 }
485 
validateAtt0PostDraw(void)486 void GLESv2Context::validateAtt0PostDraw(void)
487 {
488     if (m_att0NeedsDisable) {
489         s_glDispatch.glDisableVertexAttribArray(0);
490         m_att0NeedsDisable = false;
491     }
492 }
493 
drawWithEmulations(DrawCallCmd cmd,GLenum mode,GLint first,GLsizei count,GLenum type,const GLvoid * indices,GLsizei primcount,GLuint start,GLuint end)494 void GLESv2Context::drawWithEmulations(
495     DrawCallCmd cmd,
496     GLenum mode,
497     GLint first,
498     GLsizei count,
499     GLenum type,
500     const GLvoid* indices,
501     GLsizei primcount,
502     GLuint start,
503     GLuint end) {
504 
505     if (getMajorVersion() < 3) {
506         drawValidate();
507     }
508 
509     bool needClientVBOSetup = !vertexAttributesBufferBacked();
510 
511     bool needClientIBOSetup =
512         (cmd != DrawCallCmd::Arrays &&
513          cmd != DrawCallCmd::ArraysInstanced) &&
514         !isBindedBuffer(GL_ELEMENT_ARRAY_BUFFER);
515     bool needPointEmulation = mode == GL_POINTS && !isGles2Gles();
516 
517 #ifdef __APPLE__
518     if (primitiveRestartEnabled() && type) {
519         updatePrimitiveRestartIndex(type);
520     }
521 #endif
522 
523     if (needPointEmulation) {
524         s_glDispatch.glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
525         if (!isCoreProfile()) {
526             // Enable texture generation for GL_POINTS and gl_PointSize shader variable
527             // GLES2 assumes this is enabled by default, we need to set this state for GL
528             s_glDispatch.glEnable(GL_POINT_SPRITE);
529         }
530     }
531 
532     if (needClientVBOSetup) {
533         GLESConversionArrays tmpArrs;
534         setupArraysPointers(tmpArrs, 0, count, type, indices, false);
535         if (needAtt0PreDrawValidation()) {
536             if (indices) {
537                 validateAtt0PreDraw(findMaxIndex(count, type, indices));
538             } else {
539                 validateAtt0PreDraw(count);
540             }
541         }
542     }
543 
544     GLuint prevIBO;
545     if (needClientIBOSetup) {
546         int bpv = 2;
547         switch (type) {
548             case GL_UNSIGNED_BYTE:
549                 bpv = 1;
550                 break;
551             case GL_UNSIGNED_SHORT:
552                 bpv = 2;
553                 break;
554             case GL_UNSIGNED_INT:
555                 bpv = 4;
556                 break;
557         }
558 
559         size_t dataSize = bpv * count;
560 
561         s_glDispatch.glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint*)&prevIBO);
562         s_glDispatch.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_emulatedClientIBO);
563         s_glDispatch.glBufferData(GL_ELEMENT_ARRAY_BUFFER, dataSize, indices, GL_STREAM_DRAW);
564     }
565 
566     const GLvoid* indicesOrOffset =
567         needClientIBOSetup ? nullptr : indices;
568 
569     switch (cmd) {
570         case DrawCallCmd::Elements:
571             s_glDispatch.glDrawElements(mode, count, type, indicesOrOffset);
572             break;
573         case DrawCallCmd::ElementsInstanced:
574             s_glDispatch.glDrawElementsInstanced(mode, count, type,
575                                                  indicesOrOffset,
576                                                  primcount);
577             break;
578         case DrawCallCmd::RangeElements:
579             s_glDispatch.glDrawRangeElements(mode, start, end, count, type,
580                                              indicesOrOffset);
581             break;
582         case DrawCallCmd::Arrays:
583             s_glDispatch.glDrawArrays(mode, first, count);
584             break;
585         case DrawCallCmd::ArraysInstanced:
586             s_glDispatch.glDrawArraysInstanced(mode, first, count, primcount);
587             break;
588         default:
589             emugl_crash_reporter(
590                 "drawWithEmulations has corrupt call parameters!");
591     }
592 
593     if (needClientIBOSetup) {
594         s_glDispatch.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prevIBO);
595     }
596 
597     if (needClientVBOSetup) {
598         validateAtt0PostDraw();
599     }
600 
601     if (needPointEmulation) {
602         s_glDispatch.glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
603         if (!isCoreProfile()) {
604             s_glDispatch.glDisable(GL_POINT_SPRITE);
605         }
606     }
607 }
608 
setupArraysPointers(GLESConversionArrays & cArrs,GLint first,GLsizei count,GLenum type,const GLvoid * indices,bool direct)609 void GLESv2Context::setupArraysPointers(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct) {
610     //going over all clients arrays Pointers
611     for (uint32_t i = 0; i < kMaxVertexAttributes; ++i) {
612         GLESpointer* p = m_currVaoState.attribInfo().data() + i;
613         if (!p->isEnable() || p->getAttribType() == GLESpointer::VALUE) {
614             continue;
615         }
616 
617         setupArrWithDataSize(
618             p->getDataSize(),
619             p->getArrayData(),
620             i,
621             p->getType(),
622             p->getSize(),
623             p->getStride(),
624             p->getNormalized(),
625             -1,
626             p->isIntPointer());
627     }
628 }
629 
630 //setting client side arr
setupArrWithDataSize(GLsizei datasize,const GLvoid * arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized,int index,bool isInt)631 void GLESv2Context::setupArrWithDataSize(GLsizei datasize, const GLvoid* arr,
632                                          GLenum arrayType, GLenum dataType,
633                                          GLint size, GLsizei stride, GLboolean normalized, int index, bool isInt){
634     // is not really a client side arr.
635     if (arr == NULL) return;
636 
637     GLuint prevArrayBuffer;
638     s_glDispatch.glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&prevArrayBuffer);
639 
640     if (arrayType < m_emulatedClientVBOs.size()) {
641         s_glDispatch.glBindBuffer(GL_ARRAY_BUFFER, m_emulatedClientVBOs[arrayType]);
642     } else {
643         fprintf(stderr, "%s: invalid attribute index: %d\n", __func__, (int)arrayType);
644     }
645 
646     s_glDispatch.glBufferData(GL_ARRAY_BUFFER, datasize, arr, GL_STREAM_DRAW);
647 
648     if (isInt) {
649         s_glDispatch.glVertexAttribIPointer(arrayType, size, dataType, stride, 0);
650     } else {
651         s_glDispatch.glVertexAttribPointer(arrayType, size, dataType, normalized, stride, 0);
652     }
653 
654     s_glDispatch.glBindBuffer(GL_ARRAY_BUFFER, prevArrayBuffer);
655 }
656 
setVertexAttribDivisor(GLuint bindingindex,GLuint divisor)657 void GLESv2Context::setVertexAttribDivisor(GLuint bindingindex, GLuint divisor) {
658     if (bindingindex >= m_currVaoState.bufferBindings().size()) {
659         return;
660     }
661     m_currVaoState.bufferBindings()[bindingindex].divisor = divisor;
662 }
663 
setVertexAttribBindingIndex(GLuint attribindex,GLuint bindingindex)664 void GLESv2Context::setVertexAttribBindingIndex(GLuint attribindex, GLuint bindingindex) {
665     if (attribindex > kMaxVertexAttributes) return;
666 
667     m_currVaoState.attribInfo()[attribindex].setBindingIndex(bindingindex);
668 }
669 
setVertexAttribFormat(GLuint attribindex,GLint size,GLenum type,GLboolean normalized,GLuint reloffset,bool isInt)670 void GLESv2Context::setVertexAttribFormat(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt) {
671     if (attribindex > kMaxVertexAttributes) return;
672     m_currVaoState.attribInfo()[attribindex].setFormat(size, type, normalized == GL_TRUE, reloffset, isInt);
673 }
674 
setBindSampler(GLuint unit,GLuint sampler)675 void GLESv2Context::setBindSampler(GLuint unit, GLuint sampler) {
676     m_bindSampler[unit] = sampler;
677 }
678 
needConvert(GLESConversionArrays & cArrs,GLint first,GLsizei count,GLenum type,const GLvoid * indices,bool direct,GLESpointer * p,GLenum array_id)679 bool GLESv2Context::needConvert(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id) {
680 
681     bool usingVBO = p->getAttribType() == GLESpointer::BUFFER;
682     GLenum arrType = p->getType();
683 
684     /*
685      conversion is not necessary in the following cases:
686       (*) array type is not fixed
687     */
688     if(arrType != GL_FIXED) return false;
689 
690     if(!usingVBO) {
691         if (direct) {
692             convertDirect(cArrs,first,count,array_id,p);
693         } else {
694             convertIndirect(cArrs,count,type,indices,array_id,p);
695         }
696     } else {
697         if (direct) {
698             convertDirectVBO(cArrs,first,count,array_id,p);
699         } else {
700             convertIndirectVBO(cArrs,count,type,indices,array_id,p);
701         }
702     }
703     return true;
704 }
705 
setUseProgram(GLuint program,const ObjectDataPtr & programData)706 void GLESv2Context::setUseProgram(GLuint program,
707         const ObjectDataPtr& programData) {
708     m_useProgram = program;
709     assert(!programData ||
710             programData->getDataType() == ObjectDataType::PROGRAM_DATA);
711     m_useProgramData = programData;
712 }
713 
getCurrentProgram() const714 GLuint GLESv2Context::getCurrentProgram() const {
715     return m_useProgram;
716 }
717 
getUseProgram()718 ProgramData* GLESv2Context::getUseProgram() {
719     return (ProgramData*)m_useProgramData.get();
720 }
721 
initExtensionString()722 void GLESv2Context::initExtensionString() {
723     if (s_glExtensionsInitialized) return;
724 
725     *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 "
726                       "GL_OES_texture_float GL_OES_texture_float_linear "
727                       "GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture GL_OES_depth_texture ";
728     if (s_glSupport.GL_ARB_HALF_FLOAT_PIXEL || s_glSupport.GL_NV_HALF_FLOAT)
729         *s_glExtensions+="GL_OES_texture_half_float GL_OES_texture_half_float_linear ";
730     if (s_glSupport.GL_EXT_PACKED_DEPTH_STENCIL)
731         *s_glExtensions+="GL_OES_packed_depth_stencil ";
732     if (s_glSupport.GL_ARB_HALF_FLOAT_VERTEX)
733         *s_glExtensions+="GL_OES_vertex_half_float ";
734     if (s_glSupport.GL_OES_STANDARD_DERIVATIVES)
735         *s_glExtensions+="GL_OES_standard_derivatives ";
736     if (s_glSupport.GL_OES_TEXTURE_NPOT)
737         *s_glExtensions+="GL_OES_texture_npot ";
738     if (s_glSupport.GL_OES_RGB8_RGBA8)
739         *s_glExtensions+="GL_OES_rgb8_rgba8 ";
740     if (s_glSupport.ext_GL_EXT_color_buffer_float)
741         *s_glExtensions+="GL_EXT_color_buffer_float ";
742     if (s_glSupport.ext_GL_EXT_color_buffer_half_float)
743         *s_glExtensions+="GL_EXT_color_buffer_half_float ";
744     if (s_glSupport.ext_GL_EXT_shader_framebuffer_fetch)
745         *s_glExtensions+="GL_EXT_shader_framebuffer_fetch ";
746     if (s_glSupport.GL_EXT_TEXTURE_FORMAT_BGRA8888) {
747         *s_glExtensions+="GL_EXT_texture_format_BGRA8888 GL_APPLE_texture_format_BGRA8888 ";
748     }
749 
750     s_glExtensionsInitialized = true;
751 }
752 
getMaxTexUnits()753 int GLESv2Context::getMaxTexUnits() {
754     return getCaps()->maxTexImageUnits;
755 }
756 
getMaxCombinedTexUnits()757 int GLESv2Context::getMaxCombinedTexUnits() {
758     return getCaps()->maxCombinedTexImageUnits;
759 }
760 
getTransformFeedbackGlobalName(ObjectLocalName p_localName)761 unsigned int GLESv2Context::getTransformFeedbackGlobalName(
762         ObjectLocalName p_localName) {
763     return m_transformFeedbackNameSpace->getGlobalName(p_localName);
764 }
765 
hasBoundTransformFeedback(ObjectLocalName transformFeedback)766 bool GLESv2Context::hasBoundTransformFeedback(
767         ObjectLocalName transformFeedback) {
768     return transformFeedback &&
769            m_transformFeedbackNameSpace->getObjectDataPtr(transformFeedback)
770                    .get();
771 }
772 
genTransformFeedbackName(ObjectLocalName p_localName,bool genLocal)773 ObjectLocalName GLESv2Context::genTransformFeedbackName(
774         ObjectLocalName p_localName,
775         bool genLocal) {
776     return m_transformFeedbackNameSpace->genName(
777             GenNameInfo(NamedObjectType::TRANSFORM_FEEDBACK), p_localName,
778             genLocal);
779 }
780 
bindTransformFeedback(ObjectLocalName p_localName)781 void GLESv2Context::bindTransformFeedback(ObjectLocalName p_localName) {
782     if (m_transformFeedbackDeletePending &&
783         m_bindTransformFeedback != p_localName) {
784         m_transformFeedbackNameSpace->deleteName(m_bindTransformFeedback);
785         m_transformFeedbackDeletePending = false;
786     }
787     m_bindTransformFeedback = p_localName;
788     if (p_localName &&
789         !m_transformFeedbackNameSpace->getGlobalName(p_localName)) {
790         genTransformFeedbackName(p_localName, false);
791     }
792     if (p_localName &&
793         !m_transformFeedbackNameSpace->getObjectDataPtr(p_localName).get()) {
794         TransformFeedbackData* tf = new TransformFeedbackData();
795         tf->setMaxSize(getCaps()->maxTransformFeedbackSeparateAttribs);
796         m_transformFeedbackNameSpace->setObjectData(p_localName,
797                                                     ObjectDataPtr(tf));
798     }
799 }
800 
getTransformFeedbackBinding()801 ObjectLocalName GLESv2Context::getTransformFeedbackBinding() {
802     return m_bindTransformFeedback;
803 }
804 
deleteTransformFeedback(ObjectLocalName p_localName)805 void GLESv2Context::deleteTransformFeedback(ObjectLocalName p_localName) {
806     // Note: GLES3.0 says it should be pending for delete if it is active
807     // GLES3.2 says report error in this situation
808     if (m_bindTransformFeedback == p_localName) {
809         m_transformFeedbackDeletePending = true;
810         return;
811     }
812     m_transformFeedbackNameSpace->deleteName(p_localName);
813 }
814 
boundTransformFeedback()815 TransformFeedbackData* GLESv2Context::boundTransformFeedback() {
816     return (TransformFeedbackData*)m_transformFeedbackNameSpace
817             ->getObjectDataPtr(m_bindTransformFeedback)
818             .get();
819 }
820 
getIndexedBuffer(GLenum target,GLuint index)821 GLuint GLESv2Context::getIndexedBuffer(GLenum target, GLuint index) {
822     switch (target) {
823         case GL_TRANSFORM_FEEDBACK_BUFFER:
824             return boundTransformFeedback()->getIndexedBuffer(index);
825         default:
826             return GLEScontext::getIndexedBuffer(target, index);
827     }
828 }
829 
bindIndexedBuffer(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size,GLintptr stride,bool isBindBase)830 void GLESv2Context::bindIndexedBuffer(GLenum target,
831                                       GLuint index,
832                                       GLuint buffer,
833                                       GLintptr offset,
834                                       GLsizeiptr size,
835                                       GLintptr stride,
836                                       bool isBindBase) {
837     switch (target) {
838         case GL_TRANSFORM_FEEDBACK_BUFFER: {
839             TransformFeedbackData* tf = boundTransformFeedback();
840             tf->bindIndexedBuffer(index, buffer, offset, size, stride,
841                                   isBindBase);
842             break;
843         }
844         default:
845             GLEScontext::bindIndexedBuffer(target, index, buffer, offset, size,
846                                            stride, isBindBase);
847     }
848 }
849 
bindIndexedBuffer(GLenum target,GLuint index,GLuint buffer)850 void GLESv2Context::bindIndexedBuffer(GLenum target,
851                                       GLuint index,
852                                       GLuint buffer) {
853     GLEScontext::bindIndexedBuffer(target, index, buffer);
854 }
855 
unbindBuffer(GLuint buffer)856 void GLESv2Context::unbindBuffer(GLuint buffer) {
857     if (m_glesMajorVersion >= 3) {
858         boundTransformFeedback()->unbindBuffer(buffer);
859     }
860     GLEScontext::unbindBuffer(buffer);
861 }
862