blob: 14c5ac1460d53bad5fc1a73fa24e6f63d45c36bb [file] [log] [blame]
keunyoungb85b2752013-03-08 12:28:03 -08001/*
2* Copyright (C) 2011 The Android Open Source Project
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17#include "GL2Encoder.h"
Lingfeng Yang46153ab2017-01-09 13:37:22 -080018#include "GLESv2Validation.h"
19
20#include <string>
21#include <map>
22
keunyoungb85b2752013-03-08 12:28:03 -080023#include <assert.h>
24#include <ctype.h>
25
Lingfeng Yang69066602016-04-12 09:29:11 -070026#include <GLES2/gl2.h>
27#include <GLES2/gl2ext.h>
28#include <GLES2/gl2platform.h>
29
30#include <GLES3/gl3.h>
Lingfeng Yang46153ab2017-01-09 13:37:22 -080031#include <GLES3/gl31.h>
Lingfeng Yang69066602016-04-12 09:29:11 -070032
keunyoungb85b2752013-03-08 12:28:03 -080033#ifndef MIN
34#define MIN(a, b) ((a) < (b) ? (a) : (b))
35#endif
36
37static GLubyte *gVendorString= (GLubyte *) "Android";
Lingfeng Yang46153ab2017-01-09 13:37:22 -080038static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 3.0";
39static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 3.0";
Nicolas Capensfe2d51a2015-11-20 15:10:09 -050040static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external ";
keunyoungb85b2752013-03-08 12:28:03 -080041
Lingfeng Yang07289902017-01-27 12:26:19 -080042#define SET_ERROR_IF(condition, err) if((condition)) { \
keunyoungb85b2752013-03-08 12:28:03 -080043 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
Lingfeng Yang07289902017-01-27 12:26:19 -080044 ctx->setError(err); \
45 return; \
keunyoungb85b2752013-03-08 12:28:03 -080046 }
47
Lingfeng Yang07289902017-01-27 12:26:19 -080048#define SET_ERROR_WITH_MESSAGE_IF(condition, err, generator, genargs) if ((condition)) { \
49 std::string msg = generator genargs; \
50 ALOGE("%s:%s:%d GL error 0x%x\n" \
51 "Info: %s\n", __FILE__, __FUNCTION__, __LINE__, err, msg.c_str()); \
52 ctx->setError(err); \
53 return; \
54 } \
keunyoungb85b2752013-03-08 12:28:03 -080055
Lingfeng Yang07289902017-01-27 12:26:19 -080056#define RET_AND_SET_ERROR_IF(condition, err, ret) if((condition)) { \
keunyoungb85b2752013-03-08 12:28:03 -080057 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
Lingfeng Yang07289902017-01-27 12:26:19 -080058 ctx->setError(err); \
59 return ret; \
60 } \
keunyoungb85b2752013-03-08 12:28:03 -080061
Lingfeng Yang07289902017-01-27 12:26:19 -080062#define RET_AND_SET_ERROR_WITH_MESSAGE_IF(condition, err, ret, generator, genargs) if((condition)) { \
63 std::string msg = generator genargs; \
64 ALOGE("%s:%s:%d GL error 0x%x\n" \
65 "Info: %s\n", __FILE__, __FUNCTION__, __LINE__, err, msg.c_str()); \
66 ctx->setError(err); \
67 return ret; \
68 } \
keunyoungb85b2752013-03-08 12:28:03 -080069
Yahan Zhoub7f09082016-03-10 11:45:02 -080070GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
71 : gl2_encoder_context_t(stream, protocol)
keunyoungb85b2752013-03-08 12:28:03 -080072{
Lingfeng Yange6556dc2017-01-09 12:04:12 -080073 m_currMajorVersion = 2;
74 m_currMinorVersion = 0;
keunyoungb85b2752013-03-08 12:28:03 -080075 m_initialized = false;
76 m_state = NULL;
77 m_error = GL_NO_ERROR;
78 m_num_compressedTextureFormats = 0;
Lizhe Liue41f4ef2015-05-27 11:13:23 +080079 m_max_cubeMapTextureSize = 0;
80 m_max_renderBufferSize = 0;
81 m_max_textureSize = 0;
Lingfeng Yang46153ab2017-01-09 13:37:22 -080082 m_max_3d_textureSize = 0;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -080083 m_max_vertexAttribStride = 0;
keunyoungb85b2752013-03-08 12:28:03 -080084 m_compressedTextureFormats = NULL;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010085
Lingfeng Yang46153ab2017-01-09 13:37:22 -080086 m_ssbo_offset_align = 0;
87 m_ubo_offset_align = 0;
88
Lingfeng Yangde51dfb2016-10-17 22:48:59 -070089 m_drawCallFlushCount = 0;
90 m_primitiveRestartEnabled = false;
91 m_primitiveRestartIndex = 0;
92
Lingfeng Yang07289902017-01-27 12:26:19 -080093 // overrides
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010094#define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name
Lingfeng Yange6556dc2017-01-09 12:04:12 -080095#define OVERRIDE_CUSTOM(name) this-> name = &s_##name
96#define OVERRIDEWITH(name, target) do { \
97 m_##target##_enc = this-> target; \
98 this-> target = &s_##name; \
99} while(0)
100#define OVERRIDEOES(name) OVERRIDEWITH(name, name##OES)
bohu56bf82f2014-10-17 15:35:48 -0700101
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100102 OVERRIDE(glFlush);
103 OVERRIDE(glPixelStorei);
104 OVERRIDE(glGetString);
105 OVERRIDE(glBindBuffer);
106 OVERRIDE(glBufferData);
107 OVERRIDE(glBufferSubData);
108 OVERRIDE(glDeleteBuffers);
109 OVERRIDE(glDrawArrays);
110 OVERRIDE(glDrawElements);
111 OVERRIDE(glGetIntegerv);
112 OVERRIDE(glGetFloatv);
113 OVERRIDE(glGetBooleanv);
114 OVERRIDE(glVertexAttribPointer);
115 OVERRIDE(glEnableVertexAttribArray);
116 OVERRIDE(glDisableVertexAttribArray);
117 OVERRIDE(glGetVertexAttribiv);
118 OVERRIDE(glGetVertexAttribfv);
119 OVERRIDE(glGetVertexAttribPointerv);
keunyoungb85b2752013-03-08 12:28:03 -0800120
Bo Hu73568cd2015-01-20 16:29:50 -0800121 this->glShaderBinary = &s_glShaderBinary;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100122 this->glShaderSource = &s_glShaderSource;
123 this->glFinish = &s_glFinish;
keunyoungb85b2752013-03-08 12:28:03 -0800124
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100125 OVERRIDE(glGetError);
126 OVERRIDE(glLinkProgram);
127 OVERRIDE(glDeleteProgram);
128 OVERRIDE(glGetUniformiv);
129 OVERRIDE(glGetUniformfv);
130 OVERRIDE(glCreateProgram);
131 OVERRIDE(glCreateShader);
132 OVERRIDE(glDeleteShader);
133 OVERRIDE(glAttachShader);
134 OVERRIDE(glDetachShader);
135 OVERRIDE(glGetAttachedShaders);
136 OVERRIDE(glGetShaderSource);
137 OVERRIDE(glGetShaderInfoLog);
138 OVERRIDE(glGetProgramInfoLog);
139
140 OVERRIDE(glGetUniformLocation);
141 OVERRIDE(glUseProgram);
142
143 OVERRIDE(glUniform1f);
144 OVERRIDE(glUniform1fv);
145 OVERRIDE(glUniform1i);
146 OVERRIDE(glUniform1iv);
147 OVERRIDE(glUniform2f);
148 OVERRIDE(glUniform2fv);
149 OVERRIDE(glUniform2i);
150 OVERRIDE(glUniform2iv);
151 OVERRIDE(glUniform3f);
152 OVERRIDE(glUniform3fv);
153 OVERRIDE(glUniform3i);
154 OVERRIDE(glUniform3iv);
155 OVERRIDE(glUniform4f);
156 OVERRIDE(glUniform4fv);
157 OVERRIDE(glUniform4i);
158 OVERRIDE(glUniform4iv);
159 OVERRIDE(glUniformMatrix2fv);
160 OVERRIDE(glUniformMatrix3fv);
161 OVERRIDE(glUniformMatrix4fv);
162
163 OVERRIDE(glActiveTexture);
164 OVERRIDE(glBindTexture);
165 OVERRIDE(glDeleteTextures);
166 OVERRIDE(glGetTexParameterfv);
167 OVERRIDE(glGetTexParameteriv);
168 OVERRIDE(glTexParameterf);
169 OVERRIDE(glTexParameterfv);
170 OVERRIDE(glTexParameteri);
171 OVERRIDE(glTexParameteriv);
bohu26a92982014-11-25 16:50:37 -0800172 OVERRIDE(glTexImage2D);
Yahan Zhou2a208292016-06-22 15:36:04 -0700173 OVERRIDE(glTexSubImage2D);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -0700174 OVERRIDE(glCopyTexImage2D);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700175
176 OVERRIDE(glGenRenderbuffers);
177 OVERRIDE(glDeleteRenderbuffers);
178 OVERRIDE(glBindRenderbuffer);
Lingfeng Yang69066602016-04-12 09:29:11 -0700179 OVERRIDE(glRenderbufferStorage);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700180 OVERRIDE(glFramebufferRenderbuffer);
181
182 OVERRIDE(glGenFramebuffers);
183 OVERRIDE(glDeleteFramebuffers);
184 OVERRIDE(glBindFramebuffer);
185 OVERRIDE(glFramebufferTexture2D);
186 OVERRIDE(glFramebufferTexture3DOES);
187 OVERRIDE(glGetFramebufferAttachmentParameteriv);
Lingfeng Yang69066602016-04-12 09:29:11 -0700188
189 OVERRIDE(glCheckFramebufferStatus);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800190
191 OVERRIDE(glGenVertexArrays);
192 OVERRIDE(glDeleteVertexArrays);
193 OVERRIDE(glBindVertexArray);
194 OVERRIDEOES(glGenVertexArrays);
195 OVERRIDEOES(glDeleteVertexArrays);
196 OVERRIDEOES(glBindVertexArray);
197
198 OVERRIDE_CUSTOM(glMapBufferRange);
199 OVERRIDE_CUSTOM(glUnmapBuffer);
200 OVERRIDE_CUSTOM(glFlushMappedBufferRange);
201
202 OVERRIDE(glCompressedTexImage2D);
203 OVERRIDE(glCompressedTexSubImage2D);
204
205 OVERRIDE(glBindBufferRange);
206 OVERRIDE(glBindBufferBase);
207
208 OVERRIDE(glCopyBufferSubData);
209
210 OVERRIDE(glGetBufferParameteriv);
211 OVERRIDE(glGetBufferParameteri64v);
212 OVERRIDE(glGetBufferPointerv);
213
214 OVERRIDE_CUSTOM(glGetUniformIndices);
215
216 OVERRIDE(glUniform1ui);
217 OVERRIDE(glUniform2ui);
218 OVERRIDE(glUniform3ui);
219 OVERRIDE(glUniform4ui);
220 OVERRIDE(glUniform1uiv);
221 OVERRIDE(glUniform2uiv);
222 OVERRIDE(glUniform3uiv);
223 OVERRIDE(glUniform4uiv);
224 OVERRIDE(glUniformMatrix2x3fv);
225 OVERRIDE(glUniformMatrix3x2fv);
226 OVERRIDE(glUniformMatrix2x4fv);
227 OVERRIDE(glUniformMatrix4x2fv);
228 OVERRIDE(glUniformMatrix3x4fv);
229 OVERRIDE(glUniformMatrix4x3fv);
230
231 OVERRIDE(glGetUniformuiv);
232 OVERRIDE(glGetActiveUniformBlockiv);
233
234 OVERRIDE(glGetVertexAttribIiv);
235 OVERRIDE(glGetVertexAttribIuiv);
236
237 OVERRIDE_CUSTOM(glVertexAttribIPointer);
238
239 OVERRIDE(glVertexAttribDivisor);
240
241 OVERRIDE(glRenderbufferStorageMultisample);
242 OVERRIDE(glDrawBuffers);
243 OVERRIDE(glReadBuffer);
244 OVERRIDE(glFramebufferTextureLayer);
245 OVERRIDE(glTexStorage2D);
246
247 OVERRIDE_CUSTOM(glTransformFeedbackVaryings);
248 OVERRIDE(glBeginTransformFeedback);
249 OVERRIDE(glEndTransformFeedback);
250 OVERRIDE(glPauseTransformFeedback);
251 OVERRIDE(glResumeTransformFeedback);
252
253 OVERRIDE(glTexImage3D);
254 OVERRIDE(glTexSubImage3D);
255 OVERRIDE(glTexStorage3D);
256 OVERRIDE(glCompressedTexImage3D);
257 OVERRIDE(glCompressedTexSubImage3D);
258
259 OVERRIDE(glDrawArraysInstanced);
260 OVERRIDE_CUSTOM(glDrawElementsInstanced);
261 OVERRIDE_CUSTOM(glDrawRangeElements);
262
263 OVERRIDE_CUSTOM(glGetStringi);
264 OVERRIDE(glGetProgramBinary);
265 OVERRIDE(glReadPixels);
266
267 OVERRIDE(glEnable);
268 OVERRIDE(glDisable);
269 OVERRIDE(glClearBufferiv);
270 OVERRIDE(glClearBufferuiv);
271 OVERRIDE(glClearBufferfv);
272 OVERRIDE(glBlitFramebuffer);
273 OVERRIDE_CUSTOM(glGetInternalformativ);
274
275 OVERRIDE(glGenerateMipmap);
276
277 OVERRIDE(glBindSampler);
278
Lingfeng Yangf000ab42017-01-11 18:31:38 -0800279 OVERRIDE_CUSTOM(glFenceSync);
280 OVERRIDE_CUSTOM(glClientWaitSync);
281 OVERRIDE_CUSTOM(glWaitSync);
282 OVERRIDE_CUSTOM(glDeleteSync);
283 OVERRIDE_CUSTOM(glIsSync);
284 OVERRIDE_CUSTOM(glGetSynciv);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800285
286 OVERRIDE(glGetIntegeri_v);
287 OVERRIDE(glGetInteger64i_v);
288
289 OVERRIDE(glGetShaderiv);
290
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800291 OVERRIDE(glActiveShaderProgram);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800292 OVERRIDE_CUSTOM(glCreateShaderProgramv);
293 OVERRIDE(glProgramUniform1f);
294 OVERRIDE(glProgramUniform1fv);
295 OVERRIDE(glProgramUniform1i);
296 OVERRIDE(glProgramUniform1iv);
297 OVERRIDE(glProgramUniform1ui);
298 OVERRIDE(glProgramUniform1uiv);
299 OVERRIDE(glProgramUniform2f);
300 OVERRIDE(glProgramUniform2fv);
301 OVERRIDE(glProgramUniform2i);
302 OVERRIDE(glProgramUniform2iv);
303 OVERRIDE(glProgramUniform2ui);
304 OVERRIDE(glProgramUniform2uiv);
305 OVERRIDE(glProgramUniform3f);
306 OVERRIDE(glProgramUniform3fv);
307 OVERRIDE(glProgramUniform3i);
308 OVERRIDE(glProgramUniform3iv);
309 OVERRIDE(glProgramUniform3ui);
310 OVERRIDE(glProgramUniform3uiv);
311 OVERRIDE(glProgramUniform4f);
312 OVERRIDE(glProgramUniform4fv);
313 OVERRIDE(glProgramUniform4i);
314 OVERRIDE(glProgramUniform4iv);
315 OVERRIDE(glProgramUniform4ui);
316 OVERRIDE(glProgramUniform4uiv);
317 OVERRIDE(glProgramUniformMatrix2fv);
318 OVERRIDE(glProgramUniformMatrix2x3fv);
319 OVERRIDE(glProgramUniformMatrix2x4fv);
320 OVERRIDE(glProgramUniformMatrix3fv);
321 OVERRIDE(glProgramUniformMatrix3x2fv);
322 OVERRIDE(glProgramUniformMatrix3x4fv);
323 OVERRIDE(glProgramUniformMatrix4fv);
324 OVERRIDE(glProgramUniformMatrix4x2fv);
325 OVERRIDE(glProgramUniformMatrix4x3fv);
326
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800327 OVERRIDE(glProgramParameteri);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800328 OVERRIDE(glUseProgramStages);
329 OVERRIDE(glBindProgramPipeline);
330
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800331 OVERRIDE(glGetProgramResourceiv);
332 OVERRIDE(glGetProgramResourceIndex);
333 OVERRIDE(glGetProgramResourceLocation);
334 OVERRIDE(glGetProgramResourceName);
335 OVERRIDE(glGetProgramPipelineInfoLog);
336
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800337 OVERRIDE(glVertexAttribFormat);
338 OVERRIDE(glVertexAttribIFormat);
339 OVERRIDE(glVertexBindingDivisor);
340 OVERRIDE(glVertexAttribBinding);
341 OVERRIDE(glBindVertexBuffer);
342
343 OVERRIDE_CUSTOM(glDrawArraysIndirect);
344 OVERRIDE_CUSTOM(glDrawElementsIndirect);
345
346 OVERRIDE(glTexStorage2DMultisample);
keunyoungb85b2752013-03-08 12:28:03 -0800347}
348
349GL2Encoder::~GL2Encoder()
350{
351 delete m_compressedTextureFormats;
352}
353
354GLenum GL2Encoder::s_glGetError(void * self)
355{
356 GL2Encoder *ctx = (GL2Encoder *)self;
357 GLenum err = ctx->getError();
358 if(err != GL_NO_ERROR) {
359 ctx->setError(GL_NO_ERROR);
360 return err;
361 }
362
363 return ctx->m_glGetError_enc(self);
Yahan Zhouae30fe82016-08-10 21:15:45 +0000364
keunyoungb85b2752013-03-08 12:28:03 -0800365}
366
367void GL2Encoder::s_glFlush(void *self)
368{
369 GL2Encoder *ctx = (GL2Encoder *) self;
370 ctx->m_glFlush_enc(self);
371 ctx->m_stream->flush();
372}
373
374const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
375{
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800376 GL2Encoder *ctx = (GL2Encoder *)self;
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100377
keunyoungb85b2752013-03-08 12:28:03 -0800378 GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800379 RET_AND_SET_ERROR_IF(
380 name != GL_VENDOR &&
381 name != GL_RENDERER &&
382 name != GL_VERSION &&
383 name != GL_EXTENSIONS,
384 GL_INVALID_ENUM,
385 retval);
keunyoungb85b2752013-03-08 12:28:03 -0800386 switch(name) {
387 case GL_VENDOR:
388 retval = gVendorString;
389 break;
390 case GL_RENDERER:
391 retval = gRendererString;
392 break;
393 case GL_VERSION:
394 retval = gVersionString;
395 break;
396 case GL_EXTENSIONS:
397 retval = gExtensionsString;
398 break;
399 }
400 return retval;
401}
402
403void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
404{
405 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800406 SET_ERROR_IF(!GLESv2Validation::pixelStoreParam(ctx, param), GL_INVALID_ENUM);
407 SET_ERROR_IF(!GLESv2Validation::pixelStoreValue(param, value), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800408 ctx->m_glPixelStorei_enc(ctx, param, value);
409 assert(ctx->m_state != NULL);
410 ctx->m_state->setPixelStore(param, value);
411}
keunyoungb85b2752013-03-08 12:28:03 -0800412void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
413{
414 GL2Encoder *ctx = (GL2Encoder *) self;
415 assert(ctx->m_state != NULL);
416 ctx->m_state->bindBuffer(target, id);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800417 ctx->m_state->addBuffer(id);
keunyoungb85b2752013-03-08 12:28:03 -0800418 // TODO set error state if needed;
419 ctx->m_glBindBuffer_enc(self, target, id);
420}
421
422void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
423{
424 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800425 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800426 GLuint bufferId = ctx->m_state->getBuffer(target);
427 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
428 SET_ERROR_IF(size<0, GL_INVALID_VALUE);
429
430 ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800431 ctx->m_shared->setBufferUsage(bufferId, usage);
keunyoungb85b2752013-03-08 12:28:03 -0800432 ctx->m_glBufferData_enc(self, target, size, data, usage);
433}
434
435void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
436{
437 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800438 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800439 GLuint bufferId = ctx->m_state->getBuffer(target);
440 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800441 SET_ERROR_IF(ctx->isBufferTargetMapped(target), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800442
443 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
444 SET_ERROR_IF(res, res);
445
446 ctx->m_glBufferSubData_enc(self, target, offset, size, data);
447}
448
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800449void GL2Encoder::s_glGenBuffers(void* self, GLsizei n, GLuint* buffers) {
450 GL2Encoder *ctx = (GL2Encoder *) self;
451 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
452 ctx->m_glGenBuffers_enc(self, n, buffers);
453 for (int i = 0; i < n; i++) {
454 ctx->m_state->addBuffer(buffers[i]);
455 }
456}
457
keunyoungb85b2752013-03-08 12:28:03 -0800458void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
459{
460 GL2Encoder *ctx = (GL2Encoder *) self;
461 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
462 for (int i=0; i<n; i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800463 // Technically if the buffer is mapped, we should unmap it, but we won't
464 // use it anymore after this :)
keunyoungb85b2752013-03-08 12:28:03 -0800465 ctx->m_shared->deleteBufferData(buffers[i]);
bohub0f0cdf2014-11-06 18:08:07 -0800466 ctx->m_state->unBindBuffer(buffers[i]);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800467 ctx->m_state->removeBuffer(buffers[i]);
keunyoungb85b2752013-03-08 12:28:03 -0800468 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
469 }
470}
471
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700472static bool isValidVertexAttribIndex(void *self, GLuint indx)
473{
Lingfeng Yang07289902017-01-27 12:26:19 -0800474 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700475 GLint maxIndex;
476 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
477 return indx < maxIndex;
478}
479
Lingfeng Yang07289902017-01-27 12:26:19 -0800480#define VALIDATE_VERTEX_ATTRIB_INDEX(index) \
481 SET_ERROR_WITH_MESSAGE_IF( \
482 !isValidVertexAttribIndex(self, index), GL_INVALID_VALUE, \
483 GLESv2Validation::vertexAttribIndexRangeErrorMsg, (ctx, index)); \
484
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100485void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
keunyoungb85b2752013-03-08 12:28:03 -0800486{
487 GL2Encoder *ctx = (GL2Encoder *)self;
488 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -0800489 VALIDATE_VERTEX_ATTRIB_INDEX(indx);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700490 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800491 SET_ERROR_IF(!GLESv2Validation::vertexAttribType(ctx, type), GL_INVALID_ENUM);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700492 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800493 SET_ERROR_IF((type == GL_INT_2_10_10_10_REV ||
494 type == GL_UNSIGNED_INT_2_10_10_10_REV) &&
495 size != 4,
496 GL_INVALID_OPERATION);
497 ctx->m_state->setVertexAttribBinding(indx, indx);
498 ctx->m_state->setVertexAttribFormat(indx, size, type, normalized, 0, false);
499
500 GLsizei effectiveStride = stride;
501 if (stride == 0) {
502 effectiveStride = glSizeof(type) * size;
503 switch (type) {
504 case GL_INT_2_10_10_10_REV:
505 case GL_UNSIGNED_INT_2_10_10_10_REV:
506 effectiveStride /= 4;
507 break;
508 default:
509 break;
510 }
511 }
512
513 ctx->m_state->bindIndexedBuffer(0, indx, ctx->m_state->currentArrayVbo(), (uintptr_t)ptr, 0, stride, effectiveStride);
514
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800515 if (ctx->m_state->currentArrayVbo() != 0) {
516 ctx->glVertexAttribPointerOffset(ctx, indx, size, type, normalized, stride, (uintptr_t)ptr);
517 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800518 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && ptr, GL_INVALID_OPERATION);
519 // wait for client-array handler
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800520 }
keunyoungb85b2752013-03-08 12:28:03 -0800521}
522
523void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
524{
525 GL2Encoder *ctx = (GL2Encoder *) self;
526 assert(ctx->m_state != NULL);
527 GLClientState* state = ctx->m_state;
528
529 switch (param) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800530 case GL_MAJOR_VERSION:
531 *ptr = ctx->m_currMajorVersion;
532 break;
533 case GL_MINOR_VERSION:
534 *ptr = ctx->m_currMinorVersion;
535 break;
keunyoungb85b2752013-03-08 12:28:03 -0800536 case GL_NUM_SHADER_BINARY_FORMATS:
537 *ptr = 0;
538 break;
539 case GL_SHADER_BINARY_FORMATS:
540 // do nothing
541 break;
542
543 case GL_COMPRESSED_TEXTURE_FORMATS: {
544 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
545 if (ctx->m_num_compressedTextureFormats > 0 &&
546 compressedTextureFormats != NULL) {
547 memcpy(ptr, compressedTextureFormats,
548 ctx->m_num_compressedTextureFormats * sizeof(GLint));
549 }
550 break;
551 }
552
553 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
554 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
555 case GL_MAX_TEXTURE_IMAGE_UNITS:
556 ctx->m_glGetIntegerv_enc(self, param, ptr);
557 *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
558 break;
559
560 case GL_TEXTURE_BINDING_2D:
561 *ptr = state->getBoundTexture(GL_TEXTURE_2D);
562 break;
563 case GL_TEXTURE_BINDING_EXTERNAL_OES:
564 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
565 break;
566
Lingfeng Yangb0176982016-03-01 21:27:49 -0800567 case GL_MAX_VERTEX_ATTRIBS:
568 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
569 ctx->m_glGetIntegerv_enc(self, param, ptr);
570 ctx->m_state->setMaxVertexAttribs(*ptr);
Yahan Zhoua5c36842016-06-01 12:49:39 -0700571 }
572 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800573 case GL_MAX_VERTEX_ATTRIB_STRIDE:
574 if (ctx->m_max_vertexAttribStride != 0) {
575 *ptr = ctx->m_max_vertexAttribStride;
576 } else {
577 ctx->m_glGetIntegerv_enc(self, param, ptr);
578 ctx->m_max_vertexAttribStride = *ptr;
579 }
580 break;
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800581 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
582 if (ctx->m_max_cubeMapTextureSize != 0) {
583 *ptr = ctx->m_max_cubeMapTextureSize;
584 } else {
585 ctx->m_glGetIntegerv_enc(self, param, ptr);
586 ctx->m_max_cubeMapTextureSize = *ptr;
587 }
588 break;
589 case GL_MAX_RENDERBUFFER_SIZE:
590 if (ctx->m_max_renderBufferSize != 0) {
591 *ptr = ctx->m_max_renderBufferSize;
592 } else {
593 ctx->m_glGetIntegerv_enc(self, param, ptr);
594 ctx->m_max_renderBufferSize = *ptr;
595 }
596 break;
597 case GL_MAX_TEXTURE_SIZE:
598 if (ctx->m_max_textureSize != 0) {
599 *ptr = ctx->m_max_textureSize;
600 } else {
601 ctx->m_glGetIntegerv_enc(self, param, ptr);
602 ctx->m_max_textureSize = *ptr;
Lingfeng Yangb0176982016-03-01 21:27:49 -0800603 }
604 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800605 case GL_MAX_3D_TEXTURE_SIZE:
606 if (ctx->m_max_3d_textureSize != 0) {
607 *ptr = ctx->m_max_3d_textureSize;
608 } else {
609 ctx->m_glGetIntegerv_enc(self, param, ptr);
610 ctx->m_max_3d_textureSize = *ptr;
611 }
612 break;
613 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
614 if (ctx->m_ssbo_offset_align != 0) {
615 *ptr = ctx->m_ssbo_offset_align;
616 } else {
617 ctx->m_glGetIntegerv_enc(self, param, ptr);
618 ctx->m_ssbo_offset_align = *ptr;
619 }
620 break;
621 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
622 if (ctx->m_ubo_offset_align != 0) {
623 *ptr = ctx->m_ubo_offset_align;
624 } else {
625 ctx->m_glGetIntegerv_enc(self, param, ptr);
626 ctx->m_ubo_offset_align = *ptr;
627 }
628 break;
629 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
630 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
631 case GL_MAX_SAMPLES:
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800632 case GL_MAX_COLOR_TEXTURE_SAMPLES:
633 case GL_MAX_INTEGER_SAMPLES:
634 case GL_MAX_DEPTH_TEXTURE_SAMPLES:
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800635 *ptr = 4;
636 break;
keunyoungb85b2752013-03-08 12:28:03 -0800637 default:
638 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
639 ctx->m_glGetIntegerv_enc(self, param, ptr);
640 }
641 break;
642 }
643}
644
645
646void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
647{
648 GL2Encoder *ctx = (GL2Encoder *)self;
649 assert(ctx->m_state != NULL);
650 GLClientState* state = ctx->m_state;
651
652 switch (param) {
653 case GL_NUM_SHADER_BINARY_FORMATS:
654 *ptr = 0;
655 break;
656 case GL_SHADER_BINARY_FORMATS:
657 // do nothing
658 break;
659
660 case GL_COMPRESSED_TEXTURE_FORMATS: {
661 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
662 if (ctx->m_num_compressedTextureFormats > 0 &&
663 compressedTextureFormats != NULL) {
664 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
665 ptr[i] = (GLfloat) compressedTextureFormats[i];
666 }
667 }
668 break;
669 }
670
671 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
672 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
673 case GL_MAX_TEXTURE_IMAGE_UNITS:
674 ctx->m_glGetFloatv_enc(self, param, ptr);
675 *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
676 break;
677
678 case GL_TEXTURE_BINDING_2D:
679 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
680 break;
681 case GL_TEXTURE_BINDING_EXTERNAL_OES:
682 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
683 break;
684
685 default:
686 if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
687 ctx->m_glGetFloatv_enc(self, param, ptr);
688 }
689 break;
690 }
691}
692
693
694void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
695{
696 GL2Encoder *ctx = (GL2Encoder *)self;
697 assert(ctx->m_state != NULL);
698 GLClientState* state = ctx->m_state;
699
700 switch (param) {
701 case GL_NUM_SHADER_BINARY_FORMATS:
702 *ptr = GL_FALSE;
703 break;
704 case GL_SHADER_BINARY_FORMATS:
705 // do nothing
706 break;
707
708 case GL_COMPRESSED_TEXTURE_FORMATS: {
709 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
710 if (ctx->m_num_compressedTextureFormats > 0 &&
711 compressedTextureFormats != NULL) {
712 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
713 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
714 }
715 }
716 break;
717 }
718
719 case GL_TEXTURE_BINDING_2D:
720 *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
721 break;
722 case GL_TEXTURE_BINDING_EXTERNAL_OES:
723 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
724 ? GL_TRUE : GL_FALSE;
725 break;
726
727 default:
728 if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
729 ctx->m_glGetBooleanv_enc(self, param, ptr);
730 }
bohu05101d22014-11-17 16:28:42 -0800731 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
keunyoungb85b2752013-03-08 12:28:03 -0800732 break;
733 }
734}
735
736
737void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
738{
739 GL2Encoder *ctx = (GL2Encoder *)self;
740 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -0800741 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800742 ctx->m_glEnableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800743 ctx->m_state->enable(index, 1);
744}
745
746void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
747{
748 GL2Encoder *ctx = (GL2Encoder *)self;
749 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -0800750 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800751 ctx->m_glDisableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800752 ctx->m_state->enable(index, 0);
753}
754
755
756void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
757{
758 GL2Encoder *ctx = (GL2Encoder *)self;
759 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700760 GLint maxIndex;
761 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
762 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800763
764 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
765 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
766 }
767}
768
769void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
770{
771 GL2Encoder *ctx = (GL2Encoder *)self;
772 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700773 GLint maxIndex;
774 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
775 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800776
777 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
778 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
779 }
780}
781
782void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
783{
784 GL2Encoder *ctx = (GL2Encoder *)self;
785 if (ctx->m_state == NULL) return;
Lingfeng Yang5e100432016-04-08 12:46:42 -0700786 GLint maxIndex;
787 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
788 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
789 SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100790 (void)pname;
791
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800792 *pointer = (GLvoid*)(ctx->m_state->getCurrAttributeBindingInfo(index).offset);
keunyoungb85b2752013-03-08 12:28:03 -0800793}
794
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700795void GL2Encoder::calcIndexRange(const void* indices,
796 GLenum type,
797 GLsizei count,
798 int* minIndex_out,
799 int* maxIndex_out) {
800 switch(type) {
801 case GL_BYTE:
802 case GL_UNSIGNED_BYTE:
803 GLUtils::minmaxExcept(
804 (unsigned char *)indices, count,
805 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800806 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned char>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700807 break;
808 case GL_SHORT:
809 case GL_UNSIGNED_SHORT:
810 GLUtils::minmaxExcept(
811 (unsigned short *)indices, count,
812 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800813 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned short>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700814 break;
815 case GL_INT:
816 case GL_UNSIGNED_INT:
817 GLUtils::minmaxExcept(
818 (unsigned int *)indices, count,
819 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800820 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned int>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700821 break;
822 default:
823 ALOGE("unsupported index buffer type %d\n", type);
824 }
825}
826
827void* GL2Encoder::recenterIndices(const void* src,
828 GLenum type,
829 GLsizei count,
830 int minIndex) {
831
832 void* adjustedIndices = (void*)src;
833
834 if (minIndex != 0) {
835 adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count);
836 switch(type) {
837 case GL_BYTE:
838 case GL_UNSIGNED_BYTE:
839 GLUtils::shiftIndicesExcept(
840 (unsigned char *)src,
841 (unsigned char *)adjustedIndices,
842 count, -minIndex,
843 m_primitiveRestartEnabled,
844 (unsigned char)m_primitiveRestartIndex);
845 break;
846 case GL_SHORT:
847 case GL_UNSIGNED_SHORT:
848 GLUtils::shiftIndicesExcept(
849 (unsigned short *)src,
850 (unsigned short *)adjustedIndices,
851 count, -minIndex,
852 m_primitiveRestartEnabled,
853 (unsigned short)m_primitiveRestartIndex);
854 break;
855 case GL_INT:
856 case GL_UNSIGNED_INT:
857 GLUtils::shiftIndicesExcept(
858 (unsigned int *)src,
859 (unsigned int *)adjustedIndices,
860 count, -minIndex,
861 m_primitiveRestartEnabled,
862 (unsigned int)m_primitiveRestartIndex);
863 break;
864 default:
865 ALOGE("unsupported index buffer type %d\n", type);
866 }
867 }
868
869 return adjustedIndices;
870}
871
872void GL2Encoder::getBufferIndexRange(BufferData* buf,
873 const void* dataWithOffset,
874 GLenum type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -0800875 size_t count,
876 size_t offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700877 int* minIndex_out,
878 int* maxIndex_out) {
879
880 if (buf->m_indexRangeCache.findRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -0800881 type, offset, count,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700882 m_primitiveRestartEnabled,
883 minIndex_out,
884 maxIndex_out)) {
885 return;
886 }
887
888 calcIndexRange(dataWithOffset, type, count, minIndex_out, maxIndex_out);
889
890 buf->m_indexRangeCache.addRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -0800891 type, offset, count, m_primitiveRestartEnabled,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700892 *minIndex_out, *maxIndex_out);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800893
894 ALOGV("%s: got range [%u %u] pr? %d", __FUNCTION__, *minIndex_out, *maxIndex_out, m_primitiveRestartEnabled);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700895}
keunyoungb85b2752013-03-08 12:28:03 -0800896
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800897// For detecting legacy usage of glVertexAttribPointer
898void GL2Encoder::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) const {
899 if (hasClientArrays) *hasClientArrays = false;
900 if (hasVBOs) *hasVBOs = false;
901
902 for (int i = 0; i < m_state->nLocations(); i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800903 const GLClientState::VertexAttribState& state = m_state->getState(i);
904 if (state.enabled) {
905 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
906 GLuint bufferObject = curr_binding.buffer;
907 if (bufferObject == 0 && curr_binding.offset && hasClientArrays) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800908 *hasClientArrays = true;
909 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800910 if (bufferObject != 0 && hasVBOs) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800911 *hasVBOs = true;
912 }
913 }
914 }
915}
916
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800917void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count, bool hasClientArrays, GLsizei primcount)
keunyoungb85b2752013-03-08 12:28:03 -0800918{
919 assert(m_state);
920
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800921 GLuint currentVao = m_state->currentVertexArrayObject();
Lingfeng Yang398162b2016-05-26 14:18:33 -0700922 GLuint lastBoundVbo = m_state->currentArrayVbo();
keunyoungb85b2752013-03-08 12:28:03 -0800923 for (int i = 0; i < m_state->nLocations(); i++) {
924 bool enableDirty;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800925 const GLClientState::VertexAttribState& state = m_state->getStateAndEnableDirty(i, &enableDirty);
keunyoungb85b2752013-03-08 12:28:03 -0800926
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800927 if (!enableDirty && !state.enabled) {
keunyoungb85b2752013-03-08 12:28:03 -0800928 continue;
929 }
930
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800931 if (state.enabled) {
932 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
933 GLuint bufferObject = curr_binding.buffer;
934 if (hasClientArrays && lastBoundVbo != bufferObject) {
935 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, bufferObject);
936 lastBoundVbo = bufferObject;
Lingfeng Yang398162b2016-05-26 14:18:33 -0700937 }
keunyoungb85b2752013-03-08 12:28:03 -0800938
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800939 int divisor = curr_binding.divisor;
940 int stride = curr_binding.stride;
941 int effectiveStride = curr_binding.effectiveStride;
942 uintptr_t offset = curr_binding.offset;
943 int firstIndex = effectiveStride * first;
keunyoungb85b2752013-03-08 12:28:03 -0800944
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800945 if (bufferObject == 0) {
946 unsigned int datalen = state.elementSize * count;
947 if (divisor && primcount) {
948 ALOGV("%s: divisor for att %d: %d, w/ stride %d (effective stride %d) size %d type 0x%x) datalen %u",
949 __FUNCTION__, i, divisor, state.stride, effectiveStride, state.elementSize, state.type, datalen);
950 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
951 datalen = state.elementSize * actual_count;
952 ALOGV("%s: actual datalen %u", __FUNCTION__, datalen);
953 }
954 if (state.elementSize == 0) {
Yahan Zhou3f2f1b42016-12-01 13:49:44 -0800955 // The vertex attribute array is uninitialized. Abandon it.
956 ALOGE("a vertex attribute array is uninitialized. Skipping corresponding vertex attribute.");
957 this->m_glDisableVertexAttribArray_enc(this, i);
958 continue;
959 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700960 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang000cf4c2017-01-25 08:09:02 -0800961
962 if (datalen && (!offset || !((unsigned char*)offset + firstIndex))) {
963 ALOGD("%s: bad offset / len!!!!!", __FUNCTION__);
964 continue;
965 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800966 if (state.isInt) {
967 this->glVertexAttribIPointerDataAEMU(this, i, state.size, state.type, stride, (unsigned char *)offset + firstIndex, datalen);
968 } else {
969 this->glVertexAttribPointerData(this, i, state.size, state.type, state.normalized, stride, (unsigned char *)offset + firstIndex, datalen);
970 }
keunyoungb85b2752013-03-08 12:28:03 -0800971 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800972 const BufferData* buf = m_shared->getBufferData(bufferObject);
Yahan Zhou5507c042016-06-01 17:24:28 -0700973 // The following expression actually means bufLen = stride*count;
974 // But the last element doesn't have to fill up the whole stride.
975 // So it becomes the current form.
Lingfeng Yang5fe99012017-01-18 09:17:09 -0800976 unsigned int bufLen = effectiveStride * (count ? (count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800977 if (divisor && primcount) {
978 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
Lingfeng Yang5fe99012017-01-18 09:17:09 -0800979 bufLen = effectiveStride * (actual_count ? (actual_count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800980 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700981 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800982 if (hasClientArrays) {
983 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800984 if (state.isInt) {
985 this->glVertexAttribIPointerOffsetAEMU(this, i, state.size, state.type, stride, offset + firstIndex);
986 } else {
987 this->glVertexAttribPointerOffset(this, i, state.size, state.type, state.normalized, stride, offset + firstIndex);
988 }
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800989 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700990 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800991 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=%p", buf);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -0800992 if (buf) {
993 ALOGE("Out of bounds vertex attribute info: "
994 "clientArray? %d attribute %d vbo %u allocedBufferSize %u bufferDataSpecified? %d wantedStart %u wantedEnd %u",
995 hasClientArrays, i, bufferObject, buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen);
996 }
997 m_glDisableVertexAttribArray_enc(this, i);
Yahan Zhou5507c042016-06-01 17:24:28 -0700998 }
keunyoungb85b2752013-03-08 12:28:03 -0800999 }
1000 } else {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001001 if (hasClientArrays) {
1002 this->m_glDisableVertexAttribArray_enc(this, i);
1003 }
keunyoungb85b2752013-03-08 12:28:03 -08001004 }
1005 }
Lingfeng Yang398162b2016-05-26 14:18:33 -07001006
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001007 if (hasClientArrays && lastBoundVbo != m_state->currentArrayVbo()) {
Lingfeng Yang398162b2016-05-26 14:18:33 -07001008 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
1009 }
keunyoungb85b2752013-03-08 12:28:03 -08001010}
1011
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001012void GL2Encoder::flushDrawCall() {
Lingfeng Yang1ebb33c2017-01-19 08:04:48 -08001013 // This used to be every other draw call, but
1014 // now that we are using real GPU buffers on host,
1015 // set this to every 200 draw calls
1016 // (tuned on z840 linux NVIDIA Quadro K2200)
1017 if (m_drawCallFlushCount % 200 == 0) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001018 m_stream->flush();
1019 }
1020 m_drawCallFlushCount++;
1021}
1022
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001023static bool isValidDrawMode(GLenum mode)
1024{
1025 bool retval = false;
1026 switch (mode) {
1027 case GL_POINTS:
1028 case GL_LINE_STRIP:
1029 case GL_LINE_LOOP:
1030 case GL_LINES:
1031 case GL_TRIANGLE_STRIP:
1032 case GL_TRIANGLE_FAN:
1033 case GL_TRIANGLES:
1034 retval = true;
1035 }
1036 return retval;
1037}
1038
keunyoungb85b2752013-03-08 12:28:03 -08001039void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
1040{
1041 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001042 assert(ctx->m_state != NULL);
1043 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1044 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhoud6217a52016-02-10 16:10:46 -08001045
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001046 bool has_client_vertex_arrays = false;
1047 bool has_indirect_arrays = false;
1048 ctx->getVBOUsage(&has_client_vertex_arrays,
1049 &has_indirect_arrays);
1050
1051 if (has_client_vertex_arrays ||
1052 (!has_client_vertex_arrays &&
1053 !has_indirect_arrays)) {
1054 ctx->sendVertexAttributes(first, count, true);
1055 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
1056 } else {
1057 ctx->sendVertexAttributes(0, count, false);
1058 ctx->m_glDrawArrays_enc(ctx, mode, first, count);
1059 }
keunyoungb85b2752013-03-08 12:28:03 -08001060}
1061
1062
1063void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
1064{
1065
1066 GL2Encoder *ctx = (GL2Encoder *)self;
1067 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001068 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1069 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -07001070 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001071 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001072
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001073 bool has_client_vertex_arrays = false;
keunyoungb85b2752013-03-08 12:28:03 -08001074 bool has_indirect_arrays = false;
1075 int nLocations = ctx->m_state->nLocations();
Yahan Zhou5507c042016-06-01 17:24:28 -07001076 GLintptr offset = 0;
keunyoungb85b2752013-03-08 12:28:03 -08001077
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001078 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
keunyoungb85b2752013-03-08 12:28:03 -08001079
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001080 if (!has_client_vertex_arrays && !has_indirect_arrays) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001081 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -07001082 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
1083 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001084 }
1085
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001086 BufferData* buf = NULL;
Yahan Zhou5507c042016-06-01 17:24:28 -07001087 int minIndex = 0, maxIndex = 0;
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001088
1089 // For validation/immediate index array purposes,
1090 // we need the min/max vertex index of the index array.
1091 // If the VBO != 0, this may not be the first time we have
1092 // used this particular index buffer. getBufferIndexRange
1093 // can more quickly get min/max vertex index by
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001094 // caching previous results.
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001095 if (ctx->m_state->currentIndexVbo() != 0) {
1096 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1097 offset = (GLintptr)indices;
1098 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
1099 ctx->getBufferIndexRange(buf,
1100 indices,
1101 type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001102 (size_t)count,
1103 (size_t)offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001104 &minIndex, &maxIndex);
1105 } else {
1106 // In this case, the |indices| field holds a real
1107 // array, so calculate the indices now. They will
1108 // also be needed to know how much data to
1109 // transfer to host.
1110 ctx->calcIndexRange(indices,
1111 type,
1112 count,
1113 &minIndex,
1114 &maxIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -07001115 }
1116
keunyoungb85b2752013-03-08 12:28:03 -08001117 bool adjustIndices = true;
1118 if (ctx->m_state->currentIndexVbo() != 0) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001119 if (!has_client_vertex_arrays) {
1120 ctx->sendVertexAttributes(0, maxIndex + 1, false);
keunyoungb85b2752013-03-08 12:28:03 -08001121 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -07001122 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001123 ctx->flushDrawCall();
keunyoungb85b2752013-03-08 12:28:03 -08001124 adjustIndices = false;
1125 } else {
1126 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1127 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001128 }
1129 }
1130 if (adjustIndices) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001131 void *adjustedIndices =
1132 ctx->recenterIndices(indices,
1133 type,
1134 count,
1135 minIndex);
keunyoungb85b2752013-03-08 12:28:03 -08001136
keunyoungb85b2752013-03-08 12:28:03 -08001137 if (has_indirect_arrays || 1) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001138 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
keunyoungb85b2752013-03-08 12:28:03 -08001139 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
1140 count * glSizeof(type));
1141 // XXX - OPTIMIZATION (see the other else branch) should be implemented
1142 if(!has_indirect_arrays) {
1143 //ALOGD("unoptimized drawelements !!!\n");
1144 }
1145 } else {
1146 // we are all direct arrays and immidate mode index array -
1147 // rebuild the arrays and the index array;
1148 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
1149 }
1150 }
1151}
1152
1153
1154GLint * GL2Encoder::getCompressedTextureFormats()
1155{
1156 if (m_compressedTextureFormats == NULL) {
1157 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
1158 &m_num_compressedTextureFormats);
1159 if (m_num_compressedTextureFormats > 0) {
1160 // get number of texture formats;
1161 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
1162 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
1163 }
1164 }
1165 return m_compressedTextureFormats;
1166}
1167
1168// Replace uses of samplerExternalOES with sampler2D, recording the names of
1169// modified shaders in data. Also remove
1170// #extension GL_OES_EGL_image_external : require
1171// statements.
1172//
1173// This implementation assumes the input has already been pre-processed. If not,
1174// a few cases will be mishandled:
1175//
1176// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
1177// the following code:
1178// #if 1
1179// uniform sampler2D mySampler;
1180// #else
1181// uniform samplerExternalOES mySampler;
1182// #endif
1183//
1184// 2. Comments that look like sampler declarations will be incorrectly modified
1185// and recorded:
1186// // samplerExternalOES hahaFooledYou
1187//
1188// 3. However, GLSL ES does not have a concatentation operator, so things like
1189// this (valid in C) are invalid and not a problem:
1190// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
1191// SAMPLER(ExternalOES, mySampler);
1192//
1193static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
1194{
1195 static const char STR_HASH_EXTENSION[] = "#extension";
1196 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
1197 static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
1198 static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
1199
1200 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
1201 char* c = str;
1202 while ((c = strstr(c, STR_HASH_EXTENSION))) {
1203 char* start = c;
1204 c += sizeof(STR_HASH_EXTENSION)-1;
1205 while (isspace(*c) && *c != '\0') {
1206 c++;
1207 }
1208 if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
1209 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
1210 {
1211 // #extension statements are terminated by end of line
1212 c = start;
1213 while (*c != '\0' && *c != '\r' && *c != '\n') {
1214 *c++ = ' ';
1215 }
1216 }
1217 }
1218
1219 // -- replace "samplerExternalOES" with "sampler2D" and record name
1220 c = str;
1221 while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
1222 // Make sure "samplerExternalOES" isn't a substring of a larger token
1223 if (c == str || !isspace(*(c-1))) {
1224 c++;
1225 continue;
1226 }
1227 char* sampler_start = c;
1228 c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
1229 if (!isspace(*c) && *c != '\0') {
1230 continue;
1231 }
1232
1233 // capture sampler name
1234 while (isspace(*c) && *c != '\0') {
1235 c++;
1236 }
1237 if (!isalpha(*c) && *c != '_') {
1238 // not an identifier
1239 return false;
1240 }
1241 char* name_start = c;
1242 do {
1243 c++;
1244 } while (isalnum(*c) || *c == '_');
1245 data->samplerExternalNames.push_back(
1246 android::String8(name_start, c - name_start));
1247
1248 // memcpy instead of strcpy since we don't want the NUL terminator
1249 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
1250 }
1251
1252 return true;
1253}
1254
Bo Hu73568cd2015-01-20 16:29:50 -08001255void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
1256{
1257 GL2Encoder* ctx = (GL2Encoder*)self;
1258 // Although it is not supported, need to set proper error code.
1259 SET_ERROR_IF(1, GL_INVALID_ENUM);
1260}
1261
David 'Digit' Turner02fdb692014-10-30 18:07:56 +01001262void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -08001263{
1264 GL2Encoder* ctx = (GL2Encoder*)self;
1265 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001266 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(shader), GL_INVALID_VALUE);
Tina Zhang7a84f652014-12-04 12:37:30 +08001267 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
1268 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001269
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001270 // Track original sources---they may be translated in the backend
1271 std::vector<std::string> orig_sources;
1272 for (int i = 0; i < count; i++) {
1273 orig_sources.push_back(std::string((const char*)(string[i])));
1274 }
1275 shaderData->sources = orig_sources;
1276
keunyoungb85b2752013-03-08 12:28:03 -08001277 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
1278 char *str = new char[len + 1];
1279 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
1280
1281 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
1282 // Perhaps we can borrow Mesa's pre-processor?
1283
1284 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001285 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001286 ctx->setError(GL_OUT_OF_MEMORY);
1287 return;
1288 }
keunyoungb85b2752013-03-08 12:28:03 -08001289 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001290 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001291}
1292
1293void GL2Encoder::s_glFinish(void *self)
1294{
1295 GL2Encoder *ctx = (GL2Encoder *)self;
1296 ctx->glFinishRoundTrip(self);
1297}
1298
1299void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1300{
1301 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -08001302 bool isProgram = ctx->m_shared->isProgram(program);
1303 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
1304 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
1305
keunyoungb85b2752013-03-08 12:28:03 -08001306 ctx->m_glLinkProgram_enc(self, program);
1307
1308 GLint linkStatus = 0;
1309 ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001310 if (!linkStatus) {
keunyoungb85b2752013-03-08 12:28:03 -08001311 return;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001312 }
keunyoungb85b2752013-03-08 12:28:03 -08001313
1314 //get number of active uniforms in the program
1315 GLint numUniforms=0;
1316 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
1317 ctx->m_shared->initProgramData(program,numUniforms);
1318
1319 //get the length of the longest uniform name
1320 GLint maxLength=0;
1321 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
1322
1323 GLint size;
1324 GLenum type;
1325 GLchar *name = new GLchar[maxLength+1];
1326 GLint location;
1327 //for each active uniform, get its size and starting location.
1328 for (GLint i=0 ; i<numUniforms ; ++i)
1329 {
1330 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1331 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1332 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1333 }
1334 ctx->m_shared->setupLocationShiftWAR(program);
1335
1336 delete[] name;
1337}
1338
1339void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1340{
1341 GL2Encoder *ctx = (GL2Encoder*)self;
1342 ctx->m_glDeleteProgram_enc(self, program);
1343
1344 ctx->m_shared->deleteProgramData(program);
1345}
1346
1347void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1348{
1349 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001350 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001351 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001352 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1353 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1354 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1355 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1356}
1357void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1358{
1359 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001360 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001361 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001362 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1363 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1364 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1365 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1366}
1367
1368GLuint GL2Encoder::s_glCreateProgram(void * self)
1369{
1370 GL2Encoder *ctx = (GL2Encoder*)self;
1371 GLuint program = ctx->m_glCreateProgram_enc(self);
1372 if (program!=0)
1373 ctx->m_shared->addProgramData(program);
1374 return program;
1375}
1376
1377GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1378{
1379 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001380 RET_AND_SET_ERROR_IF(!GLESv2Validation::shaderType(ctx, shaderType), GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001381 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1382 if (shader != 0) {
1383 if (!ctx->m_shared->addShaderData(shader)) {
1384 ctx->m_glDeleteShader_enc(self, shader);
1385 return 0;
1386 }
1387 }
1388 return shader;
1389}
1390
bohu56bf82f2014-10-17 15:35:48 -07001391void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1392 GLsizei* count, GLuint* shaders)
1393{
1394 GL2Encoder *ctx = (GL2Encoder*)self;
1395 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1396 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1397}
1398
1399void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1400 GLsizei* length, GLchar* source)
1401{
1402 GL2Encoder *ctx = (GL2Encoder*)self;
1403 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1404 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001405 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
1406 if (shaderData) {
1407 std::string returned;
1408 int curr_len = 0;
1409 for (int i = 0; i < shaderData->sources.size(); i++) {
1410 if (curr_len + shaderData->sources[i].size() < bufsize - 1) {
1411 returned += shaderData->sources[i];
1412 } else {
1413 returned += shaderData->sources[i].substr(0, bufsize - 1 - curr_len);
1414 break;
1415 }
1416 }
1417 memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize);
1418 }
bohu56bf82f2014-10-17 15:35:48 -07001419}
1420
1421void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1422 GLsizei* length, GLchar* infolog)
1423{
1424 GL2Encoder *ctx = (GL2Encoder*)self;
1425 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1426 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1427}
1428
1429void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1430 GLsizei* length, GLchar* infolog)
1431{
1432 GL2Encoder *ctx = (GL2Encoder*)self;
1433 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1434 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1435}
1436
keunyoungb85b2752013-03-08 12:28:03 -08001437void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1438{
1439 GL2Encoder *ctx = (GL2Encoder*)self;
1440 ctx->m_glDeleteShader_enc(self,shader);
1441 ctx->m_shared->unrefShaderData(shader);
1442}
1443
1444void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1445{
1446 GL2Encoder *ctx = (GL2Encoder*)self;
1447 ctx->m_glAttachShader_enc(self, program, shader);
1448 ctx->m_shared->attachShader(program, shader);
1449}
1450
1451void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1452{
1453 GL2Encoder *ctx = (GL2Encoder*)self;
1454 ctx->m_glDetachShader_enc(self, program, shader);
1455 ctx->m_shared->detachShader(program, shader);
1456}
1457
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001458int sArrIndexOfUniformExpr(const char* name, int* err) {
1459 *err = 0;
1460 int arrIndex = 0;
1461 int namelen = strlen(name);
1462 if (name[namelen-1] == ']') {
1463 const char *brace = strrchr(name,'[');
1464 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1465 *err = 1; return 0;
1466 }
1467 }
1468 return arrIndex;
1469}
1470
keunyoungb85b2752013-03-08 12:28:03 -08001471int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1472{
1473 if (!name) return -1;
1474
1475 GL2Encoder *ctx = (GL2Encoder*)self;
1476
1477 // if we need the uniform location WAR
1478 // parse array index from the end of the name string
1479 int arrIndex = 0;
1480 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1481 if (needLocationWAR) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001482 int err;
1483 arrIndex = sArrIndexOfUniformExpr(name, &err);
1484 if (err) return -1;
keunyoungb85b2752013-03-08 12:28:03 -08001485 }
1486
1487 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1488 if (hostLoc >= 0 && needLocationWAR) {
1489 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1490 }
1491 return hostLoc;
1492}
1493
1494bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1495{
1496 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1497 return false;
1498
1499 m_state->setActiveTextureUnit(texUnit);
1500
1501 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1502 if (newTarget != oldTarget) {
1503 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1504 m_state->disableTextureTarget(GL_TEXTURE_2D);
1505 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1506 } else {
1507 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1508 m_state->enableTextureTarget(GL_TEXTURE_2D);
1509 }
1510 m_glActiveTexture_enc(this, texUnit);
1511 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1512 m_state->getBoundTexture(newTarget));
1513 return true;
1514 }
1515
1516 return false;
1517}
1518
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001519void GL2Encoder::updateHostTexture2DBindingsFromProgramData(GLuint program) {
1520 GL2Encoder *ctx = this;
keunyoungb85b2752013-03-08 12:28:03 -08001521 GLClientState* state = ctx->m_state;
1522 GLSharedGroupPtr shared = ctx->m_shared;
1523
keunyoungb85b2752013-03-08 12:28:03 -08001524 GLenum origActiveTexture = state->getActiveTextureUnit();
1525 GLenum hostActiveTexture = origActiveTexture;
1526 GLint samplerIdx = -1;
1527 GLint samplerVal;
1528 GLenum samplerTarget;
1529 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1530 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1531 continue;
1532 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001533 samplerTarget))
keunyoungb85b2752013-03-08 12:28:03 -08001534 {
1535 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1536 }
1537 }
1538 state->setActiveTextureUnit(origActiveTexture);
1539 if (hostActiveTexture != origActiveTexture) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001540 ctx->m_glActiveTexture_enc(ctx, origActiveTexture);
keunyoungb85b2752013-03-08 12:28:03 -08001541 }
1542}
1543
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001544void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1545{
1546 GL2Encoder *ctx = (GL2Encoder*)self;
1547 GLSharedGroupPtr shared = ctx->m_shared;
1548
1549 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
1550 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1551
1552 ctx->m_glUseProgram_enc(self, program);
1553 ctx->m_state->setCurrentProgram(program);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001554 ctx->m_state->setCurrentShaderProgram(program);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001555
1556 ctx->updateHostTexture2DBindingsFromProgramData(program);
1557}
1558
keunyoungb85b2752013-03-08 12:28:03 -08001559void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1560{
1561 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001562 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001563 ctx->m_glUniform1f_enc(self, hostLoc, x);
1564}
1565
1566void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1567{
1568 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001569 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001570 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1571}
1572
1573void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1574{
1575 GL2Encoder *ctx = (GL2Encoder*)self;
1576 GLClientState* state = ctx->m_state;
1577 GLSharedGroupPtr shared = ctx->m_shared;
1578
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001579 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001580 ctx->m_glUniform1i_enc(self, hostLoc, x);
1581
1582 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001583 if (shared->setSamplerUniform(state->currentShaderProgram(), location, x, &target)) {
keunyoungb85b2752013-03-08 12:28:03 -08001584 GLenum origActiveTexture = state->getActiveTextureUnit();
1585 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1586 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1587 }
1588 state->setActiveTextureUnit(origActiveTexture);
1589 }
1590}
1591
1592void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1593{
1594 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001595 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001596 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1597}
1598
1599void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1600{
1601 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001602 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001603 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1604}
1605
1606void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1607{
1608 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001609 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001610 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1611}
1612
1613void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1614{
1615 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001616 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001617 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1618}
1619
1620void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1621{
1622 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001623 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001624 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1625}
1626
1627void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1628{
1629 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001630 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001631 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1632}
1633
1634void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1635{
1636 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001637 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001638 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1639}
1640
1641void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1642{
1643 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001644 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001645 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1646}
1647
1648void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1649{
1650 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001651 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001652 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1653}
1654
1655void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1656{
1657 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001658 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001659 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1660}
1661
1662void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1663{
1664 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001665 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001666 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1667}
1668
1669void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1670{
1671 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001672 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001673 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1674}
1675
1676void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1677{
1678 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001679 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001680 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1681}
1682
1683void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1684{
1685 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001686 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001687 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1688}
1689
1690void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1691{
1692 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001693 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001694 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1695}
1696
1697void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1698{
1699 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001700 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001701 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1702}
1703
1704void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1705{
1706 GL2Encoder* ctx = (GL2Encoder*)self;
1707 GLClientState* state = ctx->m_state;
1708 GLenum err;
1709
1710 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1711
1712 ctx->m_glActiveTexture_enc(ctx, texture);
1713}
1714
1715void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1716{
1717 GL2Encoder* ctx = (GL2Encoder*)self;
1718 GLClientState* state = ctx->m_state;
1719 GLenum err;
1720 GLboolean firstUse;
1721
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001722 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -08001723 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1724
1725 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1726 ctx->m_glBindTexture_enc(ctx, target, texture);
1727 return;
1728 }
1729
1730 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1731
1732 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1733 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1734 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1735 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1736 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1737 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1738 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1739 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1740
1741 if (target != priorityTarget) {
1742 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1743 state->getBoundTexture(GL_TEXTURE_2D));
1744 }
1745 }
1746
1747 if (target == priorityTarget) {
1748 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1749 }
1750}
1751
1752void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1753{
1754 GL2Encoder* ctx = (GL2Encoder*)self;
1755 GLClientState* state = ctx->m_state;
1756
1757 state->deleteTextures(n, textures);
1758 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1759}
1760
1761void GL2Encoder::s_glGetTexParameterfv(void* self,
1762 GLenum target, GLenum pname, GLfloat* params)
1763{
1764 GL2Encoder* ctx = (GL2Encoder*)self;
1765 const GLClientState* state = ctx->m_state;
1766
1767 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1768 ctx->override2DTextureTarget(target);
1769 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001770 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001771 } else {
1772 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1773 }
1774}
1775
1776void GL2Encoder::s_glGetTexParameteriv(void* self,
1777 GLenum target, GLenum pname, GLint* params)
1778{
1779 GL2Encoder* ctx = (GL2Encoder*)self;
1780 const GLClientState* state = ctx->m_state;
1781
1782 switch (pname) {
1783 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1784 *params = 1;
1785 break;
1786
1787 default:
1788 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1789 ctx->override2DTextureTarget(target);
1790 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001791 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001792 } else {
1793 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1794 }
1795 break;
1796 }
1797}
1798
1799static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1800{
1801 switch (pname) {
1802 case GL_TEXTURE_MIN_FILTER:
1803 case GL_TEXTURE_MAG_FILTER:
1804 return param == GL_NEAREST || param == GL_LINEAR;
1805
1806 case GL_TEXTURE_WRAP_S:
1807 case GL_TEXTURE_WRAP_T:
1808 return param == GL_CLAMP_TO_EDGE;
1809
1810 default:
1811 return true;
1812 }
1813}
1814
1815void GL2Encoder::s_glTexParameterf(void* self,
1816 GLenum target, GLenum pname, GLfloat param)
1817{
1818 GL2Encoder* ctx = (GL2Encoder*)self;
1819 const GLClientState* state = ctx->m_state;
1820
1821 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1822 !isValidTextureExternalParam(pname, (GLenum)param)),
1823 GL_INVALID_ENUM);
1824
1825 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1826 ctx->override2DTextureTarget(target);
1827 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001828 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001829 } else {
1830 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1831 }
1832}
1833
1834void GL2Encoder::s_glTexParameterfv(void* self,
1835 GLenum target, GLenum pname, const GLfloat* params)
1836{
1837 GL2Encoder* ctx = (GL2Encoder*)self;
1838 const GLClientState* state = ctx->m_state;
1839
1840 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1841 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1842 GL_INVALID_ENUM);
1843
1844 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1845 ctx->override2DTextureTarget(target);
1846 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001847 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001848 } else {
1849 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1850 }
1851}
1852
1853void GL2Encoder::s_glTexParameteri(void* self,
1854 GLenum target, GLenum pname, GLint param)
1855{
1856 GL2Encoder* ctx = (GL2Encoder*)self;
1857 const GLClientState* state = ctx->m_state;
1858
1859 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1860 !isValidTextureExternalParam(pname, (GLenum)param)),
1861 GL_INVALID_ENUM);
1862
1863 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1864 ctx->override2DTextureTarget(target);
1865 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001866 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001867 } else {
1868 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
1869 }
1870}
1871
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001872static int ilog2(uint32_t x) {
1873 int p = 0;
1874 while ((1 << p) < x)
1875 p++;
1876 return p;
1877}
1878
bohu26a92982014-11-25 16:50:37 -08001879void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
1880 GLint internalformat, GLsizei width, GLsizei height, GLint border,
1881 GLenum format, GLenum type, const GLvoid* pixels)
1882{
1883 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07001884 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001885
1886 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
1887 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
1888 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
1889 // If unpack buffer is nonzero, verify unmapped state.
1890 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
1891
1892 GLint max_texture_size;
1893 GLint max_cube_map_texture_size;
1894 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
1895 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
1896 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
1897 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
1898 SET_ERROR_IF((target == GL_TEXTURE_CUBE_MAP) &&
1899 (level > ilog2(max_cube_map_texture_size)), GL_INVALID_VALUE);
1900 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
1901 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
1902 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
1903 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && width > max_cube_map_texture_size, GL_INVALID_VALUE);
1904 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && height > max_cube_map_texture_size, GL_INVALID_VALUE);
1905 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
1906 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
1907 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1908 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1909 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 0) >
1910 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
1911 GL_INVALID_OPERATION);
1912 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1913 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1914 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
1915 glSizeof(type)),
1916 GL_INVALID_OPERATION);
1917 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1918 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1919 ((uintptr_t)pixels % glSizeof(type)),
1920 GL_INVALID_OPERATION);
1921 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
1922
1923 GLenum stateTarget = target;
1924 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1925 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1926 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
1927 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1928 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1929 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
1930 stateTarget = GL_TEXTURE_CUBE_MAP;
1931
1932 state->setBoundTextureInternalFormat(stateTarget, internalformat);
1933 state->setBoundTextureFormat(stateTarget, format);
1934 state->setBoundTextureType(stateTarget, type);
1935 state->setBoundTextureDims(stateTarget, level, width, height, 1);
1936
bohu26a92982014-11-25 16:50:37 -08001937 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1938 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001939 }
Lingfeng Yang69066602016-04-12 09:29:11 -07001940
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001941 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
1942 ctx->glTexImage2DOffsetAEMU(
1943 ctx, target, level, internalformat,
1944 width, height, border,
1945 format, type, (uintptr_t)pixels);
bohu26a92982014-11-25 16:50:37 -08001946 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001947 ctx->m_glTexImage2D_enc(
1948 ctx, target, level, internalformat,
1949 width, height, border,
1950 format, type, pixels);
1951 }
1952
1953 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1954 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08001955 }
1956}
1957
Yahan Zhou2a208292016-06-22 15:36:04 -07001958void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
1959 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
1960 GLenum type, const GLvoid* pixels)
1961{
1962 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001963 GLClientState* state = ctx->m_state;
1964
1965 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
1966 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
1967 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
1968 // If unpack buffer is nonzero, verify unmapped state.
1969 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
1970
1971 GLint max_texture_size;
1972 GLint max_cube_map_texture_size;
1973 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
1974 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
1975 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
1976 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
1977 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) &&
1978 level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
1979 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
1980 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
1981
1982 GLuint tex = state->getBoundTexture(target);
1983 GLsizei neededWidth = xoffset + width;
1984 GLsizei neededHeight = yoffset + height;
1985 GLsizei neededDepth = 1;
1986
1987 if (tex && !state->queryTexEGLImageBacked(tex)) {
1988 SET_ERROR_IF(
1989 (neededWidth > state->queryTexWidth(level, tex) ||
1990 neededHeight > state->queryTexHeight(level, tex) ||
1991 neededDepth > state->queryTexDepth(level, tex)),
1992 GL_INVALID_VALUE);
1993 }
1994
1995 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
1996 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1997 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1998 (state->pboNeededDataSize(width, height, 1, format, type, 0) >
1999 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2000 GL_INVALID_OPERATION);
2001 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2002 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2003 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2004 glSizeof(type)),
2005 GL_INVALID_OPERATION);
2006 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !pixels, GL_INVALID_OPERATION);
Yahan Zhou2a208292016-06-22 15:36:04 -07002007
2008 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2009 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002010 }
2011
2012 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2013 ctx->glTexSubImage2DOffsetAEMU(
2014 ctx, target, level,
2015 xoffset, yoffset, width, height,
2016 format, type, (uintptr_t)pixels);
Yahan Zhou2a208292016-06-22 15:36:04 -07002017 } else {
2018 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
2019 height, format, type, pixels);
2020 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002021
2022 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2023 ctx->restore2DTextureTarget(target);
2024 }
Yahan Zhou2a208292016-06-22 15:36:04 -07002025}
bohu26a92982014-11-25 16:50:37 -08002026
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002027void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
2028 GLenum internalformat, GLint x, GLint y,
2029 GLsizei width, GLsizei height, GLint border)
2030{
2031 GL2Encoder* ctx = (GL2Encoder*)self;
2032 GLClientState* state = ctx->m_state;
2033
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002034 SET_ERROR_IF(ctx->glCheckFramebufferStatus(ctx, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
2035 GL_INVALID_FRAMEBUFFER_OPERATION);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002036 // This is needed to work around underlying OpenGL drivers
2037 // (such as those feeding some some AMD GPUs) that expect
2038 // positive components of cube maps to be defined _before_
2039 // the negative components (otherwise a segfault occurs).
2040 GLenum extraTarget =
2041 state->copyTexImageLuminanceCubeMapAMDWorkaround
2042 (target, level, internalformat);
2043
2044 if (extraTarget) {
2045 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
2046 x, y, width, height, border);
2047 }
2048
2049 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
2050 x, y, width, height, border);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002051
2052 state->setBoundTextureInternalFormat(target, internalformat);
2053 state->setBoundTextureDims(target, level, width, height, 1);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002054}
2055
keunyoungb85b2752013-03-08 12:28:03 -08002056void GL2Encoder::s_glTexParameteriv(void* self,
2057 GLenum target, GLenum pname, const GLint* params)
2058{
2059 GL2Encoder* ctx = (GL2Encoder*)self;
2060 const GLClientState* state = ctx->m_state;
2061
2062 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2063 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2064 GL_INVALID_ENUM);
2065
2066 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2067 ctx->override2DTextureTarget(target);
2068 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002069 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002070 } else {
2071 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
2072 }
2073}
2074
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002075bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
2076 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
2077 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2078}
2079
keunyoungb85b2752013-03-08 12:28:03 -08002080void GL2Encoder::override2DTextureTarget(GLenum target)
2081{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002082 if (texture2DNeedsOverride(target)) {
2083 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2084 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08002085 }
2086}
2087
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002088void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08002089{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002090 if (texture2DNeedsOverride(target)) {
2091 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2092 m_state->getBoundTexture(
2093 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)));
2094 }
keunyoungb85b2752013-03-08 12:28:03 -08002095}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002096
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002097void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2098 m_state->setBoundEGLImage(target, eglImage);
2099}
2100
2101
2102GLuint GL2Encoder::boundBuffer(GLenum target) const {
2103 return m_state->getBuffer(target);
2104}
2105
2106BufferData* GL2Encoder::getBufferData(GLenum target) const {
2107 GLuint bufferId = m_state->getBuffer(target);
2108 if (!bufferId) return NULL;
2109 return m_shared->getBufferData(bufferId);
2110}
2111
2112BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2113 if (!bufferId) return NULL;
2114 return m_shared->getBufferData(bufferId);
2115}
2116
2117bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2118 return m_shared->getBufferData(buffer)->m_mapped;
2119}
2120
2121bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2122 BufferData* buf = getBufferData(target);
2123 if (!buf) return false;
2124 return buf->m_mapped;
2125}
2126
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002127void GL2Encoder::s_glGenRenderbuffers(void* self,
2128 GLsizei n, GLuint* renderbuffers) {
2129 GL2Encoder* ctx = (GL2Encoder*)self;
2130 GLClientState* state = ctx->m_state;
2131
2132 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2133
2134 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2135 state->addRenderbuffers(n, renderbuffers);
2136}
2137
2138void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2139 GLsizei n, const GLuint* renderbuffers) {
2140 GL2Encoder* ctx = (GL2Encoder*)self;
2141 GLClientState* state = ctx->m_state;
2142
2143 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2144
2145 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002146
2147 // Nope, lets just leak those for now.
2148 // The spec has an *amazingly* convoluted set of conditions for when
2149 // render buffers are actually deleted:
2150 // glDeleteRenderbuffers deletes the n renderbuffer objects whose names are stored in the array addressed by renderbuffers. Unused names in renderbuffers that have been marked as used for the purposes of glGenRenderbuffers are marked as unused again. The name zero is reserved by the GL and is silently ignored, should it occur in renderbuffers, as are other unused names. Once a renderbuffer object is deleted, its name is again unused and it has no contents. If a renderbuffer that is currently bound to the target GL_RENDERBUFFER is deleted, it is as though glBindRenderbuffer had been executed with a target of GL_RENDERBUFFER and a name of zero.
2151 //
2152 // If a renderbuffer object is attached to one or more attachment points in the currently bound framebuffer, then it as if glFramebufferRenderbuffer had been called, with a renderbuffer of zero for each attachment point to which this image was attached in the currently bound framebuffer. In other words, this renderbuffer object is first detached from all attachment ponits in the currently bound framebuffer. ***Note that the renderbuffer image is specifically not detached from any non-bound framebuffers***
2153 //
2154 // So, just detach this one from the bound FBO, and ignore the rest.
2155 for (int i = 0; i < n; i++) {
2156 state->detachRbo(renderbuffers[i]);
2157 }
2158 // state->removeRenderbuffers(n, renderbuffers);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002159}
2160
2161void GL2Encoder::s_glBindRenderbuffer(void* self,
2162 GLenum target, GLuint renderbuffer) {
2163 GL2Encoder* ctx = (GL2Encoder*)self;
2164 GLClientState* state = ctx->m_state;
2165
2166 SET_ERROR_IF((target != GL_RENDERBUFFER),
2167 GL_INVALID_ENUM);
2168
2169 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2170 state->bindRenderbuffer(target, renderbuffer);
2171}
2172
Lingfeng Yang69066602016-04-12 09:29:11 -07002173void GL2Encoder::s_glRenderbufferStorage(void* self,
2174 GLenum target, GLenum internalformat,
2175 GLsizei width, GLsizei height) {
2176 GL2Encoder* ctx = (GL2Encoder*) self;
2177 GLClientState* state = ctx->m_state;
2178
2179 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002180 SET_ERROR_IF(
2181 !GLESv2Validation::rboFormat(ctx, internalformat),
2182 GL_INVALID_ENUM);
Lingfeng Yang69066602016-04-12 09:29:11 -07002183
2184 state->setBoundRenderbufferFormat(internalformat);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002185 state->setBoundRenderbufferSamples(0);
2186
Lingfeng Yang69066602016-04-12 09:29:11 -07002187 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
2188 width, height);
2189}
2190
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002191void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
2192 GLenum target, GLenum attachment,
2193 GLenum renderbuffertarget, GLuint renderbuffer) {
2194 GL2Encoder* ctx = (GL2Encoder*)self;
2195 GLClientState* state = ctx->m_state;
2196
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002197 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2198 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2199 state->attachRbo(target, attachment, renderbuffer);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002200
2201 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
2202}
2203
2204void GL2Encoder::s_glGenFramebuffers(void* self,
2205 GLsizei n, GLuint* framebuffers) {
2206 GL2Encoder* ctx = (GL2Encoder*)self;
2207 GLClientState* state = ctx->m_state;
2208
2209 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2210
2211 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2212 state->addFramebuffers(n, framebuffers);
2213}
2214
2215void GL2Encoder::s_glDeleteFramebuffers(void* self,
2216 GLsizei n, const GLuint* framebuffers) {
2217 GL2Encoder* ctx = (GL2Encoder*)self;
2218 GLClientState* state = ctx->m_state;
2219
2220 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2221
2222 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2223 state->removeFramebuffers(n, framebuffers);
2224}
2225
2226void GL2Encoder::s_glBindFramebuffer(void* self,
2227 GLenum target, GLuint framebuffer) {
2228 GL2Encoder* ctx = (GL2Encoder*)self;
2229 GLClientState* state = ctx->m_state;
2230
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002231 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002232
2233 state->bindFramebuffer(target, framebuffer);
2234
2235 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
2236}
2237
2238void GL2Encoder::s_glFramebufferTexture2D(void* self,
2239 GLenum target, GLenum attachment,
2240 GLenum textarget, GLuint texture, GLint level) {
2241 GL2Encoder* ctx = (GL2Encoder*)self;
2242 GLClientState* state = ctx->m_state;
2243
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002244 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2245 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2246 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002247
2248 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
2249}
2250
2251void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2252 GLenum target, GLenum attachment,
2253 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2254 GL2Encoder* ctx = (GL2Encoder*)self;
2255 GLClientState* state = ctx->m_state;
2256
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002257 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002258
2259 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2260}
2261
2262void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2263 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2264 GL2Encoder* ctx = (GL2Encoder*)self;
2265 const GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002266 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2267 SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2268 pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE &&
2269 !state->attachmentHasObject(target, attachment),
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002270 GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002271 SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL ||
2272 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE ||
2273 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) &&
2274 (!state->attachmentHasObject(target, attachment) ||
2275 state->getBoundFramebufferAttachmentType(target, attachment) !=
2276 FBO_ATTACHMENT_TEXTURE),
2277 !state->attachmentHasObject(target, attachment) ?
2278 GL_INVALID_OPERATION : GL_INVALID_ENUM);
2279 SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2280 pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2281 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
2282 state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
2283 GL_INVALID_OPERATION);
2284 SET_ERROR_IF(state->boundFramebuffer(target) &&
2285 (attachment == GL_BACK ||
2286 attachment == GL_FRONT),
2287 GL_INVALID_OPERATION);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002288 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
2289}
Lingfeng Yang69066602016-04-12 09:29:11 -07002290
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002291bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state,
Lingfeng Yang69066602016-04-12 09:29:11 -07002292 GLenum attachment) const {
2293 FboFormatInfo fbo_format_info;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002294 state->getBoundFramebufferFormat(target, attachment, &fbo_format_info);
Lingfeng Yang69066602016-04-12 09:29:11 -07002295
2296 bool res;
2297 switch (fbo_format_info.type) {
2298 case FBO_ATTACHMENT_RENDERBUFFER:
2299 switch (fbo_format_info.rb_format) {
2300 case GL_R16F:
2301 case GL_RG16F:
Lingfeng Yang69066602016-04-12 09:29:11 -07002302 case GL_RGBA16F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002303 case GL_R32F:
2304 case GL_RG32F:
2305 case GL_RGBA32F:
2306 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002307 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002308 break;
2309 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002310 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang69066602016-04-12 09:29:11 -07002311 break;
2312 case GL_STENCIL_INDEX8:
2313 if (attachment == GL_STENCIL_ATTACHMENT) {
2314 res = true;
2315 } else {
2316 res = false;
2317 }
2318 break;
2319 default:
2320 res = true;
2321 }
2322 break;
2323 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002324 switch (fbo_format_info.tex_internalformat) {
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002325 case GL_R16F:
2326 case GL_RG16F:
2327 case GL_RGBA16F:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002328 case GL_R32F:
2329 case GL_RG32F:
2330 case GL_RGBA32F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002331 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002332 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002333 break;
2334 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002335 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002336 break;
2337 case GL_RED:
2338 case GL_RG:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002339 case GL_SRGB8:
2340 case GL_RGB32UI:
2341 case GL_RGB16UI:
2342 case GL_RGB8UI:
2343 case GL_RGB32I:
2344 case GL_RGB16I:
2345 case GL_RGB8I:
2346 case GL_R8_SNORM:
2347 case GL_RG8_SNORM:
2348 case GL_RGB8_SNORM:
2349 case GL_RGBA8_SNORM:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002350 res = false;
2351 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07002352 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002353 case GL_RGB:
2354 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07002355 switch (fbo_format_info.tex_type) {
2356 case GL_FLOAT:
2357 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002358 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002359 case GL_UNSIGNED_INT_2_10_10_10_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07002360 res = false;
2361 break;
2362 default:
2363 res = true;
2364 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002365 break;
2366 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07002367 res = true;
2368 }
2369 break;
2370 case FBO_ATTACHMENT_NONE:
2371 res = true;
2372 break;
2373 default:
2374 res = true;
2375 }
2376 return res;
2377}
2378
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002379bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const {
2380 bool res = true;
2381
2382 for (int i = 0; i < state->getMaxColorAttachments(); i++) {
2383 res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i));
2384 }
2385
2386 res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT);
2387 res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT);
2388
2389 return res;
2390}
2391
Lingfeng Yang69066602016-04-12 09:29:11 -07002392GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
2393 GL2Encoder* ctx = (GL2Encoder*)self;
2394 GLClientState* state = ctx->m_state;
2395
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002396 bool fboCompleteByCodec =
2397 ctx->checkFramebufferCompleteness(target, state);
2398
2399 if (!fboCompleteByCodec) {
2400 state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
Lingfeng Yang69066602016-04-12 09:29:11 -07002401 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2402 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002403 // double check with underlying opengl to avoid craziness.
Lingfeng Yang69066602016-04-12 09:29:11 -07002404 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002405 state->setCheckFramebufferStatus(target, host_checkstatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002406 if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE;
Lingfeng Yang69066602016-04-12 09:29:11 -07002407 return host_checkstatus;
2408 }
2409}
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002410
2411void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2412 GL2Encoder* ctx = (GL2Encoder*)self;
2413 GLClientState* state = ctx->m_state;
2414 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2415
2416 ctx->m_glGenVertexArrays_enc(self, n, arrays);
2417 for (int i = 0; i < n; i++) {
2418 ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2419 }
2420 state->addVertexArrayObjects(n, arrays);
2421}
2422
2423void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2424 GL2Encoder* ctx = (GL2Encoder*)self;
2425 GLClientState* state = ctx->m_state;
2426 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2427
2428 ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2429 for (int i = 0; i < n; i++) {
2430 ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2431 }
2432 state->removeVertexArrayObjects(n, arrays);
2433}
2434
2435void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2436 ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2437 GL2Encoder* ctx = (GL2Encoder*)self;
2438 GLClientState* state = ctx->m_state;
2439 SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2440 ctx->m_glBindVertexArray_enc(self, array);
2441 state->setVertexArrayObject(array);
2442}
2443
2444void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2445 GL2Encoder* ctx = (GL2Encoder*)self;
2446 GLClientState* state = ctx->m_state;
2447
2448 // begin validation (lots)
2449
2450 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2451
2452 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2453
2454 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2455
2456 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2457 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2458
2459 GLsizeiptr bufferDataSize = buf->m_size;
2460
2461 RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2462 RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2463 RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2464 RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2465
2466 RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2467 RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2468 RET_AND_SET_ERROR_IF(
2469 (access & GL_MAP_READ_BIT) &&
2470 ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2471 (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2472 (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2473 (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2474
2475 // end validation; actually do stuff now
2476
2477 buf->m_mapped = true;
2478 buf->m_mappedAccess = access;
2479 buf->m_mappedOffset = offset;
2480 buf->m_mappedLength = length;
2481
2482 char* todo = (char*)buf->m_fixedBuffer.ptr() + offset;
2483 ctx->glMapBufferRangeAEMU(
2484 ctx, target,
2485 offset, length,
2486 access,
2487 todo);
2488
2489 return todo;
2490}
2491
2492GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
2493 GL2Encoder* ctx = (GL2Encoder*)self;
2494 GLClientState* state = ctx->m_state;
2495
2496 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
2497
2498 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2499
2500 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
2501
2502 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2503 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
2504 RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
2505
Lingfeng Yang423129e2017-01-18 09:23:12 -08002506 if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
2507 // invalide index range cache here
2508 if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) {
2509 buf->m_indexRangeCache.invalidateRange(0, buf->m_size);
2510 } else {
2511 buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength);
2512 }
2513 }
2514
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002515 GLboolean host_res = GL_TRUE;
2516
2517 ctx->glUnmapBufferAEMU(
2518 ctx, target,
2519 buf->m_mappedOffset,
2520 buf->m_mappedLength,
2521 buf->m_mappedAccess,
2522 (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
2523 &host_res);
2524
2525 buf->m_mapped = false;
2526 buf->m_mappedAccess = 0;
2527 buf->m_mappedOffset = 0;
2528 buf->m_mappedLength = 0;
2529
2530 return host_res;
2531}
2532
2533void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
2534 GL2Encoder* ctx = (GL2Encoder*)self;
2535 GLClientState* state = ctx->m_state;
2536
2537 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2538
2539 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2540 SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
2541
2542 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2543 SET_ERROR_IF(!buf, GL_INVALID_VALUE);
2544 SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
2545 SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
2546
2547 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
2548 SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
2549 SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
2550
2551 GLintptr totalOffset = buf->m_mappedOffset + offset;
Lingfeng Yang423129e2017-01-18 09:23:12 -08002552
2553 buf->m_indexRangeCache.invalidateRange(totalOffset, length);
2554
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002555 ctx->glFlushMappedBufferRangeAEMU(
2556 ctx, target,
2557 totalOffset,
2558 length,
2559 buf->m_mappedAccess,
2560 (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
2561}
2562
2563void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
2564 GL2Encoder* ctx = (GL2Encoder*)self;
2565 GLClientState* state = ctx->m_state;
2566
2567 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2568 // Filter compressed formats support.
2569 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
2570 // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
2571 GLint max_texture_size;
2572 GLint max_cube_map_texture_size;
2573 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2574 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2575 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2576 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2577 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2578 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2579 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2580 SET_ERROR_IF(border, GL_INVALID_VALUE);
2581 // If unpack buffer is nonzero, verify unmapped state.
2582 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2583 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2584 // If unpack buffer is nonzero, verify buffer data fits.
2585 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2586 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2587 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2588 GL_INVALID_OPERATION);
2589 // TODO: Fix:
2590 // If |imageSize| is inconsistent with compressed dimensions.
2591 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
2592
2593 GLenum stateTarget = target;
2594 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2595 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2596 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2597 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2598 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2599 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2600 stateTarget = GL_TEXTURE_CUBE_MAP;
2601 state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
2602 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2603
2604 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2605 ctx->glCompressedTexImage2DOffsetAEMU(
2606 ctx, target, level, internalformat,
2607 width, height, border,
2608 imageSize, (uintptr_t)data);
2609 } else {
2610 ctx->m_glCompressedTexImage2D_enc(
2611 ctx, target, level, internalformat,
2612 width, height, border,
2613 imageSize, data);
2614 }
2615}
2616
2617void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
2618 GL2Encoder* ctx = (GL2Encoder*)self;
2619 GLClientState* state = ctx->m_state;
2620
2621 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2622 // If unpack buffer is nonzero, verify unmapped state.
2623 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2624 GLint max_texture_size;
2625 GLint max_cube_map_texture_size;
2626 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2627 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2628 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2629 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2630 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2631 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2632 // If unpack buffer is nonzero, verify buffer data fits.
2633 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2634 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2635 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2636 GL_INVALID_OPERATION);
2637 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2638
2639 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2640 ctx->glCompressedTexSubImage2DOffsetAEMU(
2641 ctx, target, level,
2642 xoffset, yoffset,
2643 width, height, format,
2644 imageSize, (uintptr_t)data);
2645 } else {
2646 ctx->m_glCompressedTexSubImage2D_enc(
2647 ctx, target, level,
2648 xoffset, yoffset,
2649 width, height, format,
2650 imageSize, data);
2651 }
2652}
2653
2654void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
2655 GL2Encoder* ctx = (GL2Encoder*)self;
2656 GLClientState* state = ctx->m_state;
2657
2658 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2659
2660 // Only works with certain targets
2661 SET_ERROR_IF(
2662 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2663 target == GL_SHADER_STORAGE_BUFFER ||
2664 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2665 target == GL_UNIFORM_BUFFER),
2666 GL_INVALID_ENUM);
2667
2668 // Can't exceed range
2669 SET_ERROR_IF(index < 0 ||
2670 index >= state->getMaxIndexedBufferBindings(target),
2671 GL_INVALID_VALUE);
2672 SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
2673 SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
2674 target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
2675 (size % 4 || offset % 4),
2676 GL_INVALID_VALUE);
2677
2678 GLint ssbo_offset_align, ubo_offset_align;
2679 ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
2680 ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
2681 SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
2682 offset % ssbo_offset_align,
2683 GL_INVALID_VALUE);
2684 SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
2685 offset % ubo_offset_align,
2686 GL_INVALID_VALUE);
2687
2688 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002689 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002690 state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0);
2691 ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size);
2692}
2693
2694void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
2695 GL2Encoder* ctx = (GL2Encoder*)self;
2696 GLClientState* state = ctx->m_state;
2697
2698 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2699
2700 // Only works with certain targets
2701 SET_ERROR_IF(
2702 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2703 target == GL_SHADER_STORAGE_BUFFER ||
2704 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2705 target == GL_UNIFORM_BUFFER),
2706 GL_INVALID_ENUM);
2707 // Can't exceed range
2708 SET_ERROR_IF(index < 0 ||
2709 index >= state->getMaxIndexedBufferBindings(target),
2710 GL_INVALID_VALUE);
2711
2712 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002713 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002714 BufferData* buf = ctx->getBufferDataById(buffer);
2715 state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0);
2716 ctx->m_glBindBufferBase_enc(self, target, index, buffer);
2717}
2718
2719void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
2720 GL2Encoder* ctx = (GL2Encoder*)self;
2721 GLClientState* state = ctx->m_state;
2722
2723 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
2724 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
2725 SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
2726 readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
2727 readtarget == GL_DRAW_INDIRECT_BUFFER ||
2728 readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2729 SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
2730 writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
2731 writetarget == GL_DRAW_INDIRECT_BUFFER ||
2732 writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2733 SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
2734 SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
2735 SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
2736 SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
2737 SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
2738 SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
2739 SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
2740 SET_ERROR_IF(
2741 ctx->getBufferData(readtarget) &&
2742 (readoffset + size > ctx->getBufferData(readtarget)->m_size),
2743 GL_INVALID_VALUE);
2744 SET_ERROR_IF(
2745 ctx->getBufferData(writetarget) &&
2746 (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
2747 GL_INVALID_VALUE);
2748 SET_ERROR_IF(readtarget == writetarget &&
2749 !((writeoffset >= readoffset + size) ||
2750 (readoffset >= writeoffset + size)),
2751 GL_INVALID_VALUE);
2752
2753 ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
2754}
2755
2756void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
2757 GL2Encoder* ctx = (GL2Encoder*)self;
2758
2759 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2760 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002761 target != GL_ARRAY_BUFFER &&
2762 target != GL_ELEMENT_ARRAY_BUFFER &&
2763 target != GL_COPY_READ_BUFFER &&
2764 target != GL_COPY_WRITE_BUFFER &&
2765 target != GL_PIXEL_PACK_BUFFER &&
2766 target != GL_PIXEL_UNPACK_BUFFER &&
2767 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
2768 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002769 GL_INVALID_ENUM);
2770 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
2771 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002772 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
2773 pname != GL_BUFFER_MAPPED &&
2774 pname != GL_BUFFER_SIZE &&
2775 pname != GL_BUFFER_USAGE &&
2776 pname != GL_BUFFER_MAP_LENGTH &&
2777 pname != GL_BUFFER_MAP_OFFSET,
2778 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002779
2780 if (!params) return;
2781
2782 BufferData* buf = ctx->getBufferData(target);
2783
2784 switch (pname) {
2785 case GL_BUFFER_ACCESS_FLAGS:
2786 *params = buf ? buf->m_mappedAccess : 0;
2787 break;
2788 case GL_BUFFER_MAPPED:
2789 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
2790 break;
2791 case GL_BUFFER_SIZE:
2792 *params = buf ? buf->m_size : 0;
2793 break;
2794 case GL_BUFFER_USAGE:
2795 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
2796 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002797 case GL_BUFFER_MAP_LENGTH:
2798 *params = buf ? buf->m_mappedLength : 0;
2799 break;
2800 case GL_BUFFER_MAP_OFFSET:
2801 *params = buf ? buf->m_mappedOffset : 0;
2802 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002803 default:
2804 break;
2805 }
2806}
2807
2808void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
2809 GL2Encoder* ctx = (GL2Encoder*)self;
2810
2811 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2812 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002813 target != GL_ARRAY_BUFFER &&
2814 target != GL_ELEMENT_ARRAY_BUFFER &&
2815 target != GL_COPY_READ_BUFFER &&
2816 target != GL_COPY_WRITE_BUFFER &&
2817 target != GL_PIXEL_PACK_BUFFER &&
2818 target != GL_PIXEL_UNPACK_BUFFER &&
2819 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
2820 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002821 GL_INVALID_ENUM);
2822 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
2823 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002824 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
2825 pname != GL_BUFFER_MAPPED &&
2826 pname != GL_BUFFER_SIZE &&
2827 pname != GL_BUFFER_USAGE &&
2828 pname != GL_BUFFER_MAP_LENGTH &&
2829 pname != GL_BUFFER_MAP_OFFSET,
2830 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002831
2832 if (!params) return;
2833
2834 BufferData* buf = ctx->getBufferData(target);
2835
2836 switch (pname) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002837 case GL_BUFFER_ACCESS_FLAGS:
2838 *params = buf ? buf->m_mappedAccess : 0;
2839 break;
2840 case GL_BUFFER_MAPPED:
2841 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
2842 break;
2843 case GL_BUFFER_SIZE:
2844 *params = buf ? buf->m_size : 0;
2845 break;
2846 case GL_BUFFER_USAGE:
2847 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
2848 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002849 case GL_BUFFER_MAP_LENGTH:
2850 *params = buf ? buf->m_mappedLength : 0;
2851 break;
2852 case GL_BUFFER_MAP_OFFSET:
2853 *params = buf ? buf->m_mappedOffset : 0;
2854 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002855 default:
2856 break;
2857 }
2858}
2859
2860void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
2861 GL2Encoder* ctx = (GL2Encoder*)self;
2862 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2863 SET_ERROR_IF(
2864 target == GL_ATOMIC_COUNTER_BUFFER ||
2865 target == GL_DISPATCH_INDIRECT_BUFFER ||
2866 target == GL_DRAW_INDIRECT_BUFFER ||
2867 target == GL_SHADER_STORAGE_BUFFER,
2868 GL_INVALID_ENUM);
2869 SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
2870 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
2871 if (!params) return;
2872
2873 BufferData* buf = ctx->getBufferData(target);
2874
2875 if (!buf || !buf->m_mapped) { *params = NULL; return; }
2876
2877 *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
2878}
2879
2880static const char* const kNameDelimiter = ";";
2881
2882static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
2883
2884#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
2885
2886 std::string packed;
2887 // validate the array of char[]'s
2888 const char* currName;
2889 for (GLsizei i = 0; i < count; i++) {
2890 currName = names[i];
2891 VALIDATE(!currName, GL_INVALID_OPERATION);
2892 // check if has reasonable size
2893 size_t len = strlen(currName);
2894 VALIDATE(!len, GL_INVALID_OPERATION);
2895 // check for our delimiter, which if present
2896 // in the name, means an invalid name anyway.
2897 VALIDATE(strstr(currName, kNameDelimiter),
2898 GL_INVALID_OPERATION);
2899 packed += currName;
2900 packed += ";";
2901 }
2902
2903 *err_out = GL_NO_ERROR;
2904 return packed;
2905}
2906
2907void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
2908 GL2Encoder* ctx = (GL2Encoder*)self;
2909
2910 if (!uniformCount) return;
2911
2912 GLint err = GL_NO_ERROR;
2913 std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
2914 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
2915
2916 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
2917 std::vector<int> arrIndices;
2918 for (size_t i = 0; i < uniformCount; i++) {
2919 int err;
2920 arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
2921 if (err) {
2922 ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
2923 return;
2924 }
2925 }
2926
2927 ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
2928
2929 for (int i = 0; i < uniformCount; i++) {
2930 if (uniformIndices[i] >= 0 && needLocationWAR) {
2931 uniformIndices[i] =
2932 ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
2933 }
2934 }
2935}
2936
2937void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
2938 GL2Encoder *ctx = (GL2Encoder*)self;
2939 GLClientState* state = ctx->m_state;
2940 GLSharedGroupPtr shared = ctx->m_shared;
2941
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002942 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002943 ctx->m_glUniform1ui_enc(self, hostLoc, v0);
2944
2945 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002946 if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002947 GLenum origActiveTexture = state->getActiveTextureUnit();
2948 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
2949 ctx->m_glActiveTexture_enc(self, origActiveTexture);
2950 }
2951 state->setActiveTextureUnit(origActiveTexture);
2952 }
2953}
2954
2955void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) {
2956 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002957 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002958 ctx->m_glUniform2ui_enc(self, hostLoc, v0, v1);
2959}
2960
2961void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) {
2962 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002963 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002964 ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2);
2965}
2966
2967void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) {
2968 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002969 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002970 ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3);
2971}
2972
2973void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2974 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002975 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002976 ctx->m_glUniform1uiv_enc(self, hostLoc, count, value);
2977}
2978
2979void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2980 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002981 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002982 ctx->m_glUniform2uiv_enc(self, hostLoc, count, value);
2983}
2984
2985void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2986 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002987 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002988 ctx->m_glUniform3uiv_enc(self, hostLoc, count, value);
2989}
2990
2991void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2992 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002993 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002994 ctx->m_glUniform4uiv_enc(self, hostLoc, count, value);
2995}
2996
2997void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
2998 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002999 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003000 ctx->m_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value);
3001}
3002
3003void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3004 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003005 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003006 ctx->m_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value);
3007}
3008
3009void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3010 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003011 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003012 ctx->m_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value);
3013}
3014
3015void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3016 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003017 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003018 ctx->m_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value);
3019}
3020
3021void GL2Encoder::s_glUniformMatrix3x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3022 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003023 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003024 ctx->m_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value);
3025}
3026
3027void GL2Encoder::s_glUniformMatrix4x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3028 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003029 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003030 ctx->m_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value);
3031}
3032
3033void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3034 GL2Encoder *ctx = (GL2Encoder*)self;
3035 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3036 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3037 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3038 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3039 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3040 ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3041}
3042
3043void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3044 GL2Encoder* ctx = (GL2Encoder*)self;
3045 GLClientState* state = ctx->m_state;
3046
3047 // refresh client state's # active uniforms in this block
3048 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3049 // TODO if worth it: cache uniform count and other params,
3050 // invalidate on program relinking.
3051 GLint numActiveUniforms;
3052 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3053 program, uniformBlockIndex,
3054 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3055 &numActiveUniforms);
3056 ctx->m_state->setNumActiveUniformsInUniformBlock(
3057 program, uniformBlockIndex, numActiveUniforms);
3058 }
3059
3060 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3061 program, uniformBlockIndex,
3062 pname, params);
3063}
3064
3065void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3066 GL2Encoder *ctx = (GL2Encoder *)self;
3067 assert(ctx->m_state);
3068 GLint maxIndex;
3069 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3070 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3071
3072 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3073 ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3074 }
3075}
3076
3077void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3078 GL2Encoder *ctx = (GL2Encoder *)self;
3079 assert(ctx->m_state);
3080 GLint maxIndex;
3081 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3082 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3083
3084 if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3085 ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3086 }
3087}
3088
3089void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3090 GL2Encoder *ctx = (GL2Encoder *)self;
3091 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003092 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003093 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
3094 SET_ERROR_IF(
3095 !(type == GL_BYTE ||
3096 type == GL_UNSIGNED_BYTE ||
3097 type == GL_SHORT ||
3098 type == GL_UNSIGNED_SHORT ||
3099 type == GL_INT ||
3100 type == GL_UNSIGNED_INT),
3101 GL_INVALID_ENUM);
3102 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
3103
3104 ctx->m_state->setVertexAttribBinding(index, index);
3105 ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true);
3106 GLsizei effectiveStride = stride;
3107 if (stride == 0) {
3108 effectiveStride = glSizeof(type) * size;
3109 }
3110 ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride);
3111
3112 if (ctx->m_state->currentArrayVbo() != 0) {
3113 ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer);
3114 } else {
3115 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION);
3116 // wait for client-array handler
3117 }
3118}
3119
3120void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) {
3121 GL2Encoder *ctx = (GL2Encoder *)self;
3122 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003123 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003124 ctx->m_state->setVertexAttribBinding(index, index);
3125 ctx->m_state->setVertexBindingDivisor(index, divisor);
3126 ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor);
3127}
3128
3129void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3130 GLenum target, GLsizei samples, GLenum internalformat,
3131 GLsizei width, GLsizei height) {
3132 GL2Encoder *ctx = (GL2Encoder *)self;
3133 GLClientState* state = ctx->m_state;
3134
3135 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3136 SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3137
3138 GLint max_samples;
3139 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3140 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3141
3142 state->setBoundRenderbufferFormat(internalformat);
3143 state->setBoundRenderbufferSamples(samples);
3144 ctx->m_glRenderbufferStorageMultisample_enc(
3145 self, target, samples, internalformat, width, height);
3146}
3147
3148void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3149 GL2Encoder* ctx = (GL2Encoder*)self;
3150 SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3151 SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3152 for (int i = 0; i < n; i++) {
3153 SET_ERROR_IF(
3154 bufs[i] != GL_NONE &&
3155 bufs[i] != GL_BACK &&
3156 glUtilsColorAttachmentIndex(bufs[i]) == -1,
3157 GL_INVALID_ENUM);
3158 SET_ERROR_IF(
3159 !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3160 glUtilsColorAttachmentIndex(bufs[i]) != -1,
3161 GL_INVALID_OPERATION);
3162 SET_ERROR_IF(
3163 ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3164 ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3165 glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3166 (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3167 bufs[i] != GL_NONE)),
3168 GL_INVALID_OPERATION);
3169 }
3170
3171 ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3172}
3173
3174void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3175 GL2Encoder* ctx = (GL2Encoder*)self;
3176
3177 SET_ERROR_IF(
3178 glUtilsColorAttachmentIndex(src) != -1 &&
3179 (glUtilsColorAttachmentIndex(src) >=
3180 ctx->m_state->getMaxColorAttachments()),
3181 GL_INVALID_OPERATION);
3182 SET_ERROR_IF(
3183 src != GL_NONE &&
3184 src != GL_BACK &&
3185 src > GL_COLOR_ATTACHMENT0 &&
3186 src < GL_DEPTH_ATTACHMENT &&
3187 (src - GL_COLOR_ATTACHMENT0) >
3188 ctx->m_state->getMaxColorAttachments(),
3189 GL_INVALID_OPERATION);
3190 SET_ERROR_IF(
3191 src != GL_NONE &&
3192 src != GL_BACK &&
3193 glUtilsColorAttachmentIndex(src) == -1,
3194 GL_INVALID_ENUM);
3195 SET_ERROR_IF(
3196 !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3197 src != GL_NONE &&
3198 src != GL_BACK,
3199 GL_INVALID_OPERATION);
3200 SET_ERROR_IF(
3201 ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3202 src != GL_NONE &&
3203 glUtilsColorAttachmentIndex(src) == -1,
3204 GL_INVALID_OPERATION);
3205
3206 ctx->m_glReadBuffer_enc(ctx, src);
3207}
3208
3209void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3210 GL2Encoder* ctx = (GL2Encoder*)self;
3211 GLClientState* state = ctx->m_state;
3212
3213 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3214 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3215 GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3216 SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3217 lastBoundTarget != GL_TEXTURE_3D,
3218 GL_INVALID_OPERATION);
3219 state->attachTextureObject(target, attachment, texture);
3220
3221 GLint max3DTextureSize;
3222 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3223 SET_ERROR_IF(
3224 layer >= max3DTextureSize,
3225 GL_INVALID_VALUE);
3226
3227 ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3228}
3229
3230void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3231 GL2Encoder* ctx = (GL2Encoder*)self;
3232 GLClientState* state = ctx->m_state;
3233
3234 SET_ERROR_IF(
3235 target != GL_TEXTURE_2D &&
3236 target != GL_TEXTURE_CUBE_MAP,
3237 GL_INVALID_ENUM);
3238 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3239 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3240 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3241 SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3242 GL_INVALID_OPERATION);
3243 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3244
3245 state->setBoundTextureInternalFormat(target, internalformat);
3246 state->setBoundTextureDims(target, -1, width, height, 1);
3247 state->setBoundTextureImmutableFormat(target);
3248 ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
3249}
3250
3251void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3252 GL2Encoder* ctx = (GL2Encoder*)self;
3253
3254 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3255
3256 GLint maxCount = 0;
3257 ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3258
3259 SET_ERROR_IF(
3260 bufferMode == GL_SEPARATE_ATTRIBS &&
3261 maxCount < count,
3262 GL_INVALID_VALUE);
3263 SET_ERROR_IF(
3264 bufferMode != GL_INTERLEAVED_ATTRIBS &&
3265 bufferMode != GL_SEPARATE_ATTRIBS,
3266 GL_INVALID_ENUM);
3267
3268 if (!count) return;
3269
3270 GLint err = GL_NO_ERROR;
3271 std::string packed = packVarNames(count, varyings, &err);
3272 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3273
3274 ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3275}
3276
3277void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3278 GL2Encoder* ctx = (GL2Encoder*)self;
3279 GLClientState* state = ctx->m_state;
3280 ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3281 state->setTransformFeedbackActiveUnpaused(true);
3282}
3283
3284void GL2Encoder::s_glEndTransformFeedback(void* self) {
3285 GL2Encoder* ctx = (GL2Encoder*)self;
3286 GLClientState* state = ctx->m_state;
3287 ctx->m_glEndTransformFeedback_enc(ctx);
3288 state->setTransformFeedbackActiveUnpaused(false);
3289}
3290
3291void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3292 GL2Encoder* ctx = (GL2Encoder*)self;
3293 GLClientState* state = ctx->m_state;
3294 ctx->m_glPauseTransformFeedback_enc(ctx);
3295 state->setTransformFeedbackActiveUnpaused(false);
3296}
3297
3298void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3299 GL2Encoder* ctx = (GL2Encoder*)self;
3300 GLClientState* state = ctx->m_state;
3301 ctx->m_glResumeTransformFeedback_enc(ctx);
3302 state->setTransformFeedbackActiveUnpaused(true);
3303}
3304
3305void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3306 GLsizei width, GLsizei height, GLsizei depth,
3307 GLint border, GLenum format, GLenum type, const GLvoid* data) {
3308 GL2Encoder* ctx = (GL2Encoder*)self;
3309 GLClientState* state = ctx->m_state;
3310
3311 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3312 target != GL_TEXTURE_2D_ARRAY,
3313 GL_INVALID_ENUM);
3314 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3315 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3316
3317 // If unpack buffer is nonzero, verify unmapped state.
3318 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3319
3320 GLint max_texture_size;
3321 GLint max_3d_texture_size;
3322 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3323 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3324 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3325 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3326 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3327
3328 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3329 SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3330 SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3331 SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3332 SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3333 SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3334 SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3335 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3336 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3337 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3338 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3339 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3340 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3341 GL_INVALID_OPERATION);
3342 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3343 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3344 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3345 glSizeof(type)),
3346 GL_INVALID_OPERATION);
3347 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3348
3349 state->setBoundTextureInternalFormat(target, internalFormat);
3350 state->setBoundTextureFormat(target, format);
3351 state->setBoundTextureType(target, type);
3352 state->setBoundTextureDims(target, level, width, height, depth);
3353
3354 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3355 ctx->glTexImage3DOffsetAEMU(
3356 ctx, target, level, internalFormat,
3357 width, height, depth,
3358 border, format, type, (uintptr_t)data);
3359 } else {
3360 ctx->m_glTexImage3D_enc(ctx,
3361 target, level, internalFormat,
3362 width, height, depth,
3363 border, format, type, data);
3364 }
3365}
3366
3367void GL2Encoder::s_glTexSubImage3D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* data) {
3368 GL2Encoder* ctx = (GL2Encoder*)self;
3369 GLClientState* state = ctx->m_state;
3370
3371 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3372 target != GL_TEXTURE_2D_ARRAY,
3373 GL_INVALID_ENUM);
3374 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3375 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3376 // If unpack buffer is nonzero, verify unmapped state.
3377 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3378 GLint max_texture_size;
3379 GLint max_3d_texture_size;
3380 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3381 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3382 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3383 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3384 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3385 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3386 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3387 GLuint tex = state->getBoundTexture(target);
3388 GLsizei neededWidth = xoffset + width;
3389 GLsizei neededHeight = yoffset + height;
3390 GLsizei neededDepth = zoffset + depth;
3391
3392 SET_ERROR_IF(tex &&
3393 (neededWidth > state->queryTexWidth(level, tex) ||
3394 neededHeight > state->queryTexHeight(level, tex) ||
3395 neededDepth > state->queryTexDepth(level, tex)),
3396 GL_INVALID_VALUE);
3397 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3398 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3399 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3400 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3401 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3402 GL_INVALID_OPERATION);
3403 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3404 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3405 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3406 glSizeof(type)),
3407 GL_INVALID_OPERATION);
3408 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
3409 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3410
3411 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3412 ctx->glTexSubImage3DOffsetAEMU(ctx,
3413 target, level,
3414 xoffset, yoffset, zoffset,
3415 width, height, depth,
3416 format, type, (uintptr_t)data);
3417 } else {
3418 ctx->m_glTexSubImage3D_enc(ctx,
3419 target, level,
3420 xoffset, yoffset, zoffset,
3421 width, height, depth,
3422 format, type, data);
3423 }
3424}
3425
3426void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
3427 GL2Encoder* ctx = (GL2Encoder*)self;
3428 GLClientState* state = ctx->m_state;
3429
3430 // Filter compressed formats support.
3431 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3432 // If unpack buffer is nonzero, verify unmapped state.
3433 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3434 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3435 SET_ERROR_IF(border, GL_INVALID_VALUE);
3436 // If unpack buffer is nonzero, verify buffer data fits.
3437 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3438 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3439 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3440 GL_INVALID_OPERATION);
3441 // TODO: Fix:
3442 // If |imageSize| is too small for compressed dimensions.
3443 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
3444 state->setBoundTextureInternalFormat(target, (GLint)internalformat);
3445 state->setBoundTextureDims(target, level, width, height, depth);
3446
3447 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3448 ctx->glCompressedTexImage3DOffsetAEMU(
3449 ctx, target, level, internalformat,
3450 width, height, depth, border,
3451 imageSize, (uintptr_t)data);
3452 } else {
3453 ctx->m_glCompressedTexImage3D_enc(
3454 ctx, target, level, internalformat,
3455 width, height, depth, border,
3456 imageSize, data);
3457 }
3458}
3459
3460void GL2Encoder::s_glCompressedTexSubImage3D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) {
3461 GL2Encoder* ctx = (GL2Encoder*)self;
3462 GLClientState* state = ctx->m_state;
3463
3464 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3465 // If unpack buffer is nonzero, verify unmapped state.
3466 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3467 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3468 // If unpack buffer is nonzero, verify buffer data fits.
3469 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3470 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3471 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3472 GL_INVALID_OPERATION);
3473 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3474
3475 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3476 ctx->glCompressedTexSubImage3DOffsetAEMU(
3477 ctx, target, level,
3478 xoffset, yoffset, zoffset,
3479 width, height, depth,
3480 format, imageSize, (uintptr_t)data);
3481 } else {
3482 ctx->m_glCompressedTexSubImage3D_enc(
3483 ctx, target, level,
3484 xoffset, yoffset, zoffset,
3485 width, height, depth,
3486 format, imageSize, data);
3487
3488 }
3489}
3490
3491void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
3492 GL2Encoder* ctx = (GL2Encoder*)self;
3493 GLClientState* state = ctx->m_state;
3494 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3495 target != GL_TEXTURE_2D_ARRAY,
3496 GL_INVALID_ENUM);
3497 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3498 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3499 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3500 SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
3501 GL_INVALID_OPERATION);
3502 SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
3503 GL_INVALID_OPERATION);
3504 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3505
3506 state->setBoundTextureInternalFormat(target, internalformat);
3507 state->setBoundTextureDims(target, -1, width, height, depth);
3508 state->setBoundTextureImmutableFormat(target);
3509 ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
3510 state->setBoundTextureImmutableFormat(target);
3511}
3512
3513void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
3514 GL2Encoder *ctx = (GL2Encoder *)self;
3515 assert(ctx->m_state != NULL);
3516 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3517 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3518
3519 bool has_client_vertex_arrays = false;
3520 bool has_indirect_arrays = false;
3521 ctx->getVBOUsage(&has_client_vertex_arrays,
3522 &has_indirect_arrays);
3523
3524 if (has_client_vertex_arrays ||
3525 (!has_client_vertex_arrays &&
3526 !has_indirect_arrays)) {
3527 ctx->sendVertexAttributes(first, count, true, primcount);
3528 ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
3529 } else {
3530 ctx->sendVertexAttributes(0, count, false, primcount);
3531 ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
3532 }
3533 ctx->m_stream->flush();
3534}
3535
3536void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
3537{
3538
3539 GL2Encoder *ctx = (GL2Encoder *)self;
3540 assert(ctx->m_state != NULL);
3541 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3542 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3543 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3544 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3545
3546 bool has_client_vertex_arrays = false;
3547 bool has_indirect_arrays = false;
3548 int nLocations = ctx->m_state->nLocations();
3549 GLintptr offset = 0;
3550
3551 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3552
3553 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3554 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3555 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3556 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3557 }
3558
3559 BufferData* buf = NULL;
3560 int minIndex = 0, maxIndex = 0;
3561
3562 // For validation/immediate index array purposes,
3563 // we need the min/max vertex index of the index array.
3564 // If the VBO != 0, this may not be the first time we have
3565 // used this particular index buffer. getBufferIndexRange
3566 // can more quickly get min/max vertex index by
3567 // caching previous results.
3568 if (ctx->m_state->currentIndexVbo() != 0) {
3569 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3570 offset = (GLintptr)indices;
3571 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3572 ctx->getBufferIndexRange(buf,
3573 indices,
3574 type,
3575 (size_t)count,
3576 (size_t)offset,
3577 &minIndex, &maxIndex);
3578 } else {
3579 // In this case, the |indices| field holds a real
3580 // array, so calculate the indices now. They will
3581 // also be needed to know how much data to
3582 // transfer to host.
3583 ctx->calcIndexRange(indices,
3584 type,
3585 count,
3586 &minIndex,
3587 &maxIndex);
3588 }
3589
3590 bool adjustIndices = true;
3591 if (ctx->m_state->currentIndexVbo() != 0) {
3592 if (!has_client_vertex_arrays) {
3593 ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
3594 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3595 ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
3596 ctx->flushDrawCall();
3597 adjustIndices = false;
3598 } else {
3599 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3600 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3601 }
3602 }
3603 if (adjustIndices) {
3604 void *adjustedIndices =
3605 ctx->recenterIndices(indices,
3606 type,
3607 count,
3608 minIndex);
3609
3610 if (has_indirect_arrays || 1) {
3611 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
3612 ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
3613 ctx->m_stream->flush();
3614 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3615 if(!has_indirect_arrays) {
3616 //ALOGD("unoptimized drawelements !!!\n");
3617 }
3618 } else {
3619 // we are all direct arrays and immidate mode index array -
3620 // rebuild the arrays and the index array;
3621 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3622 }
3623 }
3624}
3625
3626void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
3627{
3628
3629 GL2Encoder *ctx = (GL2Encoder *)self;
3630 assert(ctx->m_state != NULL);
3631 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3632 SET_ERROR_IF(end < start, GL_INVALID_VALUE);
3633 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3634 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3635 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3636
3637 bool has_client_vertex_arrays = false;
3638 bool has_indirect_arrays = false;
3639 int nLocations = ctx->m_state->nLocations();
3640 GLintptr offset = 0;
3641
3642 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3643
3644 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3645 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3646 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3647 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3648 }
3649
3650 BufferData* buf = NULL;
3651 int minIndex = 0, maxIndex = 0;
3652
3653 // For validation/immediate index array purposes,
3654 // we need the min/max vertex index of the index array.
3655 // If the VBO != 0, this may not be the first time we have
3656 // used this particular index buffer. getBufferIndexRange
3657 // can more quickly get min/max vertex index by
3658 // caching previous results.
3659 if (ctx->m_state->currentIndexVbo() != 0) {
3660 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3661 offset = (GLintptr)indices;
3662 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3663 ctx->getBufferIndexRange(buf,
3664 indices,
3665 type,
3666 (size_t)count,
3667 (size_t)offset,
3668 &minIndex, &maxIndex);
3669 } else {
3670 // In this case, the |indices| field holds a real
3671 // array, so calculate the indices now. They will
3672 // also be needed to know how much data to
3673 // transfer to host.
3674 ctx->calcIndexRange(indices,
3675 type,
3676 count,
3677 &minIndex,
3678 &maxIndex);
3679 }
3680
3681 bool adjustIndices = true;
3682 if (ctx->m_state->currentIndexVbo() != 0) {
3683 if (!has_client_vertex_arrays) {
3684 ctx->sendVertexAttributes(0, maxIndex + 1, false);
3685 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3686 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
3687 ctx->flushDrawCall();
3688 adjustIndices = false;
3689 } else {
3690 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3691 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3692 }
3693 }
3694 if (adjustIndices) {
3695 void *adjustedIndices =
3696 ctx->recenterIndices(indices,
3697 type,
3698 count,
3699 minIndex);
3700
3701 if (has_indirect_arrays || 1) {
3702 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
3703 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
3704 ctx->m_stream->flush();
3705 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3706 if(!has_indirect_arrays) {
3707 //ALOGD("unoptimized drawelements !!!\n");
3708 }
3709 } else {
3710 // we are all direct arrays and immidate mode index array -
3711 // rebuild the arrays and the index array;
3712 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3713 }
3714 }
3715}
3716
3717// struct GLStringKey {
3718// GLenum name;
3719// GLuint index;
3720// };
3721//
3722// struct GLStringKeyCompare {
3723// bool operator() (const GLStringKey& a,
3724// const GLStringKey& b) const {
3725// if (a.name != b.name) return a.name < b.name;
3726// if (a.index != b.index) return a.index < b.index;
3727// return false;
3728// }
3729// };
3730//
3731// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
3732//
3733// static GLStringStore sGLStringStore;
3734// bool sGLStringStoreInitialized = false;
3735
3736const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
3737 GL2Encoder *ctx = (GL2Encoder *)self;
3738 GLubyte *retval = (GLubyte *) "";
3739
3740 RET_AND_SET_ERROR_IF(
3741 name != GL_VENDOR &&
3742 name != GL_RENDERER &&
3743 name != GL_VERSION &&
3744 name != GL_EXTENSIONS,
3745 GL_INVALID_ENUM,
3746 retval);
3747
3748 RET_AND_SET_ERROR_IF(
3749 name == GL_VENDOR ||
3750 name == GL_RENDERER ||
3751 name == GL_VERSION ||
3752 name == GL_EXTENSIONS &&
3753 index != 0,
3754 GL_INVALID_VALUE,
3755 retval);
3756
3757 switch (name) {
3758 case GL_VENDOR:
3759 retval = gVendorString;
3760 break;
3761 case GL_RENDERER:
3762 retval = gRendererString;
3763 break;
3764 case GL_VERSION:
3765 retval = gVersionString;
3766 break;
3767 case GL_EXTENSIONS:
3768 retval = gExtensionsString;
3769 break;
3770 }
3771
3772 return retval;
3773}
3774
3775void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
3776 GL2Encoder *ctx = (GL2Encoder *)self;
3777
3778 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3779
3780 GLint linkStatus = 0;
3781 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
3782 GLint properLength = 0;
3783 ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
3784
3785 SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
3786 SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
3787
3788 ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
3789}
3790
3791void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
3792 GL2Encoder *ctx = (GL2Encoder *)self;
3793
3794 SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
3795 SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
3796 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
3797 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
3798 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
3799 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
3800 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
3801 ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
3802 GL_INVALID_OPERATION);
3803 /*
3804GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is a fixed point normalized surface and format and type are neither GL_RGBA and GL_UNSIGNED_BYTE, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
3805
3806GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is a floating point surface and format and type are neither GL_RGBA and GL_FLOAT, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
3807
3808GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is a signed integer surface and format and type are neither GL_RGBA_INTEGER and GL_INT, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
3809
3810GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is an unsigned integer surface and format and type are neither GL_RGBA_INTEGER and GL_UNSIGNED_INT, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
3811*/
3812
3813 FboFormatInfo fbo_format_info;
3814 ctx->m_state->getBoundFramebufferFormat(
3815 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
3816 SET_ERROR_IF(
3817 fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3818 !GLESv2Validation::readPixelsFboFormatMatch(
3819 format, type, fbo_format_info.tex_type),
3820 GL_INVALID_OPERATION);
3821
3822 if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
3823 ctx->glReadPixelsOffsetAEMU(
3824 ctx, x, y, width, height,
3825 format, type, (uintptr_t)pixels);
3826 } else {
3827 ctx->m_glReadPixels_enc(
3828 ctx, x, y, width, height,
3829 format, type, pixels);
3830 }
3831}
3832
3833// Track enabled state for some things like:
3834// - Primitive restart
3835void GL2Encoder::s_glEnable(void* self, GLenum what) {
3836 GL2Encoder *ctx = (GL2Encoder *)self;
3837
3838 switch (what) {
3839 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
3840 ctx->m_primitiveRestartEnabled = true;
3841 break;
3842 }
3843
3844 ctx->m_glEnable_enc(ctx, what);
3845}
3846
3847void GL2Encoder::s_glDisable(void* self, GLenum what) {
3848 GL2Encoder *ctx = (GL2Encoder *)self;
3849
3850 switch (what) {
3851 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
3852 ctx->m_primitiveRestartEnabled = false;
3853 break;
3854 }
3855
3856 ctx->m_glDisable_enc(ctx, what);
3857}
3858
3859void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
3860 GL2Encoder *ctx = (GL2Encoder *)self;
3861
3862 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3863
3864 ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
3865}
3866
3867void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
3868 GL2Encoder *ctx = (GL2Encoder *)self;
3869
3870 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3871
3872 ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
3873}
3874
3875void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
3876 GL2Encoder *ctx = (GL2Encoder *)self;
3877
3878 SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3879
3880 ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
3881}
3882
3883void GL2Encoder::s_glBlitFramebuffer(void* self, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
3884 GL2Encoder *ctx = (GL2Encoder *)self;
3885 GLClientState* state = ctx->m_state;
3886
3887 bool validateColor = mask | GL_COLOR_BUFFER_BIT;
3888 bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
3889 bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
3890
3891 FboFormatInfo read_fbo_format_info;
3892 FboFormatInfo draw_fbo_format_info;
3893 if (validateColor) {
3894 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
3895 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
3896
3897 if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3898 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
3899 SET_ERROR_IF(
3900 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3901 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3902 !GLESv2Validation::blitFramebufferFormat(
3903 read_fbo_format_info.tex_type,
3904 draw_fbo_format_info.tex_type),
3905 GL_INVALID_OPERATION);
3906 }
3907 }
3908
3909 if (validateDepth) {
3910 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
3911 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
3912
3913 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3914 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
3915 SET_ERROR_IF(
3916 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3917 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3918 !GLESv2Validation::blitFramebufferFormat(
3919 read_fbo_format_info.rb_format,
3920 draw_fbo_format_info.rb_format),
3921 GL_INVALID_OPERATION);
3922 }
3923 }
3924
3925 if (validateStencil) {
3926 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
3927 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
3928
3929 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3930 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
3931 SET_ERROR_IF(
3932 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3933 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3934 !GLESv2Validation::blitFramebufferFormat(
3935 read_fbo_format_info.rb_format,
3936 draw_fbo_format_info.rb_format),
3937 GL_INVALID_OPERATION);
3938 }
3939 }
3940
3941 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
3942 SET_ERROR_IF(
3943 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3944 draw_fbo_format_info.rb_multisamples > 0,
3945 GL_INVALID_OPERATION);
3946 SET_ERROR_IF(
3947 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3948 draw_fbo_format_info.tex_multisamples > 0,
3949 GL_INVALID_OPERATION);
3950
3951 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
3952 SET_ERROR_IF(
3953 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3954 read_fbo_format_info.rb_multisamples > 0 &&
3955 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3956 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3957 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3958 (read_fbo_format_info.rb_format !=
3959 draw_fbo_format_info.rb_format),
3960 GL_INVALID_OPERATION);
3961 SET_ERROR_IF(
3962 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3963 read_fbo_format_info.rb_multisamples > 0 &&
3964 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3965 (srcX0 != dstX0 || srcY0 != dstY0 ||
3966 srcX1 != dstX1 || srcY1 != dstY1),
3967 GL_INVALID_OPERATION);
3968
3969 ctx->m_glBlitFramebuffer_enc(ctx,
3970 srcX0, srcY0, srcX1, srcY1,
3971 dstX0, dstY0, dstX1, dstY1,
3972 mask, filter);
3973}
3974
3975void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
3976 GL2Encoder *ctx = (GL2Encoder *)self;
3977
3978 SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
3979 pname != GL_SAMPLES,
3980 GL_INVALID_ENUM);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003981 SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003982 SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08003983 !GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
3984 !GLESv2Validation::depthRenderableFormat(ctx, internalformat) &&
3985 !GLESv2Validation::stencilRenderableFormat(ctx, internalformat),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003986 GL_INVALID_ENUM);
3987 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
3988
3989 if (bufSize < 1) return;
3990
3991 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
3992 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
3993 switch (pname) {
3994 case GL_NUM_SAMPLE_COUNTS:
3995 *params = 3;
3996 break;
3997 case GL_SAMPLES:
3998 params[0] = 4;
3999 if (bufSize > 1) params[1] = 2;
4000 if (bufSize > 2) params[2] = 1;
4001 break;
4002 default:
4003 break;
4004 }
4005}
4006
4007void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
4008 GL2Encoder *ctx = (GL2Encoder *)self;
4009 GLClientState* state = ctx->m_state;
4010
4011 SET_ERROR_IF(target != GL_TEXTURE_2D &&
4012 target != GL_TEXTURE_3D &&
4013 target != GL_TEXTURE_CUBE_MAP,
4014 GL_INVALID_ENUM);
4015
4016 GLuint tex = state->getBoundTexture(target);
4017 GLenum internalformat = state->queryTexInternalFormat(tex);
4018 GLenum format = state->queryTexFormat(tex);
4019
4020 SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
4021 GL_INVALID_OPERATION);
4022 SET_ERROR_IF(tex &&
4023 !GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004024 !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4025 GLESv2Validation::filterableTexFormat(ctx, internalformat)),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004026 GL_INVALID_OPERATION);
4027
4028 ctx->m_glGenerateMipmap_enc(ctx, target);
4029}
4030
4031void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4032 GL2Encoder *ctx = (GL2Encoder *)self;
4033 GLint maxCombinedUnits;
4034 ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4035 SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4036
4037 ctx->m_glBindSampler_enc(ctx, unit, sampler);
4038}
4039
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004040GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4041 GL2Encoder *ctx = (GL2Encoder *)self;
4042 uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4043 return (GLsync)(uintptr_t)syncHandle;
4044}
4045
4046GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4047 GL2Encoder *ctx = (GL2Encoder *)self;
4048 return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4049}
4050
4051void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4052 GL2Encoder *ctx = (GL2Encoder *)self;
4053 ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4054}
4055
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004056void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) {
4057 GL2Encoder *ctx = (GL2Encoder *)self;
4058
4059 if (!sync) return;
4060
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004061 ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4062}
4063
4064GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4065 GL2Encoder *ctx = (GL2Encoder *)self;
4066 return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4067}
4068
4069void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4070 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004071
4072 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4073
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004074 return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004075}
4076
4077#define LIMIT_CASE(target, lim) \
4078 case target: \
4079 ctx->glGetIntegerv(ctx, lim, &limit); \
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004080 SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004081 break; \
4082
4083void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) {
4084 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004085 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004086
4087 GLint limit;
4088
4089 switch (target) {
4090 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4091 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4092 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4093 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4094 default:
4095 break;
4096 }
4097
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004098 const GLClientState::VertexAttribBindingVector& currBindings =
4099 state->currentVertexBufferBindings();
4100
4101 switch (target) {
4102 case GL_VERTEX_BINDING_DIVISOR:
4103 case GL_VERTEX_BINDING_OFFSET:
4104 case GL_VERTEX_BINDING_STRIDE:
4105 case GL_VERTEX_BINDING_BUFFER:
4106 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4107 break;
4108 default:
4109 break;
4110 }
4111
4112 switch (target) {
4113 case GL_VERTEX_BINDING_DIVISOR:
4114 *params = currBindings[index].divisor;
4115 return;
4116 case GL_VERTEX_BINDING_OFFSET:
4117 *params = currBindings[index].offset;
4118 return;
4119 case GL_VERTEX_BINDING_STRIDE:
4120 *params = currBindings[index].effectiveStride;
4121 return;
4122 case GL_VERTEX_BINDING_BUFFER:
4123 *params = currBindings[index].buffer;
4124 return;
4125 default:
4126 break;
4127 }
4128
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004129 ctx->m_glGetIntegeri_v_enc(self, target, index, params);
4130}
4131
4132void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
4133 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004134 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004135
4136 GLint limit;
4137
4138 switch (target) {
4139 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4140 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4141 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4142 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4143 default:
4144 break;
4145 }
4146
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004147 const GLClientState::VertexAttribBindingVector& currBindings =
4148 state->currentVertexBufferBindings();
4149
4150 switch (target) {
4151 case GL_VERTEX_BINDING_DIVISOR:
4152 case GL_VERTEX_BINDING_OFFSET:
4153 case GL_VERTEX_BINDING_STRIDE:
4154 case GL_VERTEX_BINDING_BUFFER:
4155 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4156 break;
4157 default:
4158 break;
4159 }
4160
4161 switch (target) {
4162 case GL_VERTEX_BINDING_DIVISOR:
4163 *params = currBindings[index].divisor;
4164 return;
4165 case GL_VERTEX_BINDING_OFFSET:
4166 *params = currBindings[index].offset;
4167 return;
4168 case GL_VERTEX_BINDING_STRIDE:
4169 *params = currBindings[index].effectiveStride;
4170 return;
4171 case GL_VERTEX_BINDING_BUFFER:
4172 *params = currBindings[index].buffer;
4173 return;
4174 default:
4175 break;
4176 }
4177
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004178 ctx->m_glGetInteger64i_v_enc(self, target, index, params);
4179}
4180
4181void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4182 GL2Encoder *ctx = (GL2Encoder *)self;
4183 ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4184 if (pname == GL_SHADER_SOURCE_LENGTH) {
4185 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4186 if (shaderData) {
4187 int totalLen = 0;
4188 for (int i = 0; i < shaderData->sources.size(); i++) {
4189 totalLen += shaderData->sources[i].size();
4190 }
4191 if (totalLen != 0) {
4192 *params = totalLen + 1; // account for null terminator
4193 }
4194 }
4195 }
4196}
4197
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004198void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) {
4199 GL2Encoder *ctx = (GL2Encoder*)self;
4200 GLClientState* state = ctx->m_state;
4201 GLSharedGroupPtr shared = ctx->m_shared;
4202
4203 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4204 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4205 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4206
4207 ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program);
4208 if (!state->currentProgram()) {
4209 state->setCurrentShaderProgram(program);
4210 }
4211}
4212
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004213GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4214
4215 GLint* length = NULL;
4216 GL2Encoder* ctx = (GL2Encoder*)self;
4217
4218 int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
4219 char *str = new char[len + 1];
4220 glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
4221
4222 // Do GLSharedGroup and location WorkARound-specific initialization
4223 // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4224 uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4225 ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
4226 ShaderData* sData = spData->shaderData;
4227
4228 if (!replaceSamplerExternalWith2D(str, sData)) {
4229 delete [] str;
4230 ctx->setError(GL_OUT_OF_MEMORY);
4231 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4232 return -1;
4233 }
4234
4235 GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
4236 delete [] str;
4237
4238 // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4239 GLint linkStatus = 0;
4240 ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4241 if (!linkStatus) {
4242 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4243 return -1;
4244 }
4245
4246 ctx->m_shared->associateGLShaderProgram(res, spDataId);
4247
4248 GLint numUniforms = 0;
4249 ctx->glGetProgramiv(ctx, res, GL_ACTIVE_UNIFORMS, &numUniforms);
4250 ctx->m_shared->initShaderProgramData(res, numUniforms);
4251
4252 GLint maxLength=0;
4253 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4254
4255 GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4256
4257 for (GLint i = 0; i < numUniforms; ++i) {
4258 ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4259 GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4260 ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4261 }
4262
4263 ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4264
4265 delete [] name;
4266
4267 return res;
4268}
4269
4270void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4271{
4272 GL2Encoder *ctx = (GL2Encoder*)self;
4273 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4274 ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4275}
4276
4277void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4278{
4279 GL2Encoder *ctx = (GL2Encoder*)self;
4280 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4281 ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4282}
4283
4284void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4285{
4286 GL2Encoder *ctx = (GL2Encoder*)self;
4287 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004288 ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004289
4290 GLClientState* state = ctx->m_state;
4291 GLSharedGroupPtr shared = ctx->m_shared;
4292 GLenum target;
4293
4294 if (shared->setSamplerUniform(program, location, v0, &target)) {
4295 GLenum origActiveTexture = state->getActiveTextureUnit();
4296 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4297 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4298 }
4299 state->setActiveTextureUnit(origActiveTexture);
4300 }
4301}
4302
4303void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4304{
4305 GL2Encoder *ctx = (GL2Encoder*)self;
4306 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4307 ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4308}
4309
4310void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4311{
4312 GL2Encoder *ctx = (GL2Encoder*)self;
4313 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4314 ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4315
4316 GLClientState* state = ctx->m_state;
4317 GLSharedGroupPtr shared = ctx->m_shared;
4318 GLenum target;
4319
4320 if (shared->setSamplerUniform(program, location, v0, &target)) {
4321 GLenum origActiveTexture = state->getActiveTextureUnit();
4322 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4323 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4324 }
4325 state->setActiveTextureUnit(origActiveTexture);
4326 }
4327}
4328
4329void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4330{
4331 GL2Encoder *ctx = (GL2Encoder*)self;
4332 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4333 ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
4334}
4335
4336void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
4337{
4338 GL2Encoder *ctx = (GL2Encoder*)self;
4339 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4340 ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
4341}
4342
4343void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4344{
4345 GL2Encoder *ctx = (GL2Encoder*)self;
4346 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4347 ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
4348}
4349
4350void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
4351{
4352 GL2Encoder *ctx = (GL2Encoder*)self;
4353 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4354 ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
4355}
4356
4357void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4358{
4359 GL2Encoder *ctx = (GL2Encoder*)self;
4360 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4361 ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
4362}
4363
4364void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
4365{
4366 GL2Encoder *ctx = (GL2Encoder*)self;
4367 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4368 ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
4369}
4370
4371void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4372{
4373 GL2Encoder *ctx = (GL2Encoder*)self;
4374 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4375 ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
4376}
4377
4378void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
4379{
4380 GL2Encoder *ctx = (GL2Encoder*)self;
4381 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4382 ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
4383}
4384
4385void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4386{
4387 GL2Encoder *ctx = (GL2Encoder*)self;
4388 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4389 ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
4390}
4391
4392void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
4393{
4394 GL2Encoder *ctx = (GL2Encoder*)self;
4395 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4396 ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
4397}
4398
4399void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4400{
4401 GL2Encoder *ctx = (GL2Encoder*)self;
4402 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4403 ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
4404}
4405
4406void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
4407{
4408 GL2Encoder *ctx = (GL2Encoder*)self;
4409 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4410 ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
4411}
4412
4413void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4414{
4415 GL2Encoder *ctx = (GL2Encoder*)self;
4416 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4417 ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
4418}
4419
4420void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
4421{
4422 GL2Encoder *ctx = (GL2Encoder*)self;
4423 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4424 ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
4425}
4426
4427void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4428{
4429 GL2Encoder *ctx = (GL2Encoder*)self;
4430 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4431 ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
4432}
4433
4434void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
4435{
4436 GL2Encoder *ctx = (GL2Encoder*)self;
4437 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4438 ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
4439}
4440
4441void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4442{
4443 GL2Encoder *ctx = (GL2Encoder*)self;
4444 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4445 ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
4446}
4447
4448void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
4449{
4450 GL2Encoder *ctx = (GL2Encoder*)self;
4451 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4452 ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
4453}
4454
4455void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4456{
4457 GL2Encoder *ctx = (GL2Encoder*)self;
4458 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4459 ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
4460}
4461
4462void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4463{
4464 GL2Encoder *ctx = (GL2Encoder*)self;
4465 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4466 ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
4467}
4468
4469void GL2Encoder::s_glProgramUniformMatrix2x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4470{
4471 GL2Encoder *ctx = (GL2Encoder*)self;
4472 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4473 ctx->m_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
4474}
4475
4476void GL2Encoder::s_glProgramUniformMatrix2x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4477{
4478 GL2Encoder *ctx = (GL2Encoder*)self;
4479 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4480 ctx->m_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
4481}
4482
4483void GL2Encoder::s_glProgramUniformMatrix3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4484{
4485 GL2Encoder *ctx = (GL2Encoder*)self;
4486 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4487 ctx->m_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
4488}
4489
4490void GL2Encoder::s_glProgramUniformMatrix3x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4491{
4492 GL2Encoder *ctx = (GL2Encoder*)self;
4493 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4494 ctx->m_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
4495}
4496
4497void GL2Encoder::s_glProgramUniformMatrix3x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4498{
4499 GL2Encoder *ctx = (GL2Encoder*)self;
4500 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4501 ctx->m_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
4502}
4503
4504void GL2Encoder::s_glProgramUniformMatrix4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4505{
4506 GL2Encoder *ctx = (GL2Encoder*)self;
4507 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4508 ctx->m_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
4509}
4510
4511void GL2Encoder::s_glProgramUniformMatrix4x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4512{
4513 GL2Encoder *ctx = (GL2Encoder*)self;
4514 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4515 ctx->m_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
4516}
4517
4518void GL2Encoder::s_glProgramUniformMatrix4x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4519{
4520 GL2Encoder *ctx = (GL2Encoder*)self;
4521 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4522 ctx->m_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
4523}
4524
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004525void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) {
4526 GL2Encoder* ctx = (GL2Encoder*)self;
4527 ctx->m_glProgramParameteri_enc(self, program, pname, value);
4528}
4529
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004530void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
4531{
4532 GL2Encoder *ctx = (GL2Encoder*)self;
4533 GLClientState* state = ctx->m_state;
4534 GLSharedGroupPtr shared = ctx->m_shared;
4535
4536 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4537 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4538 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4539
4540 ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
4541 state->associateProgramWithPipeline(program, pipeline);
4542
4543 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4544 if (state->currentProgram()) {
4545 return;
4546 }
4547
4548 // Otherwise, update host texture 2D bindings.
4549 ctx->updateHostTexture2DBindingsFromProgramData(program);
4550}
4551
4552void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
4553{
4554 GL2Encoder *ctx = (GL2Encoder*)self;
4555 GLClientState* state = ctx->m_state;
4556
4557 ctx->m_glBindProgramPipeline_enc(self, pipeline);
4558
4559 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4560 if (!pipeline || state->currentProgram()) {
4561 return;
4562 }
4563
4564 GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
4565 for (; it != state->programPipelineEnd(); ++it) {
4566 if (it->second == pipeline) {
4567 ctx->updateHostTexture2DBindingsFromProgramData(it->first);
4568 }
4569 }
4570}
4571
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004572void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
4573 GL2Encoder *ctx = (GL2Encoder*)self;
4574 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4575 if (bufSize == 0) {
4576 if (length) *length = 0;
4577 return;
4578 }
4579
4580 // Avoid modifying |name| if |*length| < bufSize.
4581 GLint* intermediate = new GLint[bufSize];
4582 GLsizei* myLength = length ? length : new GLsizei;
4583 bool needFreeLength = length == NULL;
4584
4585 ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
4586 GLsizei writtenInts = *myLength;
4587 memcpy(params, intermediate, writtenInts * sizeof(GLint));
4588
4589 delete [] intermediate;
4590 if (needFreeLength)
4591 delete myLength;
4592}
4593
4594GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
4595 GL2Encoder *ctx = (GL2Encoder*)self;
4596 return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
4597}
4598
4599GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
4600 GL2Encoder *ctx = (GL2Encoder*)self;
4601 return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
4602}
4603
4604void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
4605 GL2Encoder *ctx = (GL2Encoder*)self;
4606 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4607 if (bufSize == 0) {
4608 if (length) *length = 0;
4609 return;
4610 }
4611
4612 // Avoid modifying |name| if |*length| < bufSize.
4613 char* intermediate = new char[bufSize];
4614 GLsizei* myLength = length ? length : new GLsizei;
4615 bool needFreeLength = length == NULL;
4616
4617 ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
4618 GLsizei writtenStrLen = *myLength;
4619 memcpy(name, intermediate, writtenStrLen + 1);
4620
4621 delete [] intermediate;
4622 if (needFreeLength)
4623 delete myLength;
4624}
4625
4626void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
4627 GL2Encoder *ctx = (GL2Encoder*)self;
4628 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4629 if (bufSize == 0) {
4630 if (length) *length = 0;
4631 return;
4632 }
4633
4634 // Avoid modifying |infoLog| if |*length| < bufSize.
4635 GLchar* intermediate = new GLchar[bufSize];
4636 GLsizei* myLength = length ? length : new GLsizei;
4637 bool needFreeLength = length == NULL;
4638
4639 ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
4640 GLsizei writtenStrLen = *myLength;
4641 memcpy(infoLog, intermediate, writtenStrLen + 1);
4642
4643 delete [] intermediate;
4644 if (needFreeLength)
4645 delete myLength;
4646}
4647
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004648void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
4649 GL2Encoder *ctx = (GL2Encoder*)self;
4650 GLClientState* state = ctx->m_state;
4651
Lingfeng Yang07289902017-01-27 12:26:19 -08004652 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004653 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4654
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004655 state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false);
4656 ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset);
4657}
4658
4659void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
4660 GL2Encoder *ctx = (GL2Encoder*)self;
4661 GLClientState* state = ctx->m_state;
4662
Lingfeng Yang07289902017-01-27 12:26:19 -08004663 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004664 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4665
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004666 state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true);
4667 ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset);
4668}
4669
4670void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004671 GL2Encoder *ctx = (GL2Encoder*)self;
4672 GLClientState* state = ctx->m_state;
4673
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004674 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4675
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004676 state->setVertexBindingDivisor(bindingindex, divisor);
4677 ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor);
4678}
4679
4680void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) {
4681 GL2Encoder *ctx = (GL2Encoder*)self;
4682 GLClientState* state = ctx->m_state;
Lingfeng Yang07289902017-01-27 12:26:19 -08004683 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004684 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004685
4686 state->setVertexAttribBinding(attribindex, bindingindex);
4687 ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex);
4688}
4689
4690void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
4691 GL2Encoder *ctx = (GL2Encoder*)self;
4692 GLClientState* state = ctx->m_state;
4693
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004694 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
4695
4696 GLint maxStride;
4697 ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
4698 SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE);
4699
4700 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4701
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004702 state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride);
4703 ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride);
4704}
4705
4706void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) {
4707 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004708 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004709
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004710 bool hasClientArrays = false;
4711 ctx->getVBOUsage(&hasClientArrays, NULL);
4712
4713 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
4714 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4715 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
4716
4717 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004718 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004719 // BufferData* buf = ctx->getBufferData(target);
4720 // if (buf) {
4721 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
4722 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004723 ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect);
4724 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004725 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
4726 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004727 ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize);
4728 }
4729}
4730
4731void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) {
4732 GL2Encoder *ctx = (GL2Encoder*)self;
4733
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004734 GLClientState* state = ctx->m_state;
4735
4736 bool hasClientArrays = false;
4737 ctx->getVBOUsage(&hasClientArrays, NULL);
4738
4739 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
4740 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4741 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
4742
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004743 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004744
4745 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004746 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004747 // BufferData* buf = ctx->getBufferData(target);
4748 // if (buf) {
4749 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
4750 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004751 ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect);
4752 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004753 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
4754 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004755 ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize);
4756 }
4757
4758}
4759
4760void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
4761 GL2Encoder *ctx = (GL2Encoder*)self;
4762 GLClientState* state = ctx->m_state;
4763
4764 SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
4765 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
4766 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
4767 SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
4768 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004769 GLint max_samples;
4770 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
4771 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004772
4773 state->setBoundTextureInternalFormat(target, internalformat);
4774 state->setBoundTextureDims(target, 0, width, height, 1);
4775 state->setBoundTextureImmutableFormat(target);
4776 state->setBoundTextureSamples(target, samples);
4777
4778 ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
4779}
4780