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