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