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(bool nativeTextureDecompressionEnabled)67 void GLESv2Context::init(bool nativeTextureDecompressionEnabled) {
68 android::base::AutoLock mutex(s_lock);
69 if(!m_initialized) {
70 GLEScontext::init(nativeTextureDecompressionEnabled);
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 initExtensionString();
240 GLDispatch& dispatcher = GLEScontext::dispatcher();
241 m_useProgramData = shareGroup()->getObjectDataPtr(
242 NamedObjectType::SHADER_OR_PROGRAM, m_useProgram);
243 const GLuint globalProgramName = shareGroup()->getGlobalName(
244 NamedObjectType::SHADER_OR_PROGRAM, m_useProgram);
245 dispatcher.glUseProgram(globalProgramName);
246
247 initEmulatedBuffers();
248 initEmulatedVAO();
249
250 // vertex attribute pointers
251 for (const auto& vaoIte : m_vaoStateMap) {
252 if (vaoIte.first != 0) {
253 genVAOName(vaoIte.first, false);
254 }
255 dispatcher.glBindVertexArray(getVAOGlobalName(vaoIte.first));
256 for (uint32_t i = 0; i < kMaxVertexAttributes; ++i) {
257 GLESpointer* glesPointer =
258 (GLESpointer*)(vaoIte.second.vertexAttribInfo.data() + i);
259
260 // don't skip enabling if the guest assumes it was enabled.
261 if (glesPointer->isEnable()) {
262 dispatcher.glEnableVertexAttribArray(i);
263 }
264
265 // attribute 0 are bound right before draw, no need to bind it here
266 if (glesPointer->getAttribType() == GLESpointer::VALUE
267 && i == 0) {
268 continue;
269 }
270 switch (glesPointer->getAttribType()) {
271 case GLESpointer::BUFFER: {
272 const GLuint globalBufferName = shareGroup()
273 ->getGlobalName(NamedObjectType::VERTEXBUFFER,
274 glesPointer->getBufferName());
275 if (!globalBufferName) {
276 continue;
277 }
278 glesPointer->restoreBufferObj(getBufferObj);
279 dispatcher.glBindBuffer(GL_ARRAY_BUFFER,
280 globalBufferName);
281 if (glesPointer->isIntPointer()) {
282 dispatcher.glVertexAttribIPointer(i,
283 glesPointer->getSize(),
284 glesPointer->getType(),
285 glesPointer->getStride(),
286 (GLvoid*)(size_t)glesPointer->getBufferOffset());
287 } else {
288 dispatcher.glVertexAttribPointer(i,
289 glesPointer->getSize(),
290 glesPointer->getType(), glesPointer->isNormalize(),
291 glesPointer->getStride(),
292 (GLvoid*)(size_t)glesPointer->getBufferOffset());
293 }
294 break;
295 }
296 case GLESpointer::VALUE:
297 switch (glesPointer->getValueCount()) {
298 case 1:
299 dispatcher.glVertexAttrib1fv(i,
300 glesPointer->getValues());
301 break;
302 case 2:
303 dispatcher.glVertexAttrib2fv(i,
304 glesPointer->getValues());
305 break;
306 case 3:
307 dispatcher.glVertexAttrib3fv(i,
308 glesPointer->getValues());
309 break;
310 case 4:
311 dispatcher.glVertexAttrib4fv(i,
312 glesPointer->getValues());
313 break;
314 }
315 break;
316 case GLESpointer::ARRAY:
317 // client arrays are set up right before draw calls
318 // so we do nothing here
319 break;
320 }
321 }
322 for (size_t i = 0; i < vaoIte.second.bindingState.size(); i++) {
323 const BufferBinding& bufferBinding = vaoIte.second.bindingState[i];
324 if (bufferBinding.divisor) {
325 dispatcher.glVertexAttribDivisor(i, bufferBinding.divisor);
326 }
327 }
328 }
329 dispatcher.glBindVertexArray(getVAOGlobalName(m_currVaoState.vaoId()));
330 if (m_glesMajorVersion >= 3) {
331 auto bindBufferRangeFunc =
332 [this](GLenum target,
333 const std::vector<BufferBinding>& bufferBindings) {
334 for (unsigned int i = 0; i < bufferBindings.size(); i++) {
335 const BufferBinding& bd = bufferBindings[i];
336 GLuint globalName = this->shareGroup()->getGlobalName(
337 NamedObjectType::VERTEXBUFFER,
338 bd.buffer);
339 assert(bd.buffer == 0 || globalName != 0);
340 if (bd.isBindBase || bd.buffer == 0) {
341 this->dispatcher().glBindBufferBase(target,
342 i, globalName);
343 } else {
344 this->dispatcher().glBindBufferRange(target,
345 i, globalName, bd.offset, bd.size);
346 }
347 }
348 };
349 bindBufferRangeFunc(GL_TRANSFORM_FEEDBACK_BUFFER,
350 m_indexedTransformFeedbackBuffers);
351 bindBufferRangeFunc(GL_UNIFORM_BUFFER,
352 m_indexedUniformBuffers);
353
354 if (m_glesMinorVersion >= 1) {
355 bindBufferRangeFunc(GL_ATOMIC_COUNTER_BUFFER,
356 m_indexedAtomicCounterBuffers);
357 bindBufferRangeFunc(GL_SHADER_STORAGE_BUFFER,
358 m_indexedShaderStorageBuffers);
359 }
360
361 // buffer bindings
362 auto bindBuffer = [this](GLenum target, GLuint buffer) {
363 this->dispatcher().glBindBuffer(target,
364 m_shareGroup->getGlobalName(NamedObjectType::VERTEXBUFFER, buffer));
365 };
366 bindBuffer(GL_COPY_READ_BUFFER, m_copyReadBuffer);
367 bindBuffer(GL_COPY_WRITE_BUFFER, m_copyWriteBuffer);
368 bindBuffer(GL_PIXEL_PACK_BUFFER, m_pixelPackBuffer);
369 bindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pixelUnpackBuffer);
370 bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transformFeedbackBuffer);
371 bindBuffer(GL_UNIFORM_BUFFER, m_uniformBuffer);
372
373 if (m_glesMinorVersion >= 1) {
374 bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterBuffer);
375 bindBuffer(GL_DISPATCH_INDIRECT_BUFFER, m_dispatchIndirectBuffer);
376 bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_drawIndirectBuffer);
377 bindBuffer(GL_SHADER_STORAGE_BUFFER, m_shaderStorageBuffer);
378 if (getCaps()->textureBufferAny()) {
379 bindBuffer(GL_TEXTURE_BUFFER, m_textureBuffer);
380 }
381 }
382 for (const auto& bindSampler : m_bindSampler) {
383 dispatcher.glBindSampler(bindSampler.first,
384 shareGroup()->getGlobalName(NamedObjectType::SAMPLER,
385 bindSampler.second));
386 }
387 m_transformFeedbackNameSpace->postLoadRestore(
388 [this](NamedObjectType p_type, ObjectLocalName p_localName) {
389 switch (p_type) {
390 case NamedObjectType::FRAMEBUFFER:
391 return getFBOGlobalName(p_localName);
392 case NamedObjectType::TRANSFORM_FEEDBACK:
393 return getTransformFeedbackGlobalName(p_localName);
394 default:
395 return m_shareGroup->getGlobalName(p_type,
396 p_localName);
397 }
398 });
399 dispatcher.glBindTransformFeedback(
400 GL_TRANSFORM_FEEDBACK,
401 getTransformFeedbackGlobalName(m_transformFeedbackBuffer));
402 }
403
404 GLEScontext::postLoadRestoreCtx();
405 }
406
loadObject(NamedObjectType type,ObjectLocalName localName,android::base::Stream * stream) const407 ObjectDataPtr GLESv2Context::loadObject(NamedObjectType type,
408 ObjectLocalName localName, android::base::Stream* stream) const {
409 switch (type) {
410 case NamedObjectType::VERTEXBUFFER:
411 case NamedObjectType::TEXTURE:
412 case NamedObjectType::FRAMEBUFFER:
413 case NamedObjectType::RENDERBUFFER:
414 return GLEScontext::loadObject(type, localName, stream);
415 case NamedObjectType::SAMPLER:
416 return ObjectDataPtr(new SamplerData(stream));
417 case NamedObjectType::SHADER_OR_PROGRAM:
418 // load the first bit to see if it is a program or shader
419 switch (stream->getByte()) {
420 case LOAD_PROGRAM:
421 return ObjectDataPtr(new ProgramData(stream));
422 case LOAD_SHADER:
423 return ObjectDataPtr(new ShaderParser(stream));
424 default:
425 fprintf(stderr, "corrupted snapshot\n");
426 assert(false);
427 return nullptr;
428 }
429 case NamedObjectType::TRANSFORM_FEEDBACK:
430 return ObjectDataPtr(new TransformFeedbackData(stream));
431 default:
432 return nullptr;
433 }
434 }
435
setAttribValue(int idx,unsigned int count,const GLfloat * val)436 void GLESv2Context::setAttribValue(int idx, unsigned int count,
437 const GLfloat* val) {
438 m_currVaoState.attribInfo()[idx].setValue(count, val);
439 }
440
setAttribute0value(float x,float y,float z,float w)441 void GLESv2Context::setAttribute0value(float x, float y, float z, float w)
442 {
443 m_attribute0valueChanged |=
444 x != m_attribute0value[0] || y != m_attribute0value[1] ||
445 z != m_attribute0value[2] || w != m_attribute0value[3];
446 m_attribute0value[0] = x;
447 m_attribute0value[1] = y;
448 m_attribute0value[2] = z;
449 m_attribute0value[3] = w;
450 }
451
needAtt0PreDrawValidation()452 bool GLESv2Context::needAtt0PreDrawValidation()
453 {
454 m_att0NeedsDisable = false;
455
456 // We could go into the driver here and call
457 // s_glDispatch.glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled)
458 // ... but it's too much for a simple check that runs on almost every draw
459 // call.
460 return !isArrEnabled(0);
461 }
462
validateAtt0PreDraw(unsigned int count)463 void GLESv2Context::validateAtt0PreDraw(unsigned int count)
464 {
465 if (count == 0) {
466 return;
467 }
468
469 if (count > m_att0ArrayLength) {
470 const unsigned newLen = std::max(count, 2 * m_att0ArrayLength);
471 m_att0Array.reset(new GLfloat[4 * newLen]);
472 m_att0ArrayLength = newLen;
473 m_attribute0valueChanged = true;
474 }
475 if (m_attribute0valueChanged) {
476 for(unsigned int i = 0; i<m_att0ArrayLength; i++) {
477 memcpy(m_att0Array.get()+i*4, m_attribute0value,
478 sizeof(m_attribute0value));
479 }
480 m_attribute0valueChanged = false;
481 }
482
483 GLuint prevArrayBuffer;
484 s_glDispatch.glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&prevArrayBuffer);
485
486 s_glDispatch.glBindBuffer(GL_ARRAY_BUFFER, m_emulatedClientVBOs[0]);
487 s_glDispatch.glBufferData(GL_ARRAY_BUFFER, m_att0ArrayLength * sizeof(GLfloat), m_att0Array.get(), GL_STREAM_DRAW);
488
489 s_glDispatch.glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
490 s_glDispatch.glEnableVertexAttribArray(0);
491
492 s_glDispatch.glBindBuffer(GL_ARRAY_BUFFER, prevArrayBuffer);
493
494 m_att0NeedsDisable = true;
495 }
496
validateAtt0PostDraw(void)497 void GLESv2Context::validateAtt0PostDraw(void)
498 {
499 if (m_att0NeedsDisable) {
500 s_glDispatch.glDisableVertexAttribArray(0);
501 m_att0NeedsDisable = false;
502 }
503 }
504
drawWithEmulations(DrawCallCmd cmd,GLenum mode,GLint first,GLsizei count,GLenum type,const GLvoid * indices,GLsizei primcount,GLuint start,GLuint end)505 void GLESv2Context::drawWithEmulations(
506 DrawCallCmd cmd,
507 GLenum mode,
508 GLint first,
509 GLsizei count,
510 GLenum type,
511 const GLvoid* indices,
512 GLsizei primcount,
513 GLuint start,
514 GLuint end) {
515
516 if (getMajorVersion() < 3) {
517 drawValidate();
518 }
519
520 bool needClientVBOSetup = !vertexAttributesBufferBacked();
521
522 bool needClientIBOSetup =
523 (cmd != DrawCallCmd::Arrays &&
524 cmd != DrawCallCmd::ArraysInstanced) &&
525 !isBindedBuffer(GL_ELEMENT_ARRAY_BUFFER);
526 bool needPointEmulation = mode == GL_POINTS && !isGles2Gles();
527
528 #ifdef __APPLE__
529 if (!isGles2Gles() && primitiveRestartEnabled() && type) {
530 updatePrimitiveRestartIndex(type);
531 }
532 #endif
533
534 if (needPointEmulation) {
535 s_glDispatch.glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
536 if (!isCoreProfile()) {
537 // Enable texture generation for GL_POINTS and gl_PointSize shader variable
538 // GLES2 assumes this is enabled by default, we need to set this state for GL
539 s_glDispatch.glEnable(GL_POINT_SPRITE);
540 }
541 }
542
543 bool needEnablingPostDraw[kMaxVertexAttributes];
544 memset(needEnablingPostDraw, 0, sizeof(needEnablingPostDraw));
545
546 if (needClientVBOSetup) {
547 GLESConversionArrays tmpArrs;
548 bool needPauseTransformFeedback = boundTransformFeedback()
549 && boundTransformFeedback()->mIsActive
550 && !boundTransformFeedback()->mIsPaused;
551 if (needPauseTransformFeedback) {
552 s_glDispatch.glPauseTransformFeedback();
553 }
554 setupArraysPointers(tmpArrs, 0, count, type, indices, false, needEnablingPostDraw);
555 if (needPauseTransformFeedback) {
556 s_glDispatch.glResumeTransformFeedback();
557 }
558 if (needAtt0PreDrawValidation()) {
559 if (indices) {
560 validateAtt0PreDraw(findMaxIndex(count, type, indices));
561 } else {
562 validateAtt0PreDraw(count);
563 }
564 }
565 }
566
567 GLuint prevIBO;
568 if (needClientIBOSetup) {
569 int bpv = 2;
570 switch (type) {
571 case GL_UNSIGNED_BYTE:
572 bpv = 1;
573 break;
574 case GL_UNSIGNED_SHORT:
575 bpv = 2;
576 break;
577 case GL_UNSIGNED_INT:
578 bpv = 4;
579 break;
580 }
581
582 size_t dataSize = bpv * count;
583
584 s_glDispatch.glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint*)&prevIBO);
585 s_glDispatch.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_emulatedClientIBO);
586 s_glDispatch.glBufferData(GL_ELEMENT_ARRAY_BUFFER, dataSize, indices, GL_STREAM_DRAW);
587 }
588
589 const GLvoid* indicesOrOffset =
590 needClientIBOSetup ? nullptr : indices;
591
592 switch (cmd) {
593 case DrawCallCmd::Elements:
594 s_glDispatch.glDrawElements(mode, count, type, indicesOrOffset);
595 break;
596 case DrawCallCmd::ElementsInstanced:
597 s_glDispatch.glDrawElementsInstanced(mode, count, type,
598 indicesOrOffset,
599 primcount);
600 break;
601 case DrawCallCmd::RangeElements:
602 s_glDispatch.glDrawRangeElements(mode, start, end, count, type,
603 indicesOrOffset);
604 break;
605 case DrawCallCmd::Arrays:
606 s_glDispatch.glDrawArrays(mode, first, count);
607 break;
608 case DrawCallCmd::ArraysInstanced:
609 s_glDispatch.glDrawArraysInstanced(mode, first, count, primcount);
610 break;
611 default:
612 emugl::emugl_crash_reporter(
613 "drawWithEmulations has corrupt call parameters!");
614 }
615
616 if (needClientIBOSetup) {
617 s_glDispatch.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prevIBO);
618 }
619
620 if (needClientVBOSetup) {
621 validateAtt0PostDraw();
622 }
623
624 if (needPointEmulation) {
625 s_glDispatch.glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
626 if (!isCoreProfile()) {
627 s_glDispatch.glDisable(GL_POINT_SPRITE);
628 }
629 }
630
631 for (int i = 0; i < kMaxVertexAttributes; ++i) {
632 if (needEnablingPostDraw[i]) {
633 s_glDispatch.glEnableVertexAttribArray(i);
634 }
635 }
636 }
637
setupArraysPointers(GLESConversionArrays & cArrs,GLint first,GLsizei count,GLenum type,const GLvoid * indices,bool direct,bool * needEnablingPostDraw)638 void GLESv2Context::setupArraysPointers(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct, bool* needEnablingPostDraw) {
639 //going over all clients arrays Pointers
640 for (uint32_t i = 0; i < kMaxVertexAttributes; ++i) {
641 GLESpointer* p = m_currVaoState.attribInfo().data() + i;
642 if (!p->isEnable() || p->getAttribType() == GLESpointer::VALUE) {
643 continue;
644 }
645
646 setupArrWithDataSize(
647 p->getDataSize(),
648 p->getArrayData(),
649 i,
650 p->getType(),
651 p->getSize(),
652 p->getStride(),
653 p->getNormalized(),
654 -1,
655 p->isIntPointer(),
656 p->getBufferName(),
657 needEnablingPostDraw);
658 }
659 }
660
661 //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)662 void GLESv2Context::setupArrWithDataSize(GLsizei datasize, const GLvoid* arr,
663 GLenum arrayType, GLenum dataType,
664 GLint size, GLsizei stride, GLboolean normalized, int index, bool isInt, GLuint ptrBufferName, bool* needEnablingPostDraw){
665 // is not really a client side arr.
666 if (arr == NULL) {
667 GLint isEnabled;
668 s_glDispatch.glGetVertexAttribiv((int)arrayType, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &isEnabled);
669 if (isEnabled && !ptrBufferName) {
670 s_glDispatch.glDisableVertexAttribArray(arrayType);
671 if (needEnablingPostDraw)
672 needEnablingPostDraw[arrayType] = true;
673 }
674
675 return;
676 }
677
678 GLuint prevArrayBuffer;
679 s_glDispatch.glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&prevArrayBuffer);
680
681 if (arrayType < m_emulatedClientVBOs.size()) {
682 s_glDispatch.glBindBuffer(GL_ARRAY_BUFFER, m_emulatedClientVBOs[arrayType]);
683 } else {
684 fprintf(stderr, "%s: invalid attribute index: %d\n", __func__, (int)arrayType);
685 }
686
687 s_glDispatch.glBufferData(GL_ARRAY_BUFFER, datasize, arr, GL_STREAM_DRAW);
688
689 if (isInt) {
690 s_glDispatch.glVertexAttribIPointer(arrayType, size, dataType, stride, 0);
691 } else {
692 s_glDispatch.glVertexAttribPointer(arrayType, size, dataType, normalized, stride, 0);
693 }
694
695 s_glDispatch.glBindBuffer(GL_ARRAY_BUFFER, prevArrayBuffer);
696 }
697
setVertexAttribDivisor(GLuint bindingindex,GLuint divisor)698 void GLESv2Context::setVertexAttribDivisor(GLuint bindingindex, GLuint divisor) {
699 if (bindingindex >= m_currVaoState.bufferBindings().size()) {
700 return;
701 }
702 m_currVaoState.bufferBindings()[bindingindex].divisor = divisor;
703 }
704
setVertexAttribBindingIndex(GLuint attribindex,GLuint bindingindex)705 void GLESv2Context::setVertexAttribBindingIndex(GLuint attribindex, GLuint bindingindex) {
706 if (attribindex > kMaxVertexAttributes) return;
707
708 m_currVaoState.attribInfo()[attribindex].setBindingIndex(bindingindex);
709 }
710
setVertexAttribFormat(GLuint attribindex,GLint size,GLenum type,GLboolean normalized,GLuint reloffset,bool isInt)711 void GLESv2Context::setVertexAttribFormat(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt) {
712 if (attribindex > kMaxVertexAttributes) return;
713 m_currVaoState.attribInfo()[attribindex].setFormat(size, type, normalized == GL_TRUE, reloffset, isInt);
714 }
715
setBindSampler(GLuint unit,GLuint sampler)716 void GLESv2Context::setBindSampler(GLuint unit, GLuint sampler) {
717 m_bindSampler[unit] = sampler;
718 }
719
needConvert(GLESConversionArrays & cArrs,GLint first,GLsizei count,GLenum type,const GLvoid * indices,bool direct,GLESpointer * p,GLenum array_id)720 bool GLESv2Context::needConvert(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id) {
721
722 bool usingVBO = p->getAttribType() == GLESpointer::BUFFER;
723 GLenum arrType = p->getType();
724
725 /*
726 conversion is not necessary in the following cases:
727 (*) array type is not fixed
728 */
729 if(arrType != GL_FIXED) return false;
730
731 if(!usingVBO) {
732 if (direct) {
733 convertDirect(cArrs,first,count,array_id,p);
734 } else {
735 convertIndirect(cArrs,count,type,indices,array_id,p);
736 }
737 } else {
738 if (direct) {
739 convertDirectVBO(cArrs,first,count,array_id,p);
740 } else {
741 convertIndirectVBO(cArrs,count,type,indices,array_id,p);
742 }
743 }
744 return true;
745 }
746
setUseProgram(GLuint program,const ObjectDataPtr & programData)747 void GLESv2Context::setUseProgram(GLuint program,
748 const ObjectDataPtr& programData) {
749 m_useProgram = program;
750 assert(!programData ||
751 programData->getDataType() == ObjectDataType::PROGRAM_DATA);
752 m_useProgramData = programData;
753 }
754
getCurrentProgram() const755 GLuint GLESv2Context::getCurrentProgram() const {
756 return m_useProgram;
757 }
758
getUseProgram()759 ProgramData* GLESv2Context::getUseProgram() {
760 return (ProgramData*)m_useProgramData.get();
761 }
762
763
InitExtensionString(GLSupport & glSupport,std::string & ext)764 void InitExtensionString(GLSupport& glSupport, std::string& ext) {
765 ext =
766 "GL_OES_EGL_sync GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_depth24 GL_OES_depth32 "
767 "GL_OES_element_index_uint "
768 "GL_OES_texture_float GL_OES_texture_float_linear "
769 "GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture "
770 "GL_OES_depth_texture ";
771 if (glSupport.GL_ARB_HALF_FLOAT_PIXEL || glSupport.GL_NV_HALF_FLOAT)
772 ext += "GL_OES_texture_half_float GL_OES_texture_half_float_linear ";
773 if (glSupport.GL_EXT_PACKED_DEPTH_STENCIL) ext += "GL_OES_packed_depth_stencil ";
774 if (glSupport.GL_ARB_HALF_FLOAT_VERTEX) ext += "GL_OES_vertex_half_float ";
775 if (glSupport.GL_OES_STANDARD_DERIVATIVES) ext += "GL_OES_standard_derivatives ";
776 if (glSupport.GL_OES_TEXTURE_NPOT) ext += "GL_OES_texture_npot ";
777 if (glSupport.GL_OES_RGB8_RGBA8) ext += "GL_OES_rgb8_rgba8 ";
778 if (glSupport.ext_GL_OVR_multiview2) ext += "GL_OVR_multiview2 ";
779 if (glSupport.ext_GL_EXT_multiview_texture_multisample) ext += "GL_EXT_multiview_texture_multisample ";
780 if (glSupport.ext_GL_EXT_color_buffer_float) ext += "GL_EXT_color_buffer_float ";
781 if (glSupport.ext_GL_EXT_color_buffer_half_float) ext += "GL_EXT_color_buffer_half_float ";
782 // b/203446380
783 // Does not really work on hardware GPUs
784 if (glSupport.ext_GL_EXT_shader_framebuffer_fetch && isGles2Gles()) ext += "GL_EXT_shader_framebuffer_fetch ";
785 if (glSupport.GL_EXT_TEXTURE_FORMAT_BGRA8888) {
786 ext += "GL_EXT_texture_format_BGRA8888 GL_APPLE_texture_format_BGRA8888 ";
787 }
788 if (glSupport.ext_GL_EXT_texture_buffer) {
789 ext += "GL_EXT_texture_buffer ";
790 }
791 if (glSupport.ext_GL_OES_texture_buffer) {
792 ext += "GL_OES_texture_buffer ";
793 }
794 if (glSupport.ext_GL_EXT_draw_buffers_indexed) {
795 ext += "GL_EXT_draw_buffers_indexed ";
796 }
797 if (glSupport.ext_GL_EXT_clip_cull_distance) {
798 ext += "GL_EXT_clip_cull_distance ";
799 }
800 }
801
initExtensionString()802 void GLESv2Context::initExtensionString() {
803 if (m_glesMajorVersion == 3 && m_glesMinorVersion == 1) {
804 if (s_glExtensionsGles31Initialized) return;
805 initCapsLocked((const GLubyte*)getHostExtensionsString(&s_glDispatch).c_str(),
806 m_nativeTextureDecompressionEnabled, s_glSupportGles31);
807 InitExtensionString(s_glSupportGles31, *s_glExtensionsGles31);
808 s_glExtensionsGles31Initialized = true;
809 } else {
810 if (s_glExtensionsInitialized) return;
811 initCapsLocked((const GLubyte*)getHostExtensionsString(&s_glDispatch).c_str(),
812 m_nativeTextureDecompressionEnabled, s_glSupport);
813 InitExtensionString(s_glSupport, *s_glExtensions);
814 s_glExtensionsInitialized = true;
815 }
816 }
817
getMaxTexUnits()818 int GLESv2Context::getMaxTexUnits() {
819 return getCaps()->maxTexImageUnits;
820 }
821
getMaxCombinedTexUnits()822 int GLESv2Context::getMaxCombinedTexUnits() {
823 return getCaps()->maxCombinedTexImageUnits;
824 }
825
getTransformFeedbackGlobalName(ObjectLocalName p_localName)826 unsigned int GLESv2Context::getTransformFeedbackGlobalName(
827 ObjectLocalName p_localName) {
828 return m_transformFeedbackNameSpace->getGlobalName(p_localName);
829 }
830
hasBoundTransformFeedback(ObjectLocalName transformFeedback)831 bool GLESv2Context::hasBoundTransformFeedback(
832 ObjectLocalName transformFeedback) {
833 return transformFeedback &&
834 m_transformFeedbackNameSpace->getObjectDataPtr(transformFeedback)
835 .get();
836 }
837
genTransformFeedbackName(ObjectLocalName p_localName,bool genLocal)838 ObjectLocalName GLESv2Context::genTransformFeedbackName(
839 ObjectLocalName p_localName,
840 bool genLocal) {
841 return m_transformFeedbackNameSpace->genName(
842 GenNameInfo(NamedObjectType::TRANSFORM_FEEDBACK), p_localName,
843 genLocal);
844 }
845
bindTransformFeedback(ObjectLocalName p_localName)846 void GLESv2Context::bindTransformFeedback(ObjectLocalName p_localName) {
847 if (m_transformFeedbackDeletePending &&
848 m_bindTransformFeedback != p_localName) {
849 m_transformFeedbackNameSpace->deleteName(m_bindTransformFeedback);
850 m_transformFeedbackDeletePending = false;
851 }
852 m_bindTransformFeedback = p_localName;
853 if (p_localName &&
854 !m_transformFeedbackNameSpace->getGlobalName(p_localName)) {
855 genTransformFeedbackName(p_localName, false);
856 }
857 if (p_localName &&
858 !m_transformFeedbackNameSpace->getObjectDataPtr(p_localName).get()) {
859 TransformFeedbackData* tf = new TransformFeedbackData();
860 tf->setMaxSize(getCaps()->maxTransformFeedbackSeparateAttribs);
861 m_transformFeedbackNameSpace->setObjectData(p_localName,
862 ObjectDataPtr(tf));
863 }
864 }
865
getTransformFeedbackBinding()866 ObjectLocalName GLESv2Context::getTransformFeedbackBinding() {
867 return m_bindTransformFeedback;
868 }
869
deleteTransformFeedback(ObjectLocalName p_localName)870 void GLESv2Context::deleteTransformFeedback(ObjectLocalName p_localName) {
871 // Note: GLES3.0 says it should be pending for delete if it is active
872 // GLES3.2 says report error in this situation
873 if (m_bindTransformFeedback == p_localName) {
874 m_transformFeedbackDeletePending = true;
875 return;
876 }
877 m_transformFeedbackNameSpace->deleteName(p_localName);
878 }
879
boundTransformFeedback()880 TransformFeedbackData* GLESv2Context::boundTransformFeedback() {
881 return (TransformFeedbackData*)m_transformFeedbackNameSpace
882 ->getObjectDataPtr(m_bindTransformFeedback)
883 .get();
884 }
885
getIndexedBuffer(GLenum target,GLuint index)886 GLuint GLESv2Context::getIndexedBuffer(GLenum target, GLuint index) {
887 switch (target) {
888 case GL_TRANSFORM_FEEDBACK_BUFFER:
889 return boundTransformFeedback()->getIndexedBuffer(index);
890 default:
891 return GLEScontext::getIndexedBuffer(target, index);
892 }
893 }
894
bindIndexedBuffer(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size,GLintptr stride,bool isBindBase)895 void GLESv2Context::bindIndexedBuffer(GLenum target,
896 GLuint index,
897 GLuint buffer,
898 GLintptr offset,
899 GLsizeiptr size,
900 GLintptr stride,
901 bool isBindBase) {
902 switch (target) {
903 case GL_TRANSFORM_FEEDBACK_BUFFER: {
904 TransformFeedbackData* tf = boundTransformFeedback();
905 tf->bindIndexedBuffer(index, buffer, offset, size, stride,
906 isBindBase);
907 break;
908 }
909 default:
910 GLEScontext::bindIndexedBuffer(target, index, buffer, offset, size,
911 stride, isBindBase);
912 }
913 }
914
bindIndexedBuffer(GLenum target,GLuint index,GLuint buffer)915 void GLESv2Context::bindIndexedBuffer(GLenum target,
916 GLuint index,
917 GLuint buffer) {
918 GLEScontext::bindIndexedBuffer(target, index, buffer);
919 }
920
unbindBuffer(GLuint buffer)921 void GLESv2Context::unbindBuffer(GLuint buffer) {
922 if (m_glesMajorVersion >= 3) {
923 boundTransformFeedback()->unbindBuffer(buffer);
924 }
925 GLEScontext::unbindBuffer(buffer);
926 }
927