1 /*
2 * Copyright (C) 2017 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 "CoreProfileEngine.h"
18 
19 #include "CoreProfileEngineShaders.h"
20 #include "GLcommon/GLEScontext.h"
21 #include "GLcommon/GLESpointer.h"
22 #include "GLEScmContext.h"
23 
24 #include "aemu/base/containers/Lookup.h"
25 #include "host-common/crash_reporter.h"
26 
27 #include <glm/vec3.hpp>
28 #include <glm/vec4.hpp>
29 #include <glm/gtc/matrix_inverse.hpp>
30 #include <glm/gtc/matrix_transform.hpp>
31 #include <glm/gtc/type_ptr.hpp>
32 
CoreProfileEngine(GLEScmContext * ctx,bool onGles)33 CoreProfileEngine::CoreProfileEngine(GLEScmContext* ctx, bool onGles) :
34     mCtx(ctx),
35     mOnGles(onGles) {
36     getGeometryDrawState();
37 }
38 
~CoreProfileEngine()39 CoreProfileEngine::~CoreProfileEngine() {
40     teardown();
41 }
42 
43 static const uint32_t sDrawTexIbo[] = {
44     0, 1, 2, 0, 2, 3,
45 };
46 
getDrawTexOESCoreState()47 const CoreProfileEngine::DrawTexOESCoreState& CoreProfileEngine::getDrawTexOESCoreState() {
48     if (!m_drawTexOESCoreState.program) {
49         m_drawTexOESCoreState.vshader =
50             GLEScontext::compileAndValidateCoreShader(
51                 GL_VERTEX_SHADER,
52                 mOnGles ? kDrawTexOESGles2_vshader : kDrawTexOESCore_vshader);
53         m_drawTexOESCoreState.fshader =
54             GLEScontext::compileAndValidateCoreShader(
55                 GL_FRAGMENT_SHADER,
56                 mOnGles ? kDrawTexOESGles2_fshader : kDrawTexOESCore_fshader);
57         m_drawTexOESCoreState.program =
58             GLEScontext::linkAndValidateProgram(m_drawTexOESCoreState.vshader,
59                                                 m_drawTexOESCoreState.fshader);
60     }
61     if (!m_drawTexOESCoreState.vao) {
62         GLDispatch& gl = GLEScontext::dispatcher();
63 
64         gl.glGenVertexArrays(1, &m_drawTexOESCoreState.vao);
65         gl.glBindVertexArray(m_drawTexOESCoreState.vao);
66 
67         // Initialize VBO
68         // Save IBO, attrib arrays/pointers to VAO
69         gl.glGenBuffers(1, &m_drawTexOESCoreState.ibo);
70         gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_drawTexOESCoreState.ibo);
71         gl.glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(sDrawTexIbo), sDrawTexIbo, GL_STATIC_DRAW);
72 
73         gl.glGenBuffers(1, &m_drawTexOESCoreState.vbo);
74         gl.glBindBuffer(GL_ARRAY_BUFFER, m_drawTexOESCoreState.vbo);
75 
76         gl.glEnableVertexAttribArray(0); // pos
77         gl.glEnableVertexAttribArray(1); // texcoord
78 
79         gl.glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)0);
80         gl.glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float),
81                                  (GLvoid*)(uintptr_t)(3 * sizeof(float)));
82 
83         gl.glBindVertexArray(0);
84 
85         gl.glBindBuffer(GL_ARRAY_BUFFER, 0);
86         gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
87     }
88 
89     return m_drawTexOESCoreState;
90 }
91 
teardown()92 void CoreProfileEngine::teardown() {
93     GLDispatch& gl = GLEScontext::dispatcher();
94 
95     if (m_drawTexOESCoreState.program) {
96         gl.glDeleteProgram(m_drawTexOESCoreState.program);
97         m_drawTexOESCoreState.program = 0;
98     }
99 
100     if (m_drawTexOESCoreState.vao) {
101         gl.glBindVertexArray(0);
102         gl.glDeleteVertexArrays(1, &m_drawTexOESCoreState.vao);
103         gl.glDeleteBuffers(1, &m_drawTexOESCoreState.ibo);
104         gl.glDeleteBuffers(1, &m_drawTexOESCoreState.vbo);
105         m_drawTexOESCoreState.vao = 0;
106         m_drawTexOESCoreState.vbo = 0;
107         m_drawTexOESCoreState.ibo = 0;
108     }
109 
110     if (m_geometryDrawState.program) {
111         gl.glDeleteProgram(m_geometryDrawState.program);
112         m_geometryDrawState.program = 0;
113     }
114 
115     if (m_geometryDrawState.programFlat) {
116         gl.glDeleteProgram(m_geometryDrawState.programFlat);
117         m_geometryDrawState.programFlat = 0;
118     }
119 
120     if (m_geometryDrawState.vao) {
121         gl.glDeleteVertexArrays(1, &m_geometryDrawState.vao);
122         m_geometryDrawState.vao = 0;
123     }
124     if (m_geometryDrawState.posVbo) {
125         gl.glDeleteBuffers(1, &m_geometryDrawState.posVbo);
126         m_geometryDrawState.posVbo = 0;
127     }
128 
129     if (m_geometryDrawState.normalVbo) {
130         gl.glDeleteBuffers(1, &m_geometryDrawState.normalVbo);
131         m_geometryDrawState.normalVbo = 0;
132     }
133 
134     if (m_geometryDrawState.colorVbo) {
135         gl.glDeleteBuffers(1, &m_geometryDrawState.colorVbo);
136         m_geometryDrawState.colorVbo = 0;
137     }
138 
139     if (m_geometryDrawState.pointsizeVbo) {
140         gl.glDeleteBuffers(1, &m_geometryDrawState.pointsizeVbo);
141         m_geometryDrawState.pointsizeVbo = 0;
142     }
143 
144     if (m_geometryDrawState.texcoordVbo) {
145         gl.glDeleteBuffers(1, &m_geometryDrawState.texcoordVbo);
146         m_geometryDrawState.texcoordVbo = 0;
147     }
148 
149     if (m_geometryDrawState.ibo) {
150         gl.glDeleteBuffers(1, &m_geometryDrawState.ibo);
151         m_geometryDrawState.ibo = 0;
152     }
153 }
154 
155 // Match attribute locations in the shader below.
arrayTypeToCoreAttrib(GLenum type)156 static GLint arrayTypeToCoreAttrib(GLenum type) {
157     switch (type) {
158     case GL_VERTEX_ARRAY:
159         return 0;
160     case GL_NORMAL_ARRAY:
161         return 1;
162     case GL_COLOR_ARRAY:
163         return 2;
164     case GL_POINT_SIZE_ARRAY_OES:
165         return 3;
166     case GL_TEXTURE_COORD_ARRAY:
167         return 4;
168     }
169     fprintf(stderr, "%s: error: unsupported array type 0x%x\n",
170             __func__, type);
171     return 0;
172 }
173 
sMakeGeometryDrawShader(bool isGles,GLenum shaderType,bool flat)174 static std::string sMakeGeometryDrawShader(bool isGles, GLenum shaderType, bool flat) {
175     // Set up a std::string to hold the result of
176     // interpolating the template. We will require some extra padding
177     // in the result string depending on how many characters
178     // we could potentially insert.
179     // For now it's just 10 chars and for a
180     // single interpolation qualifier |flat|.
181     static const char versionPartEssl300[] = "#version 300 es\n";
182     static const char versionPart330Core[] = "#version 330 core\n";
183     static const char flatKeyword[] = "flat";
184 
185     size_t extraStringLengthRequired = 10 +
186         sizeof(versionPartEssl300) +
187         sizeof(versionPart330Core) +
188         sizeof(flatKeyword);
189 
190     size_t reservation = extraStringLengthRequired;
191     std::string res;
192     const char* shaderTemplate = nullptr;
193 
194     switch (shaderType) {
195     case GL_VERTEX_SHADER:
196         reservation += sizeof(kGeometryDrawVShaderSrcTemplateCore);
197         shaderTemplate = kGeometryDrawVShaderSrcTemplateCore;
198         break;
199     case GL_FRAGMENT_SHADER:
200         reservation += sizeof(kGeometryDrawFShaderSrcTemplateCore);
201         shaderTemplate = kGeometryDrawFShaderSrcTemplateCore;
202         break;
203     default:
204         break;
205         // emugl_crash_reporter(
206         //     "%s: unknown shader type 0x%x (memory corrupt)\n", __func__,
207         //     shaderType);
208     }
209 
210     if (shaderTemplate) {
211         res.resize(reservation);
212         snprintf(&res[0], res.size(), shaderTemplate,
213                 isGles ? versionPartEssl300 : versionPart330Core,
214                 flat ? flatKeyword : "");
215     }
216     return res;
217 }
218 
getGeometryDrawState()219 const CoreProfileEngine::GeometryDrawState& CoreProfileEngine::getGeometryDrawState() {
220     auto& gl = GLEScontext::dispatcher();
221 
222     if (!m_geometryDrawState.program) {
223 
224         // Non-flat shader
225         m_geometryDrawState.vshader =
226             GLEScontext::compileAndValidateCoreShader(
227                 GL_VERTEX_SHADER,
228                 sMakeGeometryDrawShader(mOnGles, GL_VERTEX_SHADER, false /* no flat shading */).c_str());
229 
230         m_geometryDrawState.fshader =
231             GLEScontext::compileAndValidateCoreShader(
232                 GL_FRAGMENT_SHADER,
233                 sMakeGeometryDrawShader(mOnGles, GL_FRAGMENT_SHADER, false /* no flat shading */).c_str());
234 
235         m_geometryDrawState.program =
236             GLEScontext::linkAndValidateProgram(m_geometryDrawState.vshader,
237                                                 m_geometryDrawState.fshader);
238 
239         m_geometryDrawState.vshaderFlat =
240             GLEScontext::compileAndValidateCoreShader(
241                     GL_VERTEX_SHADER,
242                     sMakeGeometryDrawShader(mOnGles, GL_VERTEX_SHADER, true /* flat shading */).c_str());
243         m_geometryDrawState.fshaderFlat =
244             GLEScontext::compileAndValidateCoreShader(
245                     GL_FRAGMENT_SHADER,
246                     sMakeGeometryDrawShader(mOnGles, GL_FRAGMENT_SHADER, true /* flat shading */).c_str());
247         m_geometryDrawState.programFlat =
248             GLEScontext::linkAndValidateProgram(m_geometryDrawState.vshaderFlat,
249                                                 m_geometryDrawState.fshaderFlat);
250 
251         m_geometryDrawState.projMatrixLoc =
252             gl.glGetUniformLocation(m_geometryDrawState.program, "projection");
253         m_geometryDrawState.modelviewMatrixLoc =
254             gl.glGetUniformLocation(m_geometryDrawState.program, "modelview");
255         m_geometryDrawState.modelviewInvTrLoc =
256             gl.glGetUniformLocation(m_geometryDrawState.program, "modelview_invtr");
257         m_geometryDrawState.textureMatrixLoc =
258             gl.glGetUniformLocation(m_geometryDrawState.program, "texture_matrix");
259         m_geometryDrawState.textureSamplerLoc =
260             gl.glGetUniformLocation(m_geometryDrawState.program, "tex_sampler");
261         m_geometryDrawState.textureCubeSamplerLoc =
262             gl.glGetUniformLocation(m_geometryDrawState.program, "tex_cube_sampler");
263 
264         m_geometryDrawState.enableTextureLoc =
265             gl.glGetUniformLocation(m_geometryDrawState.program, "enable_textures");
266         m_geometryDrawState.enableLightingLoc =
267             gl.glGetUniformLocation(m_geometryDrawState.program, "enable_lighting");
268         m_geometryDrawState.enableRescaleNormalLoc =
269             gl.glGetUniformLocation(m_geometryDrawState.program, "enable_rescale_normal");
270         m_geometryDrawState.enableNormalizeLoc =
271             gl.glGetUniformLocation(m_geometryDrawState.program, "enable_normalize");
272         m_geometryDrawState.enableColorMaterialLoc =
273             gl.glGetUniformLocation(m_geometryDrawState.program, "enable_color_material");
274         m_geometryDrawState.enableFogLoc =
275             gl.glGetUniformLocation(m_geometryDrawState.program, "enable_fog");
276         m_geometryDrawState.enableReflectionMapLoc =
277             gl.glGetUniformLocation(m_geometryDrawState.program, "enable_reflection_map");
278 
279         m_geometryDrawState.textureEnvModeLoc =
280             gl.glGetUniformLocation(m_geometryDrawState.program, "texture_env_mode");
281         m_geometryDrawState.textureFormatLoc =
282             gl.glGetUniformLocation(m_geometryDrawState.program, "texture_format");
283 
284         m_geometryDrawState.materialAmbientLoc =
285             gl.glGetUniformLocation(m_geometryDrawState.program, "material_ambient");
286         m_geometryDrawState.materialDiffuseLoc =
287             gl.glGetUniformLocation(m_geometryDrawState.program, "material_diffuse");
288         m_geometryDrawState.materialSpecularLoc =
289             gl.glGetUniformLocation(m_geometryDrawState.program, "material_specular");
290         m_geometryDrawState.materialEmissiveLoc =
291             gl.glGetUniformLocation(m_geometryDrawState.program, "material_emissive");
292         m_geometryDrawState.materialSpecularExponentLoc =
293             gl.glGetUniformLocation(m_geometryDrawState.program, "material_specular_exponent");
294 
295         m_geometryDrawState.lightModelSceneAmbientLoc =
296             gl.glGetUniformLocation(m_geometryDrawState.program, "light_model_scene_ambient");
297         m_geometryDrawState.lightModelTwoSidedLoc =
298             gl.glGetUniformLocation(m_geometryDrawState.program, "light_model_two_sided");
299 
300         m_geometryDrawState.lightEnablesLoc =
301             gl.glGetUniformLocation(m_geometryDrawState.program, "light_enables");
302         m_geometryDrawState.lightAmbientsLoc =
303             gl.glGetUniformLocation(m_geometryDrawState.program, "light_ambients");
304         m_geometryDrawState.lightDiffusesLoc =
305             gl.glGetUniformLocation(m_geometryDrawState.program, "light_diffuses");
306         m_geometryDrawState.lightSpecularsLoc =
307             gl.glGetUniformLocation(m_geometryDrawState.program, "light_speculars");
308         m_geometryDrawState.lightPositionsLoc =
309             gl.glGetUniformLocation(m_geometryDrawState.program, "light_positions");
310         m_geometryDrawState.lightDirectionsLoc =
311             gl.glGetUniformLocation(m_geometryDrawState.program, "light_directions");
312         m_geometryDrawState.lightSpotlightExponentsLoc =
313             gl.glGetUniformLocation(m_geometryDrawState.program, "light_spotlight_exponents");
314         m_geometryDrawState.lightSpotlightCutoffAnglesLoc =
315             gl.glGetUniformLocation(m_geometryDrawState.program, "light_spotlight_cutoff_angles");
316         m_geometryDrawState.lightAttenuationConstsLoc =
317             gl.glGetUniformLocation(m_geometryDrawState.program, "light_attenuation_consts");
318         m_geometryDrawState.lightAttenuationLinearsLoc =
319             gl.glGetUniformLocation(m_geometryDrawState.program, "light_attenuation_linears");
320         m_geometryDrawState.lightAttenuationQuadraticsLoc =
321             gl.glGetUniformLocation(m_geometryDrawState.program, "light_attenuation_quadratics");
322 
323         m_geometryDrawState.fogModeLoc =
324             gl.glGetUniformLocation(m_geometryDrawState.program, "fog_mode");
325         m_geometryDrawState.fogDensityLoc =
326             gl.glGetUniformLocation(m_geometryDrawState.program, "fog_density");
327         m_geometryDrawState.fogStartLoc =
328             gl.glGetUniformLocation(m_geometryDrawState.program, "fog_start");
329         m_geometryDrawState.fogEndLoc =
330             gl.glGetUniformLocation(m_geometryDrawState.program, "fog_end");
331         m_geometryDrawState.fogColorLoc =
332             gl.glGetUniformLocation(m_geometryDrawState.program, "fog_color");
333 
334     }
335 
336     if (!m_geometryDrawState.vao) {
337 
338         gl.glGenBuffers(1, &m_geometryDrawState.posVbo);
339         gl.glGenBuffers(1, &m_geometryDrawState.normalVbo);
340         gl.glGenBuffers(1, &m_geometryDrawState.colorVbo);
341         gl.glGenBuffers(1, &m_geometryDrawState.pointsizeVbo);
342         gl.glGenBuffers(1, &m_geometryDrawState.texcoordVbo);
343 
344         gl.glGenVertexArrays(1, &m_geometryDrawState.vao);
345         gl.glBindVertexArray(m_geometryDrawState.vao);
346 
347         gl.glGenBuffers(1, &m_geometryDrawState.ibo);
348         gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_geometryDrawState.ibo);
349 
350         gl.glBindVertexArray(0);
351 
352         gl.glBindBuffer(GL_ARRAY_BUFFER, 0);
353         gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
354     }
355 
356     return m_geometryDrawState;
357 }
358 
getVboFor(GLenum type)359 GLuint CoreProfileEngine::getVboFor(GLenum type) {
360     switch (type) {
361     case GL_VERTEX_ARRAY:
362         return m_geometryDrawState.posVbo;
363     case GL_NORMAL_ARRAY:
364         return m_geometryDrawState.normalVbo;
365     case GL_COLOR_ARRAY:
366         return m_geometryDrawState.colorVbo;
367     case GL_POINT_SIZE_ARRAY_OES:
368         return m_geometryDrawState.pointsizeVbo;
369     case GL_TEXTURE_COORD_ARRAY:
370         return m_geometryDrawState.texcoordVbo;
371     }
372     return 0;
373 }
374 
sizeOfType(GLenum type)375 size_t CoreProfileEngine::sizeOfType(GLenum type) {
376     switch (type) {
377     case GL_BYTE:
378     case GL_UNSIGNED_BYTE:
379         return 1;
380     case GL_SHORT:
381     case GL_UNSIGNED_SHORT:
382     case GL_HALF_FLOAT_OES:
383         return 2;
384     case GL_INT:
385     case GL_UNSIGNED_INT:
386     case GL_FLOAT:
387         return 4;
388     }
389     return 4;
390 }
391 
392 template <class T>
sNeededVboCount(GLsizei indicesCount,const T * indices)393 static GLsizei sNeededVboCount(GLsizei indicesCount, const T* indices) {
394     T maxIndex = 0;
395     for (GLsizei i = 0; i < indicesCount; i++) {
396         T index = indices[i];
397         maxIndex = (index > maxIndex) ? index : maxIndex;
398     }
399     return (GLsizei)maxIndex + 1;
400 }
401 
setupArrayForDraw(GLenum arrayType,GLESpointer * p,GLint first,GLsizei count,bool isIndexed,GLenum indicesType,const GLvoid * indices)402 void CoreProfileEngine::setupArrayForDraw(
403     GLenum arrayType,
404     GLESpointer* p,
405     GLint first, GLsizei count,
406     bool isIndexed, GLenum indicesType, const GLvoid* indices) {
407 
408     auto& gl = GLEScontext::dispatcher();
409     GLint attribNum = -1;
410 
411     gl.glBindVertexArray(m_geometryDrawState.vao);
412 
413     attribNum = arrayTypeToCoreAttrib(arrayType);
414 
415     GLsizei vboCount = 0;
416 
417     if (isIndexed) {
418 
419         GLsizei indexSize = 4;
420         GLsizei indicesCount = count;
421 
422         switch (indicesType) {
423         case GL_UNSIGNED_BYTE:
424             indexSize = 1;
425             vboCount = sNeededVboCount(indicesCount, (unsigned char*)indices);
426             break;
427         case GL_UNSIGNED_SHORT:
428             indexSize = 2;
429             vboCount = sNeededVboCount(indicesCount, (uint16_t*)indices);
430             break;
431         case GL_UNSIGNED_INT:
432         default:
433             indexSize = 4;
434             vboCount = sNeededVboCount(indicesCount, (uint32_t*)indices);
435         }
436 
437         // And send the indices
438         gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_geometryDrawState.ibo);
439         gl.glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize * indicesCount, indices, GL_STREAM_DRAW);
440     } else {
441         gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
442         vboCount = count;
443     }
444 
445     if (p->isEnable()) {
446         gl.glEnableVertexAttribArray(attribNum);
447         gl.glBindBuffer(GL_ARRAY_BUFFER, getVboFor(arrayType));
448 
449         GLESConversionArrays arrs;
450 
451         bool convert = mCtx->doConvert(arrs, first, count, indicesType, indices, !isIndexed, p, arrayType);
452         ArrayData currentArr = arrs.getCurrentArray();
453 
454         GLint size = p->getSize();
455         GLenum dataType = convert ? currentArr.type : p->getType();
456         GLsizei stride = convert ? currentArr.stride : p->getStride();
457 
458         GLsizei effectiveStride =
459             stride ? stride :
460                      (size * sizeOfType(dataType));
461 
462         char* bufData = convert ? (char*)currentArr.data : (char*)p->getData();
463         uint32_t offset = first * effectiveStride;
464         uint32_t bufSize = offset + vboCount * effectiveStride;
465 
466         gl.glBufferData(GL_ARRAY_BUFFER, bufSize, bufData, GL_STREAM_DRAW);
467 
468         gl.glVertexAttribDivisor(attribNum, 0);
469         GLboolean shouldNormalize = false;
470 
471         if (arrayType == GL_COLOR_ARRAY &&
472             (dataType == GL_BYTE ||
473              dataType == GL_UNSIGNED_BYTE ||
474              dataType == GL_INT ||
475              dataType == GL_UNSIGNED_INT ||
476              dataType == GL_FIXED))
477             shouldNormalize = true;
478 
479         gl.glVertexAttribPointer(attribNum, size, dataType,
480                                  shouldNormalize ? GL_TRUE : GL_FALSE /* normalized */,
481                                  effectiveStride, nullptr /* no offset into vbo */);
482         gl.glBindBuffer(GL_ARRAY_BUFFER, 0);
483     } else {
484         if (arrayType == GL_COLOR_ARRAY ||
485             arrayType == GL_NORMAL_ARRAY ||
486             arrayType == GL_TEXTURE_COORD_ARRAY) {
487 
488             gl.glEnableVertexAttribArray(attribNum);
489             gl.glBindBuffer(GL_ARRAY_BUFFER, getVboFor(arrayType));
490 
491             GLint size;
492             std::vector<float> buffer;
493             switch (arrayType) {
494                 case GL_COLOR_ARRAY:
495                     size = 4;
496                     mCtx->getColor(count, buffer);
497                     break;
498                 case GL_NORMAL_ARRAY:
499                     size = 3;
500                     mCtx->getNormal(count, buffer);
501                     break;
502                 case GL_TEXTURE_COORD_ARRAY:
503                     size = 4;
504                     mCtx->getMultiTexCoord(count, mCtx->getActiveTextureUnit(), buffer);
505                     break;
506                 default:
507                     fprintf(stderr, "Error: Invalid array type %d.\n", arrayType);
508                     mCtx->setGLerror(GL_INVALID_OPERATION);
509                     return;
510             }
511 
512             // We need a buffer large enough to hold `count` copies of the vertex attributes provided
513             // above.
514             GLsizei bufSize = count * size * sizeof(float);
515             gl.glBufferData(GL_ARRAY_BUFFER, bufSize, buffer.data(), GL_STREAM_DRAW);
516             // Stride is set to 0 to indicate that our values are tightly packed -- the driver will
517             // do the calculation.
518             gl.glVertexAttribPointer(attribNum, size, GL_FLOAT, GL_FALSE, 0, nullptr);
519             gl.glBindBuffer(GL_ARRAY_BUFFER, 0);
520         } else {
521             gl.glDisableVertexAttribArray(attribNum);
522         }
523     }
524 
525     gl.glBindVertexArray(0);
526 }
527 
528 // API
529 
enable(GLenum cap)530 void CoreProfileEngine::enable(GLenum cap) {
531     switch (cap) {
532         case GL_TEXTURE_2D:
533         case GL_TEXTURE_CUBE_MAP_OES:
534         case GL_TEXTURE_GEN_STR_OES:
535         case GL_RESCALE_NORMAL:
536         case GL_NORMALIZE:
537         case GL_LIGHTING:
538         case GL_LIGHT0:
539         case GL_LIGHT1:
540         case GL_LIGHT2:
541         case GL_LIGHT3:
542         case GL_LIGHT4:
543         case GL_LIGHT5:
544         case GL_LIGHT6:
545         case GL_LIGHT7:
546         case GL_COLOR_MATERIAL:
547         case GL_FOG:
548         case GL_POINT_SMOOTH:
549         case GL_ALPHA_TEST:
550             return;
551         default:
552             break;
553     }
554 
555     auto& gl = GLEScontext::dispatcher();
556     gl.glEnable(cap);
557 }
558 
disable(GLenum cap)559 void CoreProfileEngine::disable(GLenum cap) {
560     switch (cap) {
561         case GL_TEXTURE_2D:
562         case GL_TEXTURE_CUBE_MAP_OES:
563         case GL_TEXTURE_GEN_STR_OES:
564         case GL_RESCALE_NORMAL:
565         case GL_NORMALIZE:
566         case GL_LIGHTING:
567         case GL_LIGHT0:
568         case GL_LIGHT1:
569         case GL_LIGHT2:
570         case GL_LIGHT3:
571         case GL_LIGHT4:
572         case GL_LIGHT5:
573         case GL_LIGHT6:
574         case GL_LIGHT7:
575         case GL_COLOR_MATERIAL:
576         case GL_FOG:
577         case GL_POINT_SMOOTH:
578         case GL_ALPHA_TEST:
579             return;
580         default:
581             break;
582     }
583 
584     auto& gl = GLEScontext::dispatcher();
585     gl.glDisable(cap);
586 }
587 
shadeModel(GLenum mode)588 void CoreProfileEngine::shadeModel(GLenum mode) {
589     // no-op
590 }
591 
matrixMode(GLenum mode)592 void CoreProfileEngine::matrixMode(GLenum mode) {
593     // no-op
594 }
595 
loadIdentity()596 void CoreProfileEngine::loadIdentity() {
597     // no-op
598 }
599 
loadMatrixf(const GLfloat * m)600 void CoreProfileEngine::loadMatrixf(const GLfloat* m) {
601     // no-op
602 }
603 
pushMatrix()604 void CoreProfileEngine::pushMatrix() {
605     // no-op
606 }
607 
popMatrix()608 void CoreProfileEngine::popMatrix() {
609     // no-op
610 }
611 
multMatrixf(const GLfloat * m)612 void CoreProfileEngine::multMatrixf(const GLfloat* m) {
613     // no-op
614 }
615 
orthof(GLfloat left,GLfloat right,GLfloat bottom,GLfloat top,GLfloat zNear,GLfloat zFar)616 void CoreProfileEngine::orthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) {
617     // no-op
618 }
619 
frustumf(GLfloat left,GLfloat right,GLfloat bottom,GLfloat top,GLfloat zNear,GLfloat zFar)620 void CoreProfileEngine::frustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) {
621     // no-op
622 }
623 
texEnvf(GLenum target,GLenum pname,GLfloat param)624 void CoreProfileEngine::texEnvf(GLenum target, GLenum pname, GLfloat param) {
625     // no-op
626 }
627 
texEnvfv(GLenum target,GLenum pname,const GLfloat * params)628 void CoreProfileEngine::texEnvfv(GLenum target, GLenum pname, const GLfloat* params) {
629     // no-op
630 }
631 
texEnvi(GLenum target,GLenum pname,GLint param)632 void CoreProfileEngine::texEnvi(GLenum target, GLenum pname, GLint param) {
633     // no-op
634 }
635 
texEnviv(GLenum target,GLenum pname,const GLint * params)636 void CoreProfileEngine::texEnviv(GLenum target, GLenum pname, const GLint* params) {
637     // no-op
638 }
639 
getTexEnvfv(GLenum env,GLenum pname,GLfloat * params)640 void CoreProfileEngine::getTexEnvfv(GLenum env, GLenum pname, GLfloat* params) {
641     // no-op
642 }
643 
getTexEnviv(GLenum env,GLenum pname,GLint * params)644 void CoreProfileEngine::getTexEnviv(GLenum env, GLenum pname, GLint* params) {
645     // no-op
646 }
647 
texGenf(GLenum coord,GLenum pname,GLfloat param)648 void CoreProfileEngine::texGenf(GLenum coord, GLenum pname, GLfloat param) {
649     // no-op
650 }
651 
texGenfv(GLenum coord,GLenum pname,const GLfloat * params)652 void CoreProfileEngine::texGenfv(GLenum coord, GLenum pname, const GLfloat* params) {
653     // no-op
654 }
655 
texGeni(GLenum coord,GLenum pname,GLint param)656 void CoreProfileEngine::texGeni(GLenum coord, GLenum pname, GLint param) {
657     // no-op
658 }
659 
texGeniv(GLenum coord,GLenum pname,const GLint * params)660 void CoreProfileEngine::texGeniv(GLenum coord, GLenum pname, const GLint* params) {
661     // no-op
662 }
663 
getTexGeniv(GLenum coord,GLenum pname,GLint * params)664 void CoreProfileEngine::getTexGeniv(GLenum coord, GLenum pname, GLint* params) {
665     // no-op
666 }
667 
getTexGenfv(GLenum coord,GLenum pname,GLfloat * params)668 void CoreProfileEngine::getTexGenfv(GLenum coord, GLenum pname, GLfloat* params) {
669     // no-op
670 }
671 
enableClientState(GLenum clientState)672 void CoreProfileEngine::enableClientState(GLenum clientState) {
673     // no-op
674 }
675 
disableClientState(GLenum clientState)676 void CoreProfileEngine::disableClientState(GLenum clientState) {
677     // no-op
678 }
679 
drawTexOES(float x,float y,float z,float width,float height)680 void CoreProfileEngine::drawTexOES(float x, float y, float z, float width, float height) {
681     auto& gl = GLEScontext::dispatcher();
682 
683     // get viewport
684     GLint viewport[4] = {};
685     gl.glGetIntegerv(GL_VIEWPORT,viewport);
686 
687     // track previous vbo/ibo
688     GLuint prev_vbo;
689     GLuint prev_ibo;
690     gl.glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&prev_vbo);
691     gl.glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint*)&prev_ibo);
692 
693     // compile shaders, generate vbo/ibo if not done already
694     CoreProfileEngine::DrawTexOESCoreState drawTexState =
695         getDrawTexOESCoreState();
696 
697     GLuint prog = drawTexState.program;
698     GLuint vbo = drawTexState.vbo;
699     GLuint vao = drawTexState.vao;
700 
701     gl.glUseProgram(prog);
702 
703     gl.glBindVertexArray(vao);
704     // This is not strictly needed, but Swiftshader indirect VAO
705     // can forget its ELEMENT_ARRAY_BUFFER binding.
706     gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_drawTexOESCoreState.ibo);
707 
708     GLint samplerLoc = gl.glGetUniformLocation(prog, "tex_sampler");
709 
710     // Compute screen coordinates for our texture.
711     // Recenter, rescale. (e.g., [0, 0, 1080, 1920] -> [-1, -1, 1, 1])
712     float xNdc = 2.0f * (float)(x - viewport[0] - viewport[2] / 2) / (float)viewport[2];
713     float yNdc = 2.0f * (float)(y - viewport[1] - viewport[3] / 2) / (float)viewport[3];
714     float wNdc = 2.0f * (float)width / (float)viewport[2];
715     float hNdc = 2.0f * (float)height / (float)viewport[3];
716     z = z >= 1.0f ? 1.0f : z;
717     z = z <= 0.0f ? 0.0f : z;
718     float zNdc = z * 2.0f - 1.0f;
719 
720     for (int i = 0; i < mCtx->getMaxTexUnits(); i++) {
721         if (mCtx->isTextureUnitEnabled(GL_TEXTURE0 + i)) {
722             GLuint bindedTex = mCtx->getBindedTexture(GL_TEXTURE0 + i, GL_TEXTURE_2D);
723             ObjectLocalName tex = mCtx->getTextureLocalName(GL_TEXTURE_2D, bindedTex);
724 
725             auto objData = mCtx->shareGroup()->getObjectData(NamedObjectType::TEXTURE, tex);
726 
727             if (objData) {
728                 TextureData* texData = (TextureData*)objData;
729 
730                 float texCropX = (float)(texData->crop_rect[0]);
731                 float texCropY = (float)(texData->crop_rect[1]);
732 
733                 float texCropW = (float)(texData->crop_rect[2]);
734                 float texCropH = (float)(texData->crop_rect[3]);
735 
736                 float texW = (float)(texData->width);
737                 float texH = (float)(texData->height);
738 
739                 // Now we know the vertex attributes (pos, texcoord).
740                 // Our vertex attributes are formatted with interleaved
741                 // position and texture coordinate:
742                 float vertexAttrs[] = {
743                     xNdc, yNdc, zNdc,
744                     texCropX / texW, texCropY / texH,
745 
746                     xNdc + wNdc, yNdc, zNdc,
747                     (texCropX + texCropW) / texW, texCropY / texH,
748 
749                     xNdc + wNdc, yNdc + hNdc, zNdc,
750                     (texCropX + texCropW) / texW, (texCropY + texCropH) / texH,
751 
752                     xNdc, yNdc + hNdc, zNdc,
753                     texCropX / texW, (texCropY + texCropH) / texH,
754                 };
755 
756                 gl.glBindBuffer(GL_ARRAY_BUFFER, vbo);
757                 gl.glBufferData(GL_ARRAY_BUFFER, sizeof(vertexAttrs),
758                                 vertexAttrs, GL_STREAM_DRAW);
759             }
760 
761             gl.glActiveTexture(GL_TEXTURE0 + i);
762             gl.glUniform1i(samplerLoc, i);
763             gl.glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
764         }
765     }
766 
767     gl.glBindVertexArray(0);
768 
769     gl.glUseProgram(0);
770 
771     gl.glBindBuffer(GL_ARRAY_BUFFER, prev_vbo);
772     gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prev_ibo);
773 }
774 
rotatef(float angle,float x,float y,float z)775 void CoreProfileEngine::rotatef(float angle, float x, float y, float z) {
776     // no-op
777 }
778 
scalef(float x,float y,float z)779 void CoreProfileEngine::scalef(float x, float y, float z) {
780     // no-op
781 }
782 
translatef(float x,float y,float z)783 void CoreProfileEngine::translatef(float x, float y, float z) {
784     // no-op
785 }
786 
color4f(GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)787 void CoreProfileEngine::color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
788     // no-op
789 }
790 
color4ub(GLubyte red,GLubyte green,GLubyte blue,GLubyte alpha)791 void CoreProfileEngine::color4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {
792     // no-op
793 }
794 
activeTexture(GLenum unit)795 void CoreProfileEngine::activeTexture(GLenum unit) {
796     // Use 2 texture image units for each texture unit of GLES1.
797     // This allows us to simultaneously use GL_TEXTURE_2D
798     // and GL_TEXTURE_CUBE_MAP with the same texture unit through
799     // using different samplers for the image units.
800     GLEScontext::dispatcher().glActiveTexture(
801         GL_TEXTURE0 + mCtx->getActiveTextureUnit() * 2);
802 }
803 
clientActiveTexture(GLenum unit)804 void CoreProfileEngine::clientActiveTexture(GLenum unit) {
805     GLEScontext::dispatcher().glActiveTexture(
806         GL_TEXTURE0 + mCtx->getActiveTextureUnit() * 2);
807 }
808 
809 
preDrawTextureUnitEmulation()810 void CoreProfileEngine::preDrawTextureUnitEmulation() {
811     auto& gl = GLEScontext::dispatcher();
812     unsigned int currTextureUnit = mCtx->getActiveTextureUnit();
813 
814     gl.glUniform1i(m_geometryDrawState.enableTextureLoc,
815                    mCtx->isEnabled(GL_TEXTURE_2D) &&
816                    mCtx->isArrEnabled(GL_TEXTURE_COORD_ARRAY));
817 
818     gl.glUniform1i(m_geometryDrawState.textureSamplerLoc, currTextureUnit * 2);
819     gl.glUniform1i(m_geometryDrawState.textureCubeSamplerLoc, currTextureUnit * 2 + 1);
820 
821     if (auto cubeMapTex = mCtx->getBindedTexture(currTextureUnit + GL_TEXTURE0, GL_TEXTURE_CUBE_MAP)) {
822         GLuint cubeMapTexGlobal = mCtx->shareGroup()->getGlobalName(
823                                       NamedObjectType::TEXTURE, cubeMapTex);
824         gl.glActiveTexture(GL_TEXTURE0 + currTextureUnit * 2);
825         gl.glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
826         gl.glActiveTexture(GL_TEXTURE0 + currTextureUnit * 2 + 1);
827         gl.glBindTexture(GL_TEXTURE_CUBE_MAP, cubeMapTexGlobal);
828         gl.glActiveTexture(GL_TEXTURE0 + currTextureUnit * 2);
829     }
830 
831     GLenum textureGenMode = mCtx->getTextureGenMode();
832     if (textureGenMode == GL_REFLECTION_MAP_OES) {
833         gl.glUniform1i(m_geometryDrawState.enableTextureLoc, 1);
834         gl.glUniform1i(m_geometryDrawState.enableReflectionMapLoc, 1);
835     } else {
836         gl.glUniform1i(m_geometryDrawState.enableReflectionMapLoc, 0);
837     }
838 
839     auto bindedTex = mCtx->getBindedTexture(GL_TEXTURE_2D);
840     ObjectLocalName tex = mCtx->getTextureLocalName(GL_TEXTURE_2D, bindedTex);
841     auto objData = mCtx->shareGroup()->getObjectData(NamedObjectType::TEXTURE, tex);
842 
843     if (objData) {
844         TextureData* texData = (TextureData*)objData;
845         gl.glUniform1i(m_geometryDrawState.textureFormatLoc, texData->internalFormat);
846     } else {
847         gl.glUniform1i(m_geometryDrawState.textureFormatLoc, GL_RGBA);
848     }
849 
850     gl.glUniform1i(m_geometryDrawState.enableLightingLoc, 0);
851     gl.glUniform1i(m_geometryDrawState.textureEnvModeLoc, mCtx->getTextureEnvMode());
852 }
853 
postDrawTextureUnitEmulation()854 void CoreProfileEngine::postDrawTextureUnitEmulation() {
855     auto& gl = GLEScontext::dispatcher();
856     unsigned int currTextureUnit = mCtx->getActiveTextureUnit();
857 
858     GLuint cubeMapTex = mCtx->getBindedTexture(currTextureUnit + GL_TEXTURE0, GL_TEXTURE_CUBE_MAP);
859 
860     if (cubeMapTex) {
861         GLuint cubeMapTexGlobal = mCtx->shareGroup()->getGlobalName(
862                                       NamedObjectType::TEXTURE, cubeMapTex);
863         gl.glActiveTexture(GL_TEXTURE0 + currTextureUnit * 2);
864         gl.glBindTexture(GL_TEXTURE_CUBE_MAP, cubeMapTexGlobal);
865         gl.glActiveTexture(GL_TEXTURE0 + currTextureUnit * 2 + 1);
866         gl.glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
867         gl.glActiveTexture(GL_TEXTURE0 + currTextureUnit * 2);
868     }
869 }
870 
preDrawVertexSetup()871 void CoreProfileEngine::preDrawVertexSetup() {
872     auto& gl = GLEScontext::dispatcher();
873 
874     glm::mat4 currProjMatrix = mCtx->getProjMatrix();
875     glm::mat4 currModelviewMatrix = mCtx->getModelviewMatrix();
876     glm::mat4 currTextureMatrix = mCtx->getTextureMatrix();
877     glm::mat4 currModelviewMatrixInvTr = glm::inverseTranspose(currModelviewMatrix);
878 
879     gl.glBindVertexArray(m_geometryDrawState.vao);
880 
881     gl.glUseProgram(mCtx->getShadeModel() == GL_FLAT ?
882                     m_geometryDrawState.programFlat :
883                     m_geometryDrawState.program);
884     gl.glUniformMatrix4fv(m_geometryDrawState.projMatrixLoc, 1, GL_FALSE, glm::value_ptr(currProjMatrix));
885     gl.glUniformMatrix4fv(m_geometryDrawState.modelviewMatrixLoc, 1, GL_FALSE, glm::value_ptr(currModelviewMatrix));
886     gl.glUniformMatrix4fv(m_geometryDrawState.modelviewInvTrLoc, 1, GL_FALSE, glm::value_ptr(currModelviewMatrixInvTr));
887     gl.glUniformMatrix4fv(m_geometryDrawState.textureMatrixLoc, 1, GL_FALSE, glm::value_ptr(currTextureMatrix));
888 }
889 
postDrawVertexSetup()890 void CoreProfileEngine::postDrawVertexSetup() {
891     auto& gl = GLEScontext::dispatcher();
892 
893     gl.glBindVertexArray(0);
894 }
895 
setupLighting()896 void CoreProfileEngine::setupLighting() {
897     auto& gl = GLEScontext::dispatcher();
898 
899     gl.glUniform1i(m_geometryDrawState.enableLightingLoc,
900                    mCtx->isEnabled(GL_LIGHTING));
901     gl.glUniform1i(m_geometryDrawState.enableRescaleNormalLoc,
902                    mCtx->isEnabled(GL_RESCALE_NORMAL));
903     gl.glUniform1i(m_geometryDrawState.enableNormalizeLoc,
904                    mCtx->isEnabled(GL_NORMALIZE));
905     gl.glUniform1i(m_geometryDrawState.enableColorMaterialLoc,
906                    mCtx->isEnabled(GL_COLOR_MATERIAL));
907 
908     const auto& material = mCtx->getMaterialInfo();
909 
910     gl.glUniform4fv(m_geometryDrawState.materialAmbientLoc, 1, material.ambient);
911     gl.glUniform4fv(m_geometryDrawState.materialDiffuseLoc, 1, material.diffuse);
912     gl.glUniform4fv(m_geometryDrawState.materialSpecularLoc, 1, material.specular);
913     gl.glUniform4fv(m_geometryDrawState.materialEmissiveLoc, 1, material.emissive);
914     gl.glUniform1f(m_geometryDrawState.materialSpecularExponentLoc, material.specularExponent);
915 
916     const auto& lightModel = mCtx->getLightModelInfo();
917 
918     gl.glUniform4fv(m_geometryDrawState.lightModelSceneAmbientLoc, 1, lightModel.color);
919     gl.glUniform1i(m_geometryDrawState.lightModelTwoSidedLoc, lightModel.twoSided);
920 
921     assert(kMaxLights == GLEScmContext::kMaxLights);
922 
923     for (int i = 0; i < GLEScmContext::kMaxLights; i++) {
924         m_lightingBuffer.lightEnables[i] = mCtx->isEnabled(GL_LIGHT0 + i);
925         const auto& light = mCtx->getLightInfo(i);
926         memcpy(m_lightingBuffer.lightAmbients + 4 * i, &light.ambient, 4 * sizeof(GLfloat));
927         memcpy(m_lightingBuffer.lightDiffuses + 4 * i, &light.diffuse, 4 * sizeof(GLfloat));
928         memcpy(m_lightingBuffer.lightSpeculars + 4 * i, &light.specular, 4 * sizeof(GLfloat));
929         memcpy(m_lightingBuffer.lightPositions + 4 * i, &light.position, 4 * sizeof(GLfloat));
930         memcpy(m_lightingBuffer.lightDirections + 3 * i, &light.direction, 3 * sizeof(GLfloat));
931         m_lightingBuffer.spotlightExponents[i] = light.spotlightExponent;
932         m_lightingBuffer.spotlightCutoffAngles[i] = light.spotlightCutoffAngle;
933         m_lightingBuffer.attenuationConsts[i] = light.attenuationConst;
934         m_lightingBuffer.attenuationLinears[i] = light.attenuationLinear;
935         m_lightingBuffer.attenuationQuadratics[i] = light.attenuationQuadratic;
936     }
937 
938     gl.glUniform1iv(m_geometryDrawState.lightEnablesLoc, GLEScmContext::kMaxLights, m_lightingBuffer.lightEnables);
939     gl.glUniform4fv(m_geometryDrawState.lightAmbientsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.lightAmbients);
940     gl.glUniform4fv(m_geometryDrawState.lightDiffusesLoc, GLEScmContext::kMaxLights, m_lightingBuffer.lightDiffuses);
941     gl.glUniform4fv(m_geometryDrawState.lightSpecularsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.lightSpeculars);
942     gl.glUniform4fv(m_geometryDrawState.lightPositionsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.lightPositions);
943     gl.glUniform3fv(m_geometryDrawState.lightDirectionsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.lightDirections);
944     gl.glUniform1fv(m_geometryDrawState.lightSpotlightExponentsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.spotlightExponents);
945     gl.glUniform1fv(m_geometryDrawState.lightSpotlightCutoffAnglesLoc, GLEScmContext::kMaxLights, m_lightingBuffer.spotlightCutoffAngles);
946     gl.glUniform1fv(m_geometryDrawState.lightAttenuationConstsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.attenuationConsts);
947     gl.glUniform1fv(m_geometryDrawState.lightAttenuationLinearsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.attenuationLinears);
948     gl.glUniform1fv(m_geometryDrawState.lightAttenuationQuadraticsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.attenuationQuadratics);
949 }
950 
setupFog()951 void CoreProfileEngine::setupFog() {
952     auto& gl = GLEScontext::dispatcher();
953 
954     gl.glUniform1i(m_geometryDrawState.enableFogLoc,
955                    mCtx->isEnabled(GL_FOG));
956 
957     const auto& fogInfo = mCtx->getFogInfo();
958 
959     gl.glUniform1i(m_geometryDrawState.fogModeLoc, fogInfo.mode);
960     gl.glUniform1f(m_geometryDrawState.fogDensityLoc, fogInfo.density);
961     gl.glUniform1f(m_geometryDrawState.fogStartLoc, fogInfo.start);
962     gl.glUniform1f(m_geometryDrawState.fogEndLoc, fogInfo.end);
963 
964     gl.glUniform4fv(m_geometryDrawState.fogColorLoc, 1, fogInfo.color);
965 }
966 
drawArrays(GLenum type,GLint first,GLsizei count)967 void CoreProfileEngine::drawArrays(GLenum type, GLint first, GLsizei count) {
968     auto& gl = GLEScontext::dispatcher();
969 
970     preDrawVertexSetup();
971     preDrawTextureUnitEmulation();
972 
973     setupLighting();
974     setupFog();
975 
976     gl.glDrawArrays(type, first, count);
977 
978     postDrawVertexSetup();
979     postDrawTextureUnitEmulation();
980 }
981 
drawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)982 void CoreProfileEngine::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) {
983     auto& gl = GLEScontext::dispatcher();
984 
985     preDrawVertexSetup();
986     preDrawTextureUnitEmulation();
987 
988     setupLighting();
989     setupFog();
990 
991     gl.glDrawElements(mode, count, type, (GLvoid*)0);
992 
993     postDrawVertexSetup();
994     postDrawTextureUnitEmulation();
995 }
996