1 /*
2  * Copyright (C) 2018 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 <OpenGLESDispatch/GLESv3Dispatch.h>
18 
19 #include "GLESv3.h"
20 
21 #include <string>
22 #include <vector>
23 
24 // Stubs (common)
25 
glDeleteFencesNV(GLsizei,const GLuint *)26 static void glDeleteFencesNV(GLsizei, const GLuint*) {
27     printf("%s: not implemented\n", __func__);
28 }
29 
glDisableDriverControlQCOM(GLuint)30 static void glDisableDriverControlQCOM(GLuint) {
31     printf("%s: not implemented\n", __func__);
32 }
33 
glDiscardFramebufferEXT(GLenum,GLsizei,const GLenum *)34 static void glDiscardFramebufferEXT(GLenum, GLsizei, const GLenum*) {
35     printf("%s: not implemented\n", __func__);
36 }
37 
glEnableDriverControlQCOM(GLuint)38 static void glEnableDriverControlQCOM(GLuint) {
39     printf("%s: not implemented\n", __func__);
40 }
41 
glEndTilingQCOM(GLbitfield)42 static void glEndTilingQCOM(GLbitfield) {
43     printf("%s: not implemented\n", __func__);
44 }
45 
glExtGetBufferPointervQCOM(GLenum,GLvoid **)46 static void glExtGetBufferPointervQCOM(GLenum, GLvoid**) {
47     printf("%s: not implemented\n", __func__);
48 }
49 
glExtGetBuffersQCOM(GLuint *,GLint,GLint *)50 static void glExtGetBuffersQCOM(GLuint*, GLint, GLint*) {
51     printf("%s: not implemented\n", __func__);
52 }
53 
glExtGetFramebuffersQCOM(GLuint *,GLint,GLint *)54 static void glExtGetFramebuffersQCOM(GLuint*, GLint, GLint*) {
55     printf("%s: not implemented\n", __func__);
56 }
57 
glExtGetProgramBinarySourceQCOM(GLuint,GLenum,GLchar *,GLint *)58 static void glExtGetProgramBinarySourceQCOM(GLuint, GLenum, GLchar*, GLint*) {
59     printf("%s: not implemented\n", __func__);
60 }
61 
glExtGetProgramsQCOM(GLuint *,GLint,GLint *)62 static void glExtGetProgramsQCOM(GLuint*, GLint, GLint*) {
63     printf("%s: not implemented\n", __func__);
64 }
65 
glExtGetRenderbuffersQCOM(GLuint *,GLint,GLint *)66 static void glExtGetRenderbuffersQCOM(GLuint*, GLint, GLint*) {
67     printf("%s: not implemented\n", __func__);
68 }
69 
glExtGetShadersQCOM(GLuint *,GLint,GLint *)70 static void glExtGetShadersQCOM(GLuint*, GLint, GLint*) {
71     printf("%s: not implemented\n", __func__);
72 }
73 
glExtGetTexLevelParameterivQCOM(GLuint,GLenum,GLint,GLenum,GLint *)74 static void glExtGetTexLevelParameterivQCOM(GLuint, GLenum, GLint, GLenum, GLint*) {
75     printf("%s: not implemented\n", __func__);
76 }
77 
glExtGetTexSubImageQCOM(GLenum,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei,GLenum,GLenum,GLvoid *)78 static void glExtGetTexSubImageQCOM(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei,
79                                     GLenum, GLenum, GLvoid*) {
80     printf("%s: not implemented\n", __func__);
81 }
82 
glExtGetTexturesQCOM(GLuint *,GLint,GLint *)83 static void glExtGetTexturesQCOM(GLuint*, GLint, GLint*) {
84     printf("%s: not implemented\n", __func__);
85 }
86 
glExtIsProgramBinaryQCOM(GLuint)87 static GLboolean glExtIsProgramBinaryQCOM(GLuint) {
88     printf("%s: not implemented\n", __func__);
89     return GL_FALSE;
90 }
91 
glExtTexObjectStateOverrideiQCOM(GLenum,GLenum,GLint)92 static void glExtTexObjectStateOverrideiQCOM(GLenum, GLenum, GLint) {
93     printf("%s: not implemented\n", __func__);
94 }
95 
glFinishFenceNV(GLuint)96 static void glFinishFenceNV(GLuint) {
97     printf("%s: not implemented\n", __func__);
98 }
99 
glFramebufferTexture2DMultisampleIMG(GLenum,GLenum,GLenum,GLuint,GLint,GLsizei)100 static void glFramebufferTexture2DMultisampleIMG(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei) {
101     printf("%s: not implemented\n", __func__);
102 }
103 
glGenFencesNV(GLsizei,GLuint *)104 static void glGenFencesNV(GLsizei, GLuint*) {
105     printf("%s: not implemented\n", __func__);
106 }
107 
glGetDriverControlsQCOM(GLint *,GLsizei,GLuint *)108 static void glGetDriverControlsQCOM(GLint*, GLsizei, GLuint*) {
109     printf("%s: not implemented\n", __func__);
110 }
111 
glGetDriverControlStringQCOM(GLuint,GLsizei,GLsizei *,GLchar *)112 static void glGetDriverControlStringQCOM(GLuint, GLsizei, GLsizei*, GLchar*) {
113     printf("%s: not implemented\n", __func__);
114 }
115 
glGetFenceivNV(GLuint,GLenum,GLint *)116 static void glGetFenceivNV(GLuint, GLenum, GLint*) {
117     printf("%s: not implemented\n", __func__);
118 }
119 
glIsFenceNV(GLuint)120 static GLboolean glIsFenceNV(GLuint) {
121     printf("%s: not implemented\n", __func__);
122     return GL_FALSE;
123 }
124 
glMapBufferOES(GLenum,GLenum)125 static void* glMapBufferOES(GLenum, GLenum) {
126     printf("%s: not implemented\n", __func__);
127     return nullptr;
128 }
129 
glMultiDrawArraysEXT(GLenum,const GLint *,const GLsizei *,GLsizei)130 static void glMultiDrawArraysEXT(GLenum, const GLint*, const GLsizei*, GLsizei) {
131     printf("%s: not implemented\n", __func__);
132 }
133 
glMultiDrawElementsEXT(GLenum,const GLsizei *,GLenum,const GLvoid * const *,GLsizei)134 static void glMultiDrawElementsEXT(GLenum, const GLsizei*, GLenum, const GLvoid* const*, GLsizei) {
135     printf("%s: not implemented\n", __func__);
136 }
137 
glRenderbufferStorageMultisampleIMG(GLenum,GLsizei,GLenum,GLsizei,GLsizei)138 static void glRenderbufferStorageMultisampleIMG(GLenum, GLsizei, GLenum, GLsizei, GLsizei) {
139     printf("%s: not implemented\n", __func__);
140 }
141 
glSetFenceNV(GLuint,GLenum)142 static void glSetFenceNV(GLuint, GLenum) {
143     printf("%s: not implemented\n", __func__);
144 }
145 
glStartTilingQCOM(GLuint,GLuint,GLuint,GLuint,GLbitfield)146 static void glStartTilingQCOM(GLuint, GLuint, GLuint, GLuint, GLbitfield) {
147     printf("%s: not implemented\n", __func__);
148 }
149 
glTestFenceNV(GLuint)150 static GLboolean glTestFenceNV(GLuint) {
151     printf("%s: not implemented\n", __func__);
152     return GL_FALSE;
153 }
154 
155 // Stubs (ES 3.1)
156 
glBeginPerfMonitorAMD(GLuint)157 static void glBeginPerfMonitorAMD(GLuint) {
158     printf("%s: not implemented\n", __func__);
159 }
160 
glCoverageMaskNV(GLboolean)161 static void glCoverageMaskNV(GLboolean) {
162     printf("%s: not implemented\n", __func__);
163 }
164 
glCoverageOperationNV(GLenum)165 static void glCoverageOperationNV(GLenum) {
166     printf("%s: not implemented\n", __func__);
167 }
168 
glDeletePerfMonitorsAMD(GLsizei,GLuint *)169 static void glDeletePerfMonitorsAMD(GLsizei, GLuint*) {
170     printf("%s: not implemented\n", __func__);
171 }
172 
glEndPerfMonitorAMD(GLuint)173 static void glEndPerfMonitorAMD(GLuint) {
174     printf("%s: not implemented\n", __func__);
175 }
176 
glGenPerfMonitorsAMD(GLsizei,GLuint *)177 static void glGenPerfMonitorsAMD(GLsizei, GLuint*) {
178     printf("%s: not implemented\n", __func__);
179 }
180 
glGetPerfMonitorCounterDataAMD(GLuint,GLenum,GLsizei,GLuint *,GLint *)181 static void glGetPerfMonitorCounterDataAMD(GLuint, GLenum, GLsizei, GLuint*, GLint*) {
182     printf("%s: not implemented\n", __func__);
183 }
184 
glGetPerfMonitorCounterInfoAMD(GLuint,GLuint,GLenum,GLvoid *)185 static void glGetPerfMonitorCounterInfoAMD(GLuint, GLuint, GLenum, GLvoid*) {
186     printf("%s: not implemented\n", __func__);
187 }
188 
glGetPerfMonitorCountersAMD(GLuint,GLint *,GLint *,GLsizei,GLuint *)189 static void glGetPerfMonitorCountersAMD(GLuint, GLint*, GLint*, GLsizei, GLuint*) {
190     printf("%s: not implemented\n", __func__);
191 }
192 
glGetPerfMonitorCounterStringAMD(GLuint,GLuint,GLsizei,GLsizei *,GLchar *)193 static void glGetPerfMonitorCounterStringAMD(GLuint, GLuint, GLsizei, GLsizei*, GLchar*) {
194     printf("%s: not implemented\n", __func__);
195 }
196 
glGetPerfMonitorGroupsAMD(GLint *,GLsizei,GLuint *)197 static void glGetPerfMonitorGroupsAMD(GLint*, GLsizei, GLuint*) {
198     printf("%s: not implemented\n", __func__);
199 }
200 
glGetPerfMonitorGroupStringAMD(GLuint,GLsizei,GLsizei *,GLchar *)201 static void glGetPerfMonitorGroupStringAMD(GLuint, GLsizei, GLsizei*, GLchar*) {
202     printf("%s: not implemented\n", __func__);
203 }
204 
glSelectPerfMonitorCountersAMD(GLuint,GLboolean,GLuint,GLint,GLuint *)205 static void glSelectPerfMonitorCountersAMD(GLuint, GLboolean, GLuint, GLint, GLuint*) {
206     printf("%s: not implemented\n", __func__);
207 }
208 
209 // Non-stubs (common)
210 
glDrawElementsData(GLenum mode,GLsizei count,GLenum type,void * indices,GLuint)211 static void glDrawElementsData(GLenum mode, GLsizei count, GLenum type, void* indices, GLuint) {
212     s_gles3.glDrawElements(mode, count, type, indices);
213 }
214 
glDrawElementsOffset(GLenum mode,GLsizei count,GLenum type,GLuint offset)215 static void glDrawElementsOffset(GLenum mode, GLsizei count, GLenum type, GLuint offset) {
216     s_gles3.glDrawElements(mode, count, type, reinterpret_cast<const GLvoid*>(offset));
217 }
218 
glFinishRoundTrip()219 static GLint glFinishRoundTrip() {
220     s_gles3.glFinish();
221     return 0;
222 }
223 
glGetCompressedTextureFormats(int count,GLint * formats)224 static void glGetCompressedTextureFormats(int count, GLint* formats) {
225     int nFormats;
226     s_gles3.glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &nFormats);
227     if (nFormats <= count)
228         s_gles3.glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats);
229 }
230 
231 // Non-stubs (ES 3.1)
232 
233 struct GlSync {
GlSyncGlSync234     GlSync(GLESv3* ctx_, GLsync sync_) : sync(sync_), id(ctx_->sync_nextId++), ctx(ctx_) {
235         ctx->sync_map.emplace(id, this);
236     }
237 
~GlSyncGlSync238     ~GlSync() {
239         ctx->sync_map.erase(id);
240     }
241 
242     GLsync sync;
243     uint64_t id;
244 
245   private:
246     GLESv3* ctx;
247 };
248 
glClientWaitSyncAEMU(void * ctx_,uint64_t wait_on,GLbitfield flags,GLuint64 timeout)249 static GLenum glClientWaitSyncAEMU(void* ctx_, uint64_t wait_on, GLbitfield flags,
250                                    GLuint64 timeout) {
251     GLESv3* ctx = static_cast<GLESv3*>(ctx_);
252 
253     std::map<uint64_t, GlSync*>::iterator it;
254     it = ctx->sync_map.find(wait_on);
255     if (it == ctx->sync_map.end())
256         return GL_INVALID_VALUE;
257 
258     GlSync* sync = it->second;
259     return s_gles3.glClientWaitSync(sync->sync, flags, timeout);
260 }
261 
glCompressedTexImage2DOffsetAEMU(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,GLuint offset)262 static void glCompressedTexImage2DOffsetAEMU(GLenum target, GLint level, GLenum internalformat,
263                                              GLsizei width, GLsizei height, GLint border,
264                                              GLsizei imageSize, GLuint offset) {
265     s_gles3.glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize,
266                                    reinterpret_cast<const GLvoid*>(offset));
267 }
268 
glCompressedTexImage3DOffsetAEMU(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,GLuint offset)269 static void glCompressedTexImage3DOffsetAEMU(GLenum target, GLint level, GLenum internalformat,
270                                              GLsizei width, GLsizei height, GLsizei depth,
271                                              GLint border, GLsizei imageSize, GLuint offset) {
272     s_gles3.glCompressedTexImage3D(target, level, internalformat, width, height, depth, border,
273                                    imageSize, reinterpret_cast<const GLvoid*>(offset));
274 }
275 
glCompressedTexSubImage2DOffsetAEMU(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,GLuint offset)276 static void glCompressedTexSubImage2DOffsetAEMU(GLenum target, GLint level, GLint xoffset,
277                                                 GLint yoffset, GLsizei width, GLsizei height,
278                                                 GLenum format, GLsizei imageSize, GLuint offset) {
279     s_gles3.glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
280                                       imageSize, reinterpret_cast<const GLvoid*>(offset));
281 }
282 
glCompressedTexSubImage3DOffsetAEMU(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,GLuint offset)283 static void glCompressedTexSubImage3DOffsetAEMU(GLenum target, GLint level, GLint xoffset,
284                                                 GLint yoffset, GLint zoffset, GLsizei width,
285                                                 GLsizei height, GLsizei depth, GLenum format,
286                                                 GLsizei imageSize, GLuint offset) {
287     s_gles3.glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth,
288                                       format, imageSize, reinterpret_cast<const GLvoid*>(offset));
289 }
290 
glCreateShaderProgramvAEMU(GLenum type,GLsizei,const char * packedStrings,GLuint)291 static GLuint glCreateShaderProgramvAEMU(GLenum type, GLsizei, const char* packedStrings, GLuint) {
292     return s_gles3.glCreateShaderProgramv(type, 1, &packedStrings);
293 }
294 
glDeleteSyncAEMU(void * ctx_,uint64_t to_delete)295 static void glDeleteSyncAEMU(void* ctx_, uint64_t to_delete) {
296     GLESv3* ctx = static_cast<GLESv3*>(ctx_);
297 
298     std::map<uint64_t, GlSync*>::iterator it;
299     it = ctx->sync_map.find(to_delete);
300     if (it == ctx->sync_map.end())
301         return;
302 
303     GlSync* sync = it->second;
304     s_gles3.glDeleteSync(sync->sync);
305     delete sync;
306 }
307 
glDrawArraysIndirectDataAEMU(GLenum mode,const void * indirect,GLuint)308 static void glDrawArraysIndirectDataAEMU(GLenum mode, const void* indirect, GLuint) {
309     s_gles3.glDrawArraysIndirect(mode, indirect);
310 }
311 
glDrawArraysIndirectOffsetAEMU(GLenum mode,GLuint offset)312 static void glDrawArraysIndirectOffsetAEMU(GLenum mode, GLuint offset) {
313     s_gles3.glDrawArraysIndirect(mode, reinterpret_cast<const void*>(offset));
314 }
315 
glDrawElementsIndirectDataAEMU(GLenum mode,GLenum type,const void * indirect,GLuint)316 static void glDrawElementsIndirectDataAEMU(GLenum mode, GLenum type, const void* indirect, GLuint) {
317     s_gles3.glDrawElementsIndirect(mode, type, indirect);
318 }
319 
glDrawElementsIndirectOffsetAEMU(GLenum mode,GLenum type,GLuint offset)320 static void glDrawElementsIndirectOffsetAEMU(GLenum mode, GLenum type, GLuint offset) {
321     s_gles3.glDrawElementsIndirect(mode, type, reinterpret_cast<const void*>(offset));
322 }
323 
glDrawElementsInstancedDataAEMU(GLenum mode,GLsizei count,GLenum type,const void * indices,GLsizei primcount,GLsizei)324 static void glDrawElementsInstancedDataAEMU(GLenum mode, GLsizei count, GLenum type,
325                                             const void* indices, GLsizei primcount, GLsizei) {
326     s_gles3.glDrawElementsInstanced(mode, count, type, indices, primcount);
327 }
328 
glDrawElementsInstancedOffsetAEMU(GLenum mode,GLsizei count,GLenum type,GLuint offset,GLsizei primcount)329 static void glDrawElementsInstancedOffsetAEMU(GLenum mode, GLsizei count, GLenum type,
330                                               GLuint offset, GLsizei primcount) {
331     s_gles3.glDrawElementsInstanced(mode, count, type, reinterpret_cast<const void*>(offset),
332                                     primcount);
333 }
334 
glDrawRangeElementsDataAEMU(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices,GLsizei)335 static void glDrawRangeElementsDataAEMU(GLenum mode, GLuint start, GLuint end, GLsizei count,
336                                         GLenum type, const GLvoid* indices, GLsizei) {
337     s_gles3.glDrawRangeElements(mode, start, end, count, type, indices);
338 }
339 
glDrawRangeElementsOffsetAEMU(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,GLuint offset)340 static void glDrawRangeElementsOffsetAEMU(GLenum mode, GLuint start, GLuint end, GLsizei count,
341                                           GLenum type, GLuint offset) {
342     s_gles3.glDrawRangeElements(mode, start, end, count, type,
343                                 reinterpret_cast<const GLvoid*>(offset));
344 }
345 
glFenceSyncAEMU(void * ctx_,GLenum condition,GLbitfield flags)346 static uint64_t glFenceSyncAEMU(void* ctx_, GLenum condition, GLbitfield flags) {
347     GLsync sync_ = s_gles3.glFenceSync(condition, flags);
348     if (sync_ == 0)
349         return 0U;
350 
351     GLESv3* ctx = static_cast<GLESv3*>(ctx_);
352     GlSync* sync = new (std::nothrow) GlSync(ctx, sync_);
353     if (!sync) {
354         s_gles3.glDeleteSync(sync_);
355         return 0U;
356     }
357 
358     return sync->id;
359 }
360 
glFlushMappedBufferRangeAEMU(GLenum target,GLintptr offset,GLsizeiptr length,GLbitfield access,void * guest_buffer)361 static void glFlushMappedBufferRangeAEMU(GLenum target, GLintptr offset, GLsizeiptr length,
362                                          GLbitfield access, void* guest_buffer) {
363     if (guest_buffer && length) {
364         void* gpuPtr = s_gles3.glMapBufferRange(target, offset, length, access);
365         if (gpuPtr) {
366             memcpy(gpuPtr, guest_buffer, length);
367             s_gles3.glFlushMappedBufferRange(target, 0, length);
368             s_gles3.glUnmapBuffer(target);
369         }
370     }
371 }
372 
glGetSyncivAEMU(void * ctx_,uint64_t sync_,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * values)373 static void glGetSyncivAEMU(void* ctx_, uint64_t sync_, GLenum pname, GLsizei bufSize,
374                             GLsizei* length, GLint* values) {
375     GLESv3* ctx = static_cast<GLESv3*>(ctx_);
376 
377     std::map<uint64_t, GlSync*>::iterator it;
378     it = ctx->sync_map.find(sync_);
379     if (it == ctx->sync_map.end())
380         return;
381 
382     GlSync* sync = it->second;
383     s_gles3.glGetSynciv(sync->sync, pname, bufSize, length, values);
384 }
385 
sUnpackVarNames(GLsizei count,const char * packedNames)386 static std::vector<std::string> sUnpackVarNames(GLsizei count, const char* packedNames) {
387     std::vector<std::string> unpacked;
388     GLsizei current = 0;
389 
390     while (current < count) {
391         const char* delimPos = strstr(packedNames, ";");
392         size_t nameLen = delimPos - packedNames;
393         std::string next;
394         next.resize(nameLen);
395         memcpy(&next[0], packedNames, nameLen);
396         unpacked.push_back(next);
397         packedNames = delimPos + 1;
398         current++;
399     }
400 
401     return unpacked;
402 }
403 
glGetUniformIndicesAEMU(GLuint program,GLsizei uniformCount,const GLchar * packedNames,GLsizei packedLen,GLuint * uniformIndices)404 static void glGetUniformIndicesAEMU(GLuint program, GLsizei uniformCount, const GLchar* packedNames,
405                                     GLsizei packedLen, GLuint* uniformIndices) {
406     std::vector<std::string> unpacked = sUnpackVarNames(uniformCount, packedNames);
407     GLchar** unpackedArray = new GLchar*[unpacked.size()];
408     GLsizei i = 0;
409     for (auto& elt : unpacked) {
410         unpackedArray[i] = (GLchar*)&elt[0];
411         i++;
412     }
413 
414     s_gles3.glGetUniformIndices(program, uniformCount, const_cast<const GLchar**>(unpackedArray),
415                                 uniformIndices);
416     delete[] unpackedArray;
417 }
418 
glIsSyncAEMU(void * ctx_,uint64_t sync)419 static GLboolean glIsSyncAEMU(void* ctx_, uint64_t sync) {
420     GLESv3* ctx = static_cast<GLESv3*>(ctx_);
421     return ctx->sync_map.count(sync) ? GL_TRUE : GL_FALSE;
422 }
423 
glMapBufferRangeAEMU(GLenum target,GLintptr offset,GLsizeiptr length,GLbitfield access,void * mapped)424 static void glMapBufferRangeAEMU(GLenum target, GLintptr offset, GLsizeiptr length,
425                                  GLbitfield access, void* mapped) {
426     if ((access & GL_MAP_READ_BIT) ||
427         ((access & GL_MAP_WRITE_BIT) &&
428          (!(access & GL_MAP_INVALIDATE_RANGE_BIT) && !(access & GL_MAP_INVALIDATE_BUFFER_BIT)))) {
429         void* gpuPtr = s_gles3.glMapBufferRange(target, offset, length, access);
430         if (gpuPtr) {
431             if (mapped)
432                 memcpy(mapped, gpuPtr, length);
433             s_gles3.glUnmapBuffer(target);
434         }
435     }
436 }
437 
glReadPixelsOffsetAEMU(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLuint offset)438 static void glReadPixelsOffsetAEMU(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
439                                    GLenum type, GLuint offset) {
440     s_gles3.glReadPixels(x, y, width, height, format, type, reinterpret_cast<GLvoid*>(offset));
441 }
442 
glShaderString(GLuint shader,const GLchar * string,GLsizei)443 static void glShaderString(GLuint shader, const GLchar* string, GLsizei) {
444     s_gles3.glShaderSource(shader, 1, &string, NULL);
445 }
446 
glTexImage2DOffsetAEMU(GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,GLuint offset)447 static void glTexImage2DOffsetAEMU(GLenum target, GLint level, GLint internalformat, GLsizei width,
448                                    GLsizei height, GLint border, GLenum format, GLenum type,
449                                    GLuint offset) {
450     s_gles3.glTexImage2D(target, level, internalformat, width, height, border, format, type,
451                          reinterpret_cast<const GLvoid*>(offset));
452 }
453 
glTexImage3DOffsetAEMU(GLenum target,GLint level,GLint internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLuint offset)454 static void glTexImage3DOffsetAEMU(GLenum target, GLint level, GLint internalFormat, GLsizei width,
455                                    GLsizei height, GLsizei depth, GLint border, GLenum format,
456                                    GLenum type, GLuint offset) {
457     s_gles3.glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type,
458                          reinterpret_cast<const GLvoid*>(offset));
459 }
460 
glTexSubImage2DOffsetAEMU(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,GLuint offset)461 static void glTexSubImage2DOffsetAEMU(GLenum target, GLint level, GLint xoffset, GLint yoffset,
462                                       GLsizei width, GLsizei height, GLenum format, GLenum type,
463                                       GLuint offset) {
464     s_gles3.glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
465                             reinterpret_cast<const GLvoid*>(offset));
466 }
467 
glTexSubImage3DOffsetAEMU(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,GLuint offset)468 static void glTexSubImage3DOffsetAEMU(GLenum target, GLint level, GLint xoffset, GLint yoffset,
469                                       GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
470                                       GLenum format, GLenum type, GLuint offset) {
471     s_gles3.glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format,
472                             type, reinterpret_cast<const GLvoid*>(offset));
473 }
474 
glTransformFeedbackVaryingsAEMU(GLuint program,GLsizei count,const char * packedVaryings,GLuint packedVaryingsLen,GLenum bufferMode)475 static void glTransformFeedbackVaryingsAEMU(GLuint program, GLsizei count,
476                                             const char* packedVaryings, GLuint packedVaryingsLen,
477                                             GLenum bufferMode) {
478     std::vector<std::string> unpacked = sUnpackVarNames(count, packedVaryings);
479     char** unpackedArray = new char*[unpacked.size()];
480     GLsizei i = 0;
481     for (auto& elt : unpacked) {
482         unpackedArray[i] = &elt[0];
483         i++;
484     }
485 
486     s_gles3.glTransformFeedbackVaryings(program, count, const_cast<const char**>(unpackedArray),
487                                         bufferMode);
488     delete[] unpackedArray;
489 }
490 
glUnmapBufferAEMU(GLenum target,GLintptr offset,GLsizeiptr length,GLbitfield access,void * guest_buffer,GLboolean * out_res)491 static void glUnmapBufferAEMU(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access,
492                               void* guest_buffer, GLboolean* out_res) {
493     *out_res = GL_TRUE;
494 
495     if (access & GL_MAP_WRITE_BIT) {
496         if (guest_buffer) {
497             void* gpuPtr = s_gles3.glMapBufferRange(target, offset, length, access);
498             if (gpuPtr)
499                 memcpy(gpuPtr, guest_buffer, length);
500         }
501 
502         *out_res = s_gles3.glUnmapBuffer(target);
503     }
504 }
505 
glVertexAttribIPointerDataAEMU(GLuint index,GLint size,GLenum type,GLsizei,void * data,GLuint)506 static void glVertexAttribIPointerDataAEMU(GLuint index, GLint size, GLenum type, GLsizei,
507                                            void* data, GLuint) {
508     s_gles3.glVertexAttribIPointer(index, size, type, 0, data);
509 }
510 
glVertexAttribIPointerOffsetAEMU(GLuint index,GLint size,GLenum type,GLsizei,GLuint offset)511 static void glVertexAttribIPointerOffsetAEMU(GLuint index, GLint size, GLenum type, GLsizei,
512                                              GLuint offset) {
513     s_gles3.glVertexAttribIPointer(index, size, type, 0, reinterpret_cast<const GLvoid*>(offset));
514 }
515 
glVertexAttribPointerData(GLuint indx,GLint size,GLenum type,GLboolean normalized,GLsizei,void * data,GLuint)516 static void glVertexAttribPointerData(GLuint indx, GLint size, GLenum type, GLboolean normalized,
517                                       GLsizei, void* data, GLuint) {
518     s_gles3.glVertexAttribPointer(indx, size, type, normalized, 0, data);
519 }
520 
glVertexAttribPointerOffset(GLuint indx,GLint size,GLenum type,GLboolean normalized,GLsizei,GLuint offset)521 static void glVertexAttribPointerOffset(GLuint indx, GLint size, GLenum type, GLboolean normalized,
522                                         GLsizei, GLuint offset) {
523     s_gles3.glVertexAttribPointer(indx, size, type, normalized, 0,
524                                   reinterpret_cast<const GLvoid*>(offset));
525 }
526 
glWaitSyncAEMU(void * ctx_,uint64_t wait_on,GLbitfield flags,GLuint64 timeout)527 static void glWaitSyncAEMU(void* ctx_, uint64_t wait_on, GLbitfield flags, GLuint64 timeout) {
528     GLESv3* ctx = static_cast<GLESv3*>(ctx_);
529 
530     std::map<uint64_t, GlSync*>::iterator it;
531     it = ctx->sync_map.find(wait_on);
532     if (it == ctx->sync_map.end())
533         return;
534 
535     GlSync* sync = it->second;
536     s_gles3.glWaitSync(sync->sync, flags, timeout);
537 }
538 
539 #define KNIT(return_type, function_name, signature, callargs) function_name = s_gles3.function_name;
540 
GLESv3()541 GLESv3::GLESv3() {
542     LIST_GLES3_FUNCTIONS(KNIT, KNIT)
543 
544     // Remap some ES 2.0 extensions that become core in ES 3.1
545     glBindVertexArrayOES = glBindVertexArray;
546     glDeleteVertexArraysOES = glDeleteVertexArrays;
547     glGenVertexArraysOES = glGenVertexArrays;
548     glGetProgramBinaryOES = glGetProgramBinary;
549     glIsVertexArrayOES = glIsVertexArray;
550     glProgramBinaryOES = glProgramBinary;
551     glUnmapBufferOES = glUnmapBuffer;
552 
553     // Entrypoints requiring custom wrappers (common)
554     glDrawElementsData = ::glDrawElementsData;
555     glDrawElementsOffset = ::glDrawElementsOffset;
556     glFinishRoundTrip = ::glFinishRoundTrip;
557     glGetCompressedTextureFormats = ::glGetCompressedTextureFormats;
558 
559     // Entrypoints requiring custom wrappers (ES 3.1)
560     glClientWaitSyncAEMU = ::glClientWaitSyncAEMU;
561     glCompressedTexImage2DOffsetAEMU = ::glCompressedTexImage2DOffsetAEMU;
562     glCompressedTexImage3DOffsetAEMU = ::glCompressedTexImage3DOffsetAEMU;
563     glCompressedTexSubImage2DOffsetAEMU = ::glCompressedTexSubImage2DOffsetAEMU;
564     glCompressedTexSubImage3DOffsetAEMU = ::glCompressedTexSubImage3DOffsetAEMU;
565     glCreateShaderProgramvAEMU = ::glCreateShaderProgramvAEMU;
566     glDeleteSyncAEMU = ::glDeleteSyncAEMU;
567     glDrawArraysIndirectDataAEMU = ::glDrawArraysIndirectDataAEMU;
568     glDrawArraysIndirectOffsetAEMU = ::glDrawArraysIndirectOffsetAEMU;
569     glDrawElementsIndirectDataAEMU = ::glDrawElementsIndirectDataAEMU;
570     glDrawElementsIndirectOffsetAEMU = ::glDrawElementsIndirectOffsetAEMU;
571     glDrawElementsInstancedDataAEMU = ::glDrawElementsInstancedDataAEMU;
572     glDrawElementsInstancedOffsetAEMU = ::glDrawElementsInstancedOffsetAEMU;
573     glDrawRangeElementsDataAEMU = ::glDrawRangeElementsDataAEMU;
574     glDrawRangeElementsOffsetAEMU = ::glDrawRangeElementsOffsetAEMU;
575     glFenceSyncAEMU = ::glFenceSyncAEMU;
576     glFlushMappedBufferRangeAEMU = ::glFlushMappedBufferRangeAEMU;
577     glGetSyncivAEMU = ::glGetSyncivAEMU;
578     glGetUniformIndicesAEMU = ::glGetUniformIndicesAEMU;
579     glIsSyncAEMU = ::glIsSyncAEMU;
580     glMapBufferRangeAEMU = ::glMapBufferRangeAEMU;
581     glReadPixelsOffsetAEMU = ::glReadPixelsOffsetAEMU;
582     glShaderString = ::glShaderString;
583     glTexImage2DOffsetAEMU = ::glTexImage2DOffsetAEMU;
584     glTexImage3DOffsetAEMU = ::glTexImage3DOffsetAEMU;
585     glTexSubImage2DOffsetAEMU = ::glTexSubImage2DOffsetAEMU;
586     glTexSubImage3DOffsetAEMU = ::glTexSubImage3DOffsetAEMU;
587     glTransformFeedbackVaryingsAEMU = ::glTransformFeedbackVaryingsAEMU;
588     glUnmapBufferAEMU = ::glUnmapBufferAEMU;
589     glVertexAttribIPointerDataAEMU = ::glVertexAttribIPointerDataAEMU;
590     glVertexAttribIPointerOffsetAEMU = ::glVertexAttribIPointerOffsetAEMU;
591     glVertexAttribPointerData = ::glVertexAttribPointerData;
592     glVertexAttribPointerOffset = ::glVertexAttribPointerOffset;
593     glWaitSyncAEMU = ::glWaitSyncAEMU;
594 
595     // Stub some extensions we will never implement (common)
596     glDeleteFencesNV = ::glDeleteFencesNV;
597     glDisableDriverControlQCOM = ::glDisableDriverControlQCOM;
598     glDiscardFramebufferEXT = ::glDiscardFramebufferEXT;
599     glEnableDriverControlQCOM = ::glEnableDriverControlQCOM;
600     glEndTilingQCOM = ::glEndTilingQCOM;
601     glExtGetBufferPointervQCOM = ::glExtGetBufferPointervQCOM;
602     glExtGetBuffersQCOM = ::glExtGetBuffersQCOM;
603     glExtGetFramebuffersQCOM = ::glExtGetFramebuffersQCOM;
604     glExtGetProgramBinarySourceQCOM = ::glExtGetProgramBinarySourceQCOM;
605     glExtGetProgramsQCOM = ::glExtGetProgramsQCOM;
606     glExtGetRenderbuffersQCOM = ::glExtGetRenderbuffersQCOM;
607     glExtGetShadersQCOM = ::glExtGetShadersQCOM;
608     glExtGetTexLevelParameterivQCOM = ::glExtGetTexLevelParameterivQCOM;
609     glExtGetTexSubImageQCOM = ::glExtGetTexSubImageQCOM;
610     glExtGetTexturesQCOM = ::glExtGetTexturesQCOM;
611     glExtIsProgramBinaryQCOM = ::glExtIsProgramBinaryQCOM;
612     glExtTexObjectStateOverrideiQCOM = ::glExtTexObjectStateOverrideiQCOM;
613     glFinishFenceNV = ::glFinishFenceNV;
614     glFramebufferTexture2DMultisampleIMG = ::glFramebufferTexture2DMultisampleIMG;
615     glGenFencesNV = ::glGenFencesNV;
616     glGetDriverControlsQCOM = ::glGetDriverControlsQCOM;
617     glGetDriverControlStringQCOM = ::glGetDriverControlStringQCOM;
618     glGetFenceivNV = ::glGetFenceivNV;
619     glIsFenceNV = ::glIsFenceNV;
620     glMapBufferOES = ::glMapBufferOES;
621     glMultiDrawArraysEXT = ::glMultiDrawArraysEXT;
622     glMultiDrawElementsEXT = ::glMultiDrawElementsEXT;
623     glRenderbufferStorageMultisampleIMG = ::glRenderbufferStorageMultisampleIMG;
624     glSetFenceNV = ::glSetFenceNV;
625     glStartTilingQCOM = ::glStartTilingQCOM;
626     glTestFenceNV = ::glTestFenceNV;
627 
628     // Stub some extensions we will never implement (ES 3.1)
629     glBeginPerfMonitorAMD = ::glBeginPerfMonitorAMD;
630     glCoverageMaskNV = ::glCoverageMaskNV;
631     glCoverageOperationNV = ::glCoverageOperationNV;
632     glDeletePerfMonitorsAMD = ::glDeletePerfMonitorsAMD;
633     glEndPerfMonitorAMD = ::glEndPerfMonitorAMD;
634     glGenPerfMonitorsAMD = ::glGenPerfMonitorsAMD;
635     glGetPerfMonitorCounterDataAMD = ::glGetPerfMonitorCounterDataAMD;
636     glGetPerfMonitorCounterInfoAMD = ::glGetPerfMonitorCounterInfoAMD;
637     glGetPerfMonitorCountersAMD = ::glGetPerfMonitorCountersAMD;
638     glGetPerfMonitorCounterStringAMD = ::glGetPerfMonitorCounterStringAMD;
639     glGetPerfMonitorGroupsAMD = ::glGetPerfMonitorGroupsAMD;
640     glGetPerfMonitorGroupStringAMD = ::glGetPerfMonitorGroupStringAMD;
641     glSelectPerfMonitorCountersAMD = ::glSelectPerfMonitorCountersAMD;
642 }
643