• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/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             // Use vertex attrib divisor to avoid creating a buffer
492             // that repeats the same value for as many verts.
493 
494             GLint size = 4;
495             GLenum dataType = GL_FLOAT;
496             std::vector<float> data(4, 0.f);
497             switch (arrayType) {
498                 case GL_VERTEX_ARRAY:
499                     size = 4;
500                     fprintf(stderr, "Error: GLES1 does not support immediate vertices\n");
501                     mCtx->setGLerror(GL_INVALID_OPERATION);
502                     break;
503                 case GL_COLOR_ARRAY:
504                     size = 4;
505                     data = mCtx->getColor();
506                     break;
507                 case GL_NORMAL_ARRAY:
508                     size = 3;
509                     data = mCtx->getNormal();
510                     break;
511                 case GL_POINT_SIZE_ARRAY_OES:
512                     data = mCtx->getColor();
513                     break;
514                 case GL_TEXTURE_COORD_ARRAY:
515                     size = 4;
516                     data = mCtx->getMultiTexCoord(mCtx->getActiveTextureUnit());
517                     break;
518                 default:
519                     break;
520             }
521             GLsizei stride = size * sizeof(float);
522             gl.glBufferData(GL_ARRAY_BUFFER, stride, (GLvoid*)&data[0], GL_STREAM_DRAW);
523             gl.glVertexAttribDivisor(attribNum, 1);
524             gl.glVertexAttribPointer(attribNum, size, dataType,
525                                      GL_FALSE /* normalized */,
526                                      stride, nullptr /* no offset into vbo */);
527             gl.glBindBuffer(GL_ARRAY_BUFFER, 0);
528         } else {
529             gl.glDisableVertexAttribArray(attribNum);
530         }
531     }
532 
533     gl.glBindVertexArray(0);
534 }
535 
536 // API
537 
enable(GLenum cap)538 void CoreProfileEngine::enable(GLenum cap) {
539     switch (cap) {
540         case GL_TEXTURE_2D:
541         case GL_TEXTURE_CUBE_MAP_OES:
542         case GL_TEXTURE_GEN_STR_OES:
543         case GL_RESCALE_NORMAL:
544         case GL_NORMALIZE:
545         case GL_LIGHTING:
546         case GL_LIGHT0:
547         case GL_LIGHT1:
548         case GL_LIGHT2:
549         case GL_LIGHT3:
550         case GL_LIGHT4:
551         case GL_LIGHT5:
552         case GL_LIGHT6:
553         case GL_LIGHT7:
554         case GL_COLOR_MATERIAL:
555         case GL_FOG:
556         case GL_POINT_SMOOTH:
557         case GL_ALPHA_TEST:
558             return;
559         default:
560             break;
561     }
562 
563     auto& gl = GLEScontext::dispatcher();
564     gl.glEnable(cap);
565 }
566 
disable(GLenum cap)567 void CoreProfileEngine::disable(GLenum cap) {
568     switch (cap) {
569         case GL_TEXTURE_2D:
570         case GL_TEXTURE_CUBE_MAP_OES:
571         case GL_TEXTURE_GEN_STR_OES:
572         case GL_RESCALE_NORMAL:
573         case GL_NORMALIZE:
574         case GL_LIGHTING:
575         case GL_LIGHT0:
576         case GL_LIGHT1:
577         case GL_LIGHT2:
578         case GL_LIGHT3:
579         case GL_LIGHT4:
580         case GL_LIGHT5:
581         case GL_LIGHT6:
582         case GL_LIGHT7:
583         case GL_COLOR_MATERIAL:
584         case GL_FOG:
585         case GL_POINT_SMOOTH:
586         case GL_ALPHA_TEST:
587             return;
588         default:
589             break;
590     }
591 
592     auto& gl = GLEScontext::dispatcher();
593     gl.glDisable(cap);
594 }
595 
shadeModel(GLenum mode)596 void CoreProfileEngine::shadeModel(GLenum mode) {
597     // no-op
598 }
599 
matrixMode(GLenum mode)600 void CoreProfileEngine::matrixMode(GLenum mode) {
601     // no-op
602 }
603 
loadIdentity()604 void CoreProfileEngine::loadIdentity() {
605     // no-op
606 }
607 
loadMatrixf(const GLfloat * m)608 void CoreProfileEngine::loadMatrixf(const GLfloat* m) {
609     // no-op
610 }
611 
pushMatrix()612 void CoreProfileEngine::pushMatrix() {
613     // no-op
614 }
615 
popMatrix()616 void CoreProfileEngine::popMatrix() {
617     // no-op
618 }
619 
multMatrixf(const GLfloat * m)620 void CoreProfileEngine::multMatrixf(const GLfloat* m) {
621     // no-op
622 }
623 
orthof(GLfloat left,GLfloat right,GLfloat bottom,GLfloat top,GLfloat zNear,GLfloat zFar)624 void CoreProfileEngine::orthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) {
625     // no-op
626 }
627 
frustumf(GLfloat left,GLfloat right,GLfloat bottom,GLfloat top,GLfloat zNear,GLfloat zFar)628 void CoreProfileEngine::frustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) {
629     // no-op
630 }
631 
texEnvf(GLenum target,GLenum pname,GLfloat param)632 void CoreProfileEngine::texEnvf(GLenum target, GLenum pname, GLfloat param) {
633     // no-op
634 }
635 
texEnvfv(GLenum target,GLenum pname,const GLfloat * params)636 void CoreProfileEngine::texEnvfv(GLenum target, GLenum pname, const GLfloat* params) {
637     // no-op
638 }
639 
texEnvi(GLenum target,GLenum pname,GLint param)640 void CoreProfileEngine::texEnvi(GLenum target, GLenum pname, GLint param) {
641     // no-op
642 }
643 
texEnviv(GLenum target,GLenum pname,const GLint * params)644 void CoreProfileEngine::texEnviv(GLenum target, GLenum pname, const GLint* params) {
645     // no-op
646 }
647 
getTexEnvfv(GLenum env,GLenum pname,GLfloat * params)648 void CoreProfileEngine::getTexEnvfv(GLenum env, GLenum pname, GLfloat* params) {
649     // no-op
650 }
651 
getTexEnviv(GLenum env,GLenum pname,GLint * params)652 void CoreProfileEngine::getTexEnviv(GLenum env, GLenum pname, GLint* params) {
653     // no-op
654 }
655 
texGenf(GLenum coord,GLenum pname,GLfloat param)656 void CoreProfileEngine::texGenf(GLenum coord, GLenum pname, GLfloat param) {
657     // no-op
658 }
659 
texGenfv(GLenum coord,GLenum pname,const GLfloat * params)660 void CoreProfileEngine::texGenfv(GLenum coord, GLenum pname, const GLfloat* params) {
661     // no-op
662 }
663 
texGeni(GLenum coord,GLenum pname,GLint param)664 void CoreProfileEngine::texGeni(GLenum coord, GLenum pname, GLint param) {
665     // no-op
666 }
667 
texGeniv(GLenum coord,GLenum pname,const GLint * params)668 void CoreProfileEngine::texGeniv(GLenum coord, GLenum pname, const GLint* params) {
669     // no-op
670 }
671 
getTexGeniv(GLenum coord,GLenum pname,GLint * params)672 void CoreProfileEngine::getTexGeniv(GLenum coord, GLenum pname, GLint* params) {
673     // no-op
674 }
675 
getTexGenfv(GLenum coord,GLenum pname,GLfloat * params)676 void CoreProfileEngine::getTexGenfv(GLenum coord, GLenum pname, GLfloat* params) {
677     // no-op
678 }
679 
enableClientState(GLenum clientState)680 void CoreProfileEngine::enableClientState(GLenum clientState) {
681     // no-op
682 }
683 
disableClientState(GLenum clientState)684 void CoreProfileEngine::disableClientState(GLenum clientState) {
685     // no-op
686 }
687 
drawTexOES(float x,float y,float z,float width,float height)688 void CoreProfileEngine::drawTexOES(float x, float y, float z, float width, float height) {
689     auto& gl = GLEScontext::dispatcher();
690 
691     // get viewport
692     GLint viewport[4] = {};
693     gl.glGetIntegerv(GL_VIEWPORT,viewport);
694 
695     // track previous vbo/ibo
696     GLuint prev_vbo;
697     GLuint prev_ibo;
698     gl.glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&prev_vbo);
699     gl.glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint*)&prev_ibo);
700 
701     // compile shaders, generate vbo/ibo if not done already
702     CoreProfileEngine::DrawTexOESCoreState drawTexState =
703         getDrawTexOESCoreState();
704 
705     GLuint prog = drawTexState.program;
706     GLuint vbo = drawTexState.vbo;
707     GLuint vao = drawTexState.vao;
708 
709     gl.glUseProgram(prog);
710 
711     gl.glBindVertexArray(vao);
712     // This is not strictly needed, but Swiftshader indirect VAO
713     // can forget its ELEMENT_ARRAY_BUFFER binding.
714     gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_drawTexOESCoreState.ibo);
715 
716     GLint samplerLoc = gl.glGetUniformLocation(prog, "tex_sampler");
717 
718     // Compute screen coordinates for our texture.
719     // Recenter, rescale. (e.g., [0, 0, 1080, 1920] -> [-1, -1, 1, 1])
720     float xNdc = 2.0f * (float)(x - viewport[0] - viewport[2] / 2) / (float)viewport[2];
721     float yNdc = 2.0f * (float)(y - viewport[1] - viewport[3] / 2) / (float)viewport[3];
722     float wNdc = 2.0f * (float)width / (float)viewport[2];
723     float hNdc = 2.0f * (float)height / (float)viewport[3];
724     z = z >= 1.0f ? 1.0f : z;
725     z = z <= 0.0f ? 0.0f : z;
726     float zNdc = z * 2.0f - 1.0f;
727 
728     for (int i = 0; i < mCtx->getMaxTexUnits(); i++) {
729         if (mCtx->isTextureUnitEnabled(GL_TEXTURE0 + i)) {
730             GLuint bindedTex = mCtx->getBindedTexture(GL_TEXTURE0 + i, GL_TEXTURE_2D);
731             ObjectLocalName tex = mCtx->getTextureLocalName(GL_TEXTURE_2D, bindedTex);
732 
733             auto objData = mCtx->shareGroup()->getObjectData(NamedObjectType::TEXTURE, tex);
734 
735             if (objData) {
736                 TextureData* texData = (TextureData*)objData;
737 
738                 float texCropX = (float)(texData->crop_rect[0]);
739                 float texCropY = (float)(texData->crop_rect[1]);
740 
741                 float texCropW = (float)(texData->crop_rect[2]);
742                 float texCropH = (float)(texData->crop_rect[3]);
743 
744                 float texW = (float)(texData->width);
745                 float texH = (float)(texData->height);
746 
747                 // Now we know the vertex attributes (pos, texcoord).
748                 // Our vertex attributes are formatted with interleaved
749                 // position and texture coordinate:
750                 float vertexAttrs[] = {
751                     xNdc, yNdc, zNdc,
752                     texCropX / texW, texCropY / texH,
753 
754                     xNdc + wNdc, yNdc, zNdc,
755                     (texCropX + texCropW) / texW, texCropY / texH,
756 
757                     xNdc + wNdc, yNdc + hNdc, zNdc,
758                     (texCropX + texCropW) / texW, (texCropY + texCropH) / texH,
759 
760                     xNdc, yNdc + hNdc, zNdc,
761                     texCropX / texW, (texCropY + texCropH) / texH,
762                 };
763 
764                 gl.glBindBuffer(GL_ARRAY_BUFFER, vbo);
765                 gl.glBufferData(GL_ARRAY_BUFFER, sizeof(vertexAttrs),
766                                 vertexAttrs, GL_STREAM_DRAW);
767             }
768 
769             gl.glActiveTexture(GL_TEXTURE0 + i);
770             gl.glUniform1i(samplerLoc, i);
771             gl.glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
772         }
773     }
774 
775     gl.glBindVertexArray(0);
776 
777     gl.glUseProgram(0);
778 
779     gl.glBindBuffer(GL_ARRAY_BUFFER, prev_vbo);
780     gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prev_ibo);
781 }
782 
rotatef(float angle,float x,float y,float z)783 void CoreProfileEngine::rotatef(float angle, float x, float y, float z) {
784     // no-op
785 }
786 
scalef(float x,float y,float z)787 void CoreProfileEngine::scalef(float x, float y, float z) {
788     // no-op
789 }
790 
translatef(float x,float y,float z)791 void CoreProfileEngine::translatef(float x, float y, float z) {
792     // no-op
793 }
794 
color4f(GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)795 void CoreProfileEngine::color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
796     // no-op
797 }
798 
color4ub(GLubyte red,GLubyte green,GLubyte blue,GLubyte alpha)799 void CoreProfileEngine::color4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {
800     // no-op
801 }
802 
activeTexture(GLenum unit)803 void CoreProfileEngine::activeTexture(GLenum unit) {
804     // Use 2 texture image units for each texture unit of GLES1.
805     // This allows us to simultaneously use GL_TEXTURE_2D
806     // and GL_TEXTURE_CUBE_MAP with the same texture unit through
807     // using different samplers for the image units.
808     GLEScontext::dispatcher().glActiveTexture(
809         GL_TEXTURE0 + mCtx->getActiveTextureUnit() * 2);
810 }
811 
clientActiveTexture(GLenum unit)812 void CoreProfileEngine::clientActiveTexture(GLenum unit) {
813     GLEScontext::dispatcher().glActiveTexture(
814         GL_TEXTURE0 + mCtx->getActiveTextureUnit() * 2);
815 }
816 
817 
preDrawTextureUnitEmulation()818 void CoreProfileEngine::preDrawTextureUnitEmulation() {
819     auto& gl = GLEScontext::dispatcher();
820     unsigned int currTextureUnit = mCtx->getActiveTextureUnit();
821 
822     gl.glUniform1i(m_geometryDrawState.enableTextureLoc,
823                    mCtx->isEnabled(GL_TEXTURE_2D) &&
824                    mCtx->isArrEnabled(GL_TEXTURE_COORD_ARRAY));
825 
826     gl.glUniform1i(m_geometryDrawState.textureSamplerLoc, currTextureUnit * 2);
827     gl.glUniform1i(m_geometryDrawState.textureCubeSamplerLoc, currTextureUnit * 2 + 1);
828 
829     if (auto cubeMapTex = mCtx->getBindedTexture(currTextureUnit + GL_TEXTURE0, GL_TEXTURE_CUBE_MAP)) {
830         GLuint cubeMapTexGlobal = mCtx->shareGroup()->getGlobalName(
831                                       NamedObjectType::TEXTURE, cubeMapTex);
832         gl.glActiveTexture(GL_TEXTURE0 + currTextureUnit * 2);
833         gl.glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
834         gl.glActiveTexture(GL_TEXTURE0 + currTextureUnit * 2 + 1);
835         gl.glBindTexture(GL_TEXTURE_CUBE_MAP, cubeMapTexGlobal);
836         gl.glActiveTexture(GL_TEXTURE0 + currTextureUnit * 2);
837     }
838 
839     GLenum textureGenMode = mCtx->getTextureGenMode();
840     if (textureGenMode == GL_REFLECTION_MAP_OES) {
841         gl.glUniform1i(m_geometryDrawState.enableTextureLoc, 1);
842         gl.glUniform1i(m_geometryDrawState.enableReflectionMapLoc, 1);
843     } else {
844         gl.glUniform1i(m_geometryDrawState.enableReflectionMapLoc, 0);
845     }
846 
847     auto bindedTex = mCtx->getBindedTexture(GL_TEXTURE_2D);
848     ObjectLocalName tex = mCtx->getTextureLocalName(GL_TEXTURE_2D, bindedTex);
849     auto objData = mCtx->shareGroup()->getObjectData(NamedObjectType::TEXTURE, tex);
850 
851     if (objData) {
852         TextureData* texData = (TextureData*)objData;
853         gl.glUniform1i(m_geometryDrawState.textureFormatLoc, texData->internalFormat);
854     } else {
855         gl.glUniform1i(m_geometryDrawState.textureFormatLoc, GL_RGBA);
856     }
857 
858     gl.glUniform1i(m_geometryDrawState.enableLightingLoc, 0);
859     gl.glUniform1i(m_geometryDrawState.textureEnvModeLoc, mCtx->getTextureEnvMode());
860 }
861 
postDrawTextureUnitEmulation()862 void CoreProfileEngine::postDrawTextureUnitEmulation() {
863     auto& gl = GLEScontext::dispatcher();
864     unsigned int currTextureUnit = mCtx->getActiveTextureUnit();
865 
866     GLuint cubeMapTex = mCtx->getBindedTexture(currTextureUnit + GL_TEXTURE0, GL_TEXTURE_CUBE_MAP);
867 
868     if (cubeMapTex) {
869         GLuint cubeMapTexGlobal = mCtx->shareGroup()->getGlobalName(
870                                       NamedObjectType::TEXTURE, cubeMapTex);
871         gl.glActiveTexture(GL_TEXTURE0 + currTextureUnit * 2);
872         gl.glBindTexture(GL_TEXTURE_CUBE_MAP, cubeMapTexGlobal);
873         gl.glActiveTexture(GL_TEXTURE0 + currTextureUnit * 2 + 1);
874         gl.glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
875         gl.glActiveTexture(GL_TEXTURE0 + currTextureUnit * 2);
876     }
877 }
878 
preDrawVertexSetup()879 void CoreProfileEngine::preDrawVertexSetup() {
880     auto& gl = GLEScontext::dispatcher();
881 
882     glm::mat4 currProjMatrix = mCtx->getProjMatrix();
883     glm::mat4 currModelviewMatrix = mCtx->getModelviewMatrix();
884     glm::mat4 currTextureMatrix = mCtx->getTextureMatrix();
885     glm::mat4 currModelviewMatrixInvTr = glm::inverseTranspose(currModelviewMatrix);
886 
887     gl.glBindVertexArray(m_geometryDrawState.vao);
888 
889     gl.glUseProgram(mCtx->getShadeModel() == GL_FLAT ?
890                     m_geometryDrawState.programFlat :
891                     m_geometryDrawState.program);
892     gl.glUniformMatrix4fv(m_geometryDrawState.projMatrixLoc, 1, GL_FALSE, glm::value_ptr(currProjMatrix));
893     gl.glUniformMatrix4fv(m_geometryDrawState.modelviewMatrixLoc, 1, GL_FALSE, glm::value_ptr(currModelviewMatrix));
894     gl.glUniformMatrix4fv(m_geometryDrawState.modelviewInvTrLoc, 1, GL_FALSE, glm::value_ptr(currModelviewMatrixInvTr));
895     gl.glUniformMatrix4fv(m_geometryDrawState.textureMatrixLoc, 1, GL_FALSE, glm::value_ptr(currTextureMatrix));
896 }
897 
postDrawVertexSetup()898 void CoreProfileEngine::postDrawVertexSetup() {
899     auto& gl = GLEScontext::dispatcher();
900 
901     gl.glBindVertexArray(0);
902 }
903 
setupLighting()904 void CoreProfileEngine::setupLighting() {
905     auto& gl = GLEScontext::dispatcher();
906 
907     gl.glUniform1i(m_geometryDrawState.enableLightingLoc,
908                    mCtx->isEnabled(GL_LIGHTING));
909     gl.glUniform1i(m_geometryDrawState.enableRescaleNormalLoc,
910                    mCtx->isEnabled(GL_RESCALE_NORMAL));
911     gl.glUniform1i(m_geometryDrawState.enableNormalizeLoc,
912                    mCtx->isEnabled(GL_NORMALIZE));
913     gl.glUniform1i(m_geometryDrawState.enableColorMaterialLoc,
914                    mCtx->isEnabled(GL_COLOR_MATERIAL));
915 
916     const auto& material = mCtx->getMaterialInfo();
917 
918     gl.glUniform4fv(m_geometryDrawState.materialAmbientLoc, 1, material.ambient);
919     gl.glUniform4fv(m_geometryDrawState.materialDiffuseLoc, 1, material.diffuse);
920     gl.glUniform4fv(m_geometryDrawState.materialSpecularLoc, 1, material.specular);
921     gl.glUniform4fv(m_geometryDrawState.materialEmissiveLoc, 1, material.emissive);
922     gl.glUniform1f(m_geometryDrawState.materialSpecularExponentLoc, material.specularExponent);
923 
924     const auto& lightModel = mCtx->getLightModelInfo();
925 
926     gl.glUniform4fv(m_geometryDrawState.lightModelSceneAmbientLoc, 1, lightModel.color);
927     gl.glUniform1i(m_geometryDrawState.lightModelTwoSidedLoc, lightModel.twoSided);
928 
929     assert(kMaxLights == GLEScmContext::kMaxLights);
930 
931     for (int i = 0; i < GLEScmContext::kMaxLights; i++) {
932         m_lightingBuffer.lightEnables[i] = mCtx->isEnabled(GL_LIGHT0 + i);
933         const auto& light = mCtx->getLightInfo(i);
934         memcpy(m_lightingBuffer.lightAmbients + 4 * i, &light.ambient, 4 * sizeof(GLfloat));
935         memcpy(m_lightingBuffer.lightDiffuses + 4 * i, &light.diffuse, 4 * sizeof(GLfloat));
936         memcpy(m_lightingBuffer.lightSpeculars + 4 * i, &light.specular, 4 * sizeof(GLfloat));
937         memcpy(m_lightingBuffer.lightPositions + 4 * i, &light.position, 4 * sizeof(GLfloat));
938         memcpy(m_lightingBuffer.lightDirections + 3 * i, &light.direction, 3 * sizeof(GLfloat));
939         m_lightingBuffer.spotlightExponents[i] = light.spotlightExponent;
940         m_lightingBuffer.spotlightCutoffAngles[i] = light.spotlightCutoffAngle;
941         m_lightingBuffer.attenuationConsts[i] = light.attenuationConst;
942         m_lightingBuffer.attenuationLinears[i] = light.attenuationLinear;
943         m_lightingBuffer.attenuationQuadratics[i] = light.attenuationQuadratic;
944     }
945 
946     gl.glUniform1iv(m_geometryDrawState.lightEnablesLoc, GLEScmContext::kMaxLights, m_lightingBuffer.lightEnables);
947     gl.glUniform4fv(m_geometryDrawState.lightAmbientsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.lightAmbients);
948     gl.glUniform4fv(m_geometryDrawState.lightDiffusesLoc, GLEScmContext::kMaxLights, m_lightingBuffer.lightDiffuses);
949     gl.glUniform4fv(m_geometryDrawState.lightSpecularsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.lightSpeculars);
950     gl.glUniform4fv(m_geometryDrawState.lightPositionsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.lightPositions);
951     gl.glUniform3fv(m_geometryDrawState.lightDirectionsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.lightDirections);
952     gl.glUniform1fv(m_geometryDrawState.lightSpotlightExponentsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.spotlightExponents);
953     gl.glUniform1fv(m_geometryDrawState.lightSpotlightCutoffAnglesLoc, GLEScmContext::kMaxLights, m_lightingBuffer.spotlightCutoffAngles);
954     gl.glUniform1fv(m_geometryDrawState.lightAttenuationConstsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.attenuationConsts);
955     gl.glUniform1fv(m_geometryDrawState.lightAttenuationLinearsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.attenuationLinears);
956     gl.glUniform1fv(m_geometryDrawState.lightAttenuationQuadraticsLoc, GLEScmContext::kMaxLights, m_lightingBuffer.attenuationQuadratics);
957 }
958 
setupFog()959 void CoreProfileEngine::setupFog() {
960     auto& gl = GLEScontext::dispatcher();
961 
962     gl.glUniform1i(m_geometryDrawState.enableFogLoc,
963                    mCtx->isEnabled(GL_FOG));
964 
965     const auto& fogInfo = mCtx->getFogInfo();
966 
967     gl.glUniform1i(m_geometryDrawState.fogModeLoc, fogInfo.mode);
968     gl.glUniform1f(m_geometryDrawState.fogDensityLoc, fogInfo.density);
969     gl.glUniform1f(m_geometryDrawState.fogStartLoc, fogInfo.start);
970     gl.glUniform1f(m_geometryDrawState.fogEndLoc, fogInfo.end);
971 
972     gl.glUniform4fv(m_geometryDrawState.fogColorLoc, 1, fogInfo.color);
973 }
974 
drawArrays(GLenum type,GLint first,GLsizei count)975 void CoreProfileEngine::drawArrays(GLenum type, GLint first, GLsizei count) {
976     auto& gl = GLEScontext::dispatcher();
977 
978     preDrawVertexSetup();
979     preDrawTextureUnitEmulation();
980 
981     setupLighting();
982     setupFog();
983 
984     gl.glDrawArrays(type, first, count);
985 
986     postDrawVertexSetup();
987     postDrawTextureUnitEmulation();
988 }
989 
drawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)990 void CoreProfileEngine::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) {
991     auto& gl = GLEScontext::dispatcher();
992 
993     preDrawVertexSetup();
994     preDrawTextureUnitEmulation();
995 
996     setupLighting();
997     setupFog();
998 
999     gl.glDrawElements(mode, count, type, (GLvoid*)0);
1000 
1001     postDrawVertexSetup();
1002     postDrawTextureUnitEmulation();
1003 }
1004