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