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