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