blob: 3c37a821d6381cc975009ba6160e42151cc9eef2 [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:
Lingfeng Yang324c8452017-02-17 09:56:26 -0800531 *ptr = ctx->m_deviceMajorVersion;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800532 break;
533 case GL_MINOR_VERSION:
Lingfeng Yang324c8452017-02-17 09:56:26 -0800534 *ptr = ctx->m_deviceMinorVersion;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800535 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;
Lingfeng Yang4e5446b2017-02-15 08:44:21 -0800943
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800944 int firstIndex = effectiveStride * first;
Lingfeng Yang4e5446b2017-02-15 08:44:21 -0800945 if (firstIndex && divisor && !primcount) {
946 // If firstIndex != 0 according to effectiveStride * first,
947 // it needs to be adjusted if a divisor has been specified,
948 // even if we are not in glDraw***Instanced.
949 firstIndex = 0;
950 }
keunyoungb85b2752013-03-08 12:28:03 -0800951
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800952 if (bufferObject == 0) {
953 unsigned int datalen = state.elementSize * count;
954 if (divisor && primcount) {
955 ALOGV("%s: divisor for att %d: %d, w/ stride %d (effective stride %d) size %d type 0x%x) datalen %u",
956 __FUNCTION__, i, divisor, state.stride, effectiveStride, state.elementSize, state.type, datalen);
957 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
958 datalen = state.elementSize * actual_count;
959 ALOGV("%s: actual datalen %u", __FUNCTION__, datalen);
960 }
961 if (state.elementSize == 0) {
Yahan Zhou3f2f1b42016-12-01 13:49:44 -0800962 // The vertex attribute array is uninitialized. Abandon it.
963 ALOGE("a vertex attribute array is uninitialized. Skipping corresponding vertex attribute.");
964 this->m_glDisableVertexAttribArray_enc(this, i);
965 continue;
966 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700967 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang000cf4c2017-01-25 08:09:02 -0800968
969 if (datalen && (!offset || !((unsigned char*)offset + firstIndex))) {
970 ALOGD("%s: bad offset / len!!!!!", __FUNCTION__);
971 continue;
972 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800973 if (state.isInt) {
974 this->glVertexAttribIPointerDataAEMU(this, i, state.size, state.type, stride, (unsigned char *)offset + firstIndex, datalen);
975 } else {
976 this->glVertexAttribPointerData(this, i, state.size, state.type, state.normalized, stride, (unsigned char *)offset + firstIndex, datalen);
977 }
keunyoungb85b2752013-03-08 12:28:03 -0800978 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800979 const BufferData* buf = m_shared->getBufferData(bufferObject);
Yahan Zhou5507c042016-06-01 17:24:28 -0700980 // The following expression actually means bufLen = stride*count;
981 // But the last element doesn't have to fill up the whole stride.
982 // So it becomes the current form.
Lingfeng Yang5fe99012017-01-18 09:17:09 -0800983 unsigned int bufLen = effectiveStride * (count ? (count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800984 if (divisor && primcount) {
985 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
Lingfeng Yang5fe99012017-01-18 09:17:09 -0800986 bufLen = effectiveStride * (actual_count ? (actual_count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800987 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700988 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800989 if (hasClientArrays) {
990 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800991 if (state.isInt) {
992 this->glVertexAttribIPointerOffsetAEMU(this, i, state.size, state.type, stride, offset + firstIndex);
993 } else {
994 this->glVertexAttribPointerOffset(this, i, state.size, state.type, state.normalized, stride, offset + firstIndex);
995 }
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800996 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700997 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800998 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=%p", buf);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -0800999 if (buf) {
1000 ALOGE("Out of bounds vertex attribute info: "
1001 "clientArray? %d attribute %d vbo %u allocedBufferSize %u bufferDataSpecified? %d wantedStart %u wantedEnd %u",
1002 hasClientArrays, i, bufferObject, buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen);
1003 }
1004 m_glDisableVertexAttribArray_enc(this, i);
Yahan Zhou5507c042016-06-01 17:24:28 -07001005 }
keunyoungb85b2752013-03-08 12:28:03 -08001006 }
1007 } else {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001008 if (hasClientArrays) {
1009 this->m_glDisableVertexAttribArray_enc(this, i);
1010 }
keunyoungb85b2752013-03-08 12:28:03 -08001011 }
1012 }
Lingfeng Yang398162b2016-05-26 14:18:33 -07001013
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001014 if (hasClientArrays && lastBoundVbo != m_state->currentArrayVbo()) {
Lingfeng Yang398162b2016-05-26 14:18:33 -07001015 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
1016 }
keunyoungb85b2752013-03-08 12:28:03 -08001017}
1018
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001019void GL2Encoder::flushDrawCall() {
Lingfeng Yang1ebb33c2017-01-19 08:04:48 -08001020 // This used to be every other draw call, but
1021 // now that we are using real GPU buffers on host,
1022 // set this to every 200 draw calls
1023 // (tuned on z840 linux NVIDIA Quadro K2200)
1024 if (m_drawCallFlushCount % 200 == 0) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001025 m_stream->flush();
1026 }
1027 m_drawCallFlushCount++;
1028}
1029
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001030static bool isValidDrawMode(GLenum mode)
1031{
1032 bool retval = false;
1033 switch (mode) {
1034 case GL_POINTS:
1035 case GL_LINE_STRIP:
1036 case GL_LINE_LOOP:
1037 case GL_LINES:
1038 case GL_TRIANGLE_STRIP:
1039 case GL_TRIANGLE_FAN:
1040 case GL_TRIANGLES:
1041 retval = true;
1042 }
1043 return retval;
1044}
1045
keunyoungb85b2752013-03-08 12:28:03 -08001046void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
1047{
1048 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001049 assert(ctx->m_state != NULL);
1050 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1051 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhoud6217a52016-02-10 16:10:46 -08001052
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001053 bool has_client_vertex_arrays = false;
1054 bool has_indirect_arrays = false;
1055 ctx->getVBOUsage(&has_client_vertex_arrays,
1056 &has_indirect_arrays);
1057
1058 if (has_client_vertex_arrays ||
1059 (!has_client_vertex_arrays &&
1060 !has_indirect_arrays)) {
1061 ctx->sendVertexAttributes(first, count, true);
1062 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
1063 } else {
1064 ctx->sendVertexAttributes(0, count, false);
1065 ctx->m_glDrawArrays_enc(ctx, mode, first, count);
1066 }
keunyoungb85b2752013-03-08 12:28:03 -08001067}
1068
1069
1070void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
1071{
1072
1073 GL2Encoder *ctx = (GL2Encoder *)self;
1074 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001075 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1076 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -07001077 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 -08001078 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001079
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001080 bool has_client_vertex_arrays = false;
keunyoungb85b2752013-03-08 12:28:03 -08001081 bool has_indirect_arrays = false;
1082 int nLocations = ctx->m_state->nLocations();
Yahan Zhou5507c042016-06-01 17:24:28 -07001083 GLintptr offset = 0;
keunyoungb85b2752013-03-08 12:28:03 -08001084
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001085 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
keunyoungb85b2752013-03-08 12:28:03 -08001086
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001087 if (!has_client_vertex_arrays && !has_indirect_arrays) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001088 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -07001089 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
1090 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001091 }
1092
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001093 BufferData* buf = NULL;
Yahan Zhou5507c042016-06-01 17:24:28 -07001094 int minIndex = 0, maxIndex = 0;
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001095
1096 // For validation/immediate index array purposes,
1097 // we need the min/max vertex index of the index array.
1098 // If the VBO != 0, this may not be the first time we have
1099 // used this particular index buffer. getBufferIndexRange
1100 // can more quickly get min/max vertex index by
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001101 // caching previous results.
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001102 if (ctx->m_state->currentIndexVbo() != 0) {
1103 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1104 offset = (GLintptr)indices;
1105 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
1106 ctx->getBufferIndexRange(buf,
1107 indices,
1108 type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001109 (size_t)count,
1110 (size_t)offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001111 &minIndex, &maxIndex);
1112 } else {
1113 // In this case, the |indices| field holds a real
1114 // array, so calculate the indices now. They will
1115 // also be needed to know how much data to
1116 // transfer to host.
1117 ctx->calcIndexRange(indices,
1118 type,
1119 count,
1120 &minIndex,
1121 &maxIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -07001122 }
1123
keunyoungb85b2752013-03-08 12:28:03 -08001124 bool adjustIndices = true;
1125 if (ctx->m_state->currentIndexVbo() != 0) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001126 if (!has_client_vertex_arrays) {
1127 ctx->sendVertexAttributes(0, maxIndex + 1, false);
keunyoungb85b2752013-03-08 12:28:03 -08001128 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -07001129 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001130 ctx->flushDrawCall();
keunyoungb85b2752013-03-08 12:28:03 -08001131 adjustIndices = false;
1132 } else {
1133 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1134 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001135 }
1136 }
1137 if (adjustIndices) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001138 void *adjustedIndices =
1139 ctx->recenterIndices(indices,
1140 type,
1141 count,
1142 minIndex);
keunyoungb85b2752013-03-08 12:28:03 -08001143
keunyoungb85b2752013-03-08 12:28:03 -08001144 if (has_indirect_arrays || 1) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001145 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
keunyoungb85b2752013-03-08 12:28:03 -08001146 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
1147 count * glSizeof(type));
1148 // XXX - OPTIMIZATION (see the other else branch) should be implemented
1149 if(!has_indirect_arrays) {
1150 //ALOGD("unoptimized drawelements !!!\n");
1151 }
1152 } else {
1153 // we are all direct arrays and immidate mode index array -
1154 // rebuild the arrays and the index array;
1155 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
1156 }
1157 }
1158}
1159
1160
1161GLint * GL2Encoder::getCompressedTextureFormats()
1162{
1163 if (m_compressedTextureFormats == NULL) {
1164 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
1165 &m_num_compressedTextureFormats);
1166 if (m_num_compressedTextureFormats > 0) {
1167 // get number of texture formats;
1168 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
1169 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
1170 }
1171 }
1172 return m_compressedTextureFormats;
1173}
1174
1175// Replace uses of samplerExternalOES with sampler2D, recording the names of
1176// modified shaders in data. Also remove
1177// #extension GL_OES_EGL_image_external : require
1178// statements.
1179//
1180// This implementation assumes the input has already been pre-processed. If not,
1181// a few cases will be mishandled:
1182//
1183// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
1184// the following code:
1185// #if 1
1186// uniform sampler2D mySampler;
1187// #else
1188// uniform samplerExternalOES mySampler;
1189// #endif
1190//
1191// 2. Comments that look like sampler declarations will be incorrectly modified
1192// and recorded:
1193// // samplerExternalOES hahaFooledYou
1194//
1195// 3. However, GLSL ES does not have a concatentation operator, so things like
1196// this (valid in C) are invalid and not a problem:
1197// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
1198// SAMPLER(ExternalOES, mySampler);
1199//
1200static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
1201{
1202 static const char STR_HASH_EXTENSION[] = "#extension";
1203 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
1204 static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
1205 static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
1206
1207 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
1208 char* c = str;
1209 while ((c = strstr(c, STR_HASH_EXTENSION))) {
1210 char* start = c;
1211 c += sizeof(STR_HASH_EXTENSION)-1;
1212 while (isspace(*c) && *c != '\0') {
1213 c++;
1214 }
1215 if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
1216 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
1217 {
1218 // #extension statements are terminated by end of line
1219 c = start;
1220 while (*c != '\0' && *c != '\r' && *c != '\n') {
1221 *c++ = ' ';
1222 }
1223 }
1224 }
1225
1226 // -- replace "samplerExternalOES" with "sampler2D" and record name
1227 c = str;
1228 while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
1229 // Make sure "samplerExternalOES" isn't a substring of a larger token
1230 if (c == str || !isspace(*(c-1))) {
1231 c++;
1232 continue;
1233 }
1234 char* sampler_start = c;
1235 c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
1236 if (!isspace(*c) && *c != '\0') {
1237 continue;
1238 }
1239
1240 // capture sampler name
1241 while (isspace(*c) && *c != '\0') {
1242 c++;
1243 }
1244 if (!isalpha(*c) && *c != '_') {
1245 // not an identifier
1246 return false;
1247 }
1248 char* name_start = c;
1249 do {
1250 c++;
1251 } while (isalnum(*c) || *c == '_');
1252 data->samplerExternalNames.push_back(
1253 android::String8(name_start, c - name_start));
1254
1255 // memcpy instead of strcpy since we don't want the NUL terminator
1256 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
1257 }
1258
1259 return true;
1260}
1261
Bo Hu73568cd2015-01-20 16:29:50 -08001262void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
1263{
1264 GL2Encoder* ctx = (GL2Encoder*)self;
1265 // Although it is not supported, need to set proper error code.
1266 SET_ERROR_IF(1, GL_INVALID_ENUM);
1267}
1268
David 'Digit' Turner02fdb692014-10-30 18:07:56 +01001269void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -08001270{
1271 GL2Encoder* ctx = (GL2Encoder*)self;
1272 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001273 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(shader), GL_INVALID_VALUE);
Tina Zhang7a84f652014-12-04 12:37:30 +08001274 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
1275 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001276
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001277 // Track original sources---they may be translated in the backend
1278 std::vector<std::string> orig_sources;
1279 for (int i = 0; i < count; i++) {
1280 orig_sources.push_back(std::string((const char*)(string[i])));
1281 }
1282 shaderData->sources = orig_sources;
1283
keunyoungb85b2752013-03-08 12:28:03 -08001284 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
1285 char *str = new char[len + 1];
1286 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
1287
1288 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
1289 // Perhaps we can borrow Mesa's pre-processor?
1290
1291 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001292 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001293 ctx->setError(GL_OUT_OF_MEMORY);
1294 return;
1295 }
keunyoungb85b2752013-03-08 12:28:03 -08001296 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001297 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001298}
1299
1300void GL2Encoder::s_glFinish(void *self)
1301{
1302 GL2Encoder *ctx = (GL2Encoder *)self;
1303 ctx->glFinishRoundTrip(self);
1304}
1305
1306void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1307{
1308 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -08001309 bool isProgram = ctx->m_shared->isProgram(program);
1310 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
1311 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
1312
keunyoungb85b2752013-03-08 12:28:03 -08001313 ctx->m_glLinkProgram_enc(self, program);
1314
1315 GLint linkStatus = 0;
1316 ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001317 if (!linkStatus) {
keunyoungb85b2752013-03-08 12:28:03 -08001318 return;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001319 }
keunyoungb85b2752013-03-08 12:28:03 -08001320
1321 //get number of active uniforms in the program
1322 GLint numUniforms=0;
1323 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
1324 ctx->m_shared->initProgramData(program,numUniforms);
1325
1326 //get the length of the longest uniform name
1327 GLint maxLength=0;
1328 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
1329
1330 GLint size;
1331 GLenum type;
1332 GLchar *name = new GLchar[maxLength+1];
1333 GLint location;
1334 //for each active uniform, get its size and starting location.
1335 for (GLint i=0 ; i<numUniforms ; ++i)
1336 {
1337 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1338 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1339 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1340 }
1341 ctx->m_shared->setupLocationShiftWAR(program);
1342
1343 delete[] name;
1344}
1345
1346void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1347{
1348 GL2Encoder *ctx = (GL2Encoder*)self;
1349 ctx->m_glDeleteProgram_enc(self, program);
1350
1351 ctx->m_shared->deleteProgramData(program);
1352}
1353
1354void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1355{
1356 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001357 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001358 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001359 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1360 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1361 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1362 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1363}
1364void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1365{
1366 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001367 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001368 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001369 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1370 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1371 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1372 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1373}
1374
1375GLuint GL2Encoder::s_glCreateProgram(void * self)
1376{
1377 GL2Encoder *ctx = (GL2Encoder*)self;
1378 GLuint program = ctx->m_glCreateProgram_enc(self);
1379 if (program!=0)
1380 ctx->m_shared->addProgramData(program);
1381 return program;
1382}
1383
1384GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1385{
1386 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001387 RET_AND_SET_ERROR_IF(!GLESv2Validation::shaderType(ctx, shaderType), GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001388 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1389 if (shader != 0) {
1390 if (!ctx->m_shared->addShaderData(shader)) {
1391 ctx->m_glDeleteShader_enc(self, shader);
1392 return 0;
1393 }
1394 }
1395 return shader;
1396}
1397
bohu56bf82f2014-10-17 15:35:48 -07001398void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1399 GLsizei* count, GLuint* shaders)
1400{
1401 GL2Encoder *ctx = (GL2Encoder*)self;
1402 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1403 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1404}
1405
1406void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1407 GLsizei* length, GLchar* source)
1408{
1409 GL2Encoder *ctx = (GL2Encoder*)self;
1410 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1411 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001412 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
1413 if (shaderData) {
1414 std::string returned;
1415 int curr_len = 0;
1416 for (int i = 0; i < shaderData->sources.size(); i++) {
1417 if (curr_len + shaderData->sources[i].size() < bufsize - 1) {
1418 returned += shaderData->sources[i];
1419 } else {
1420 returned += shaderData->sources[i].substr(0, bufsize - 1 - curr_len);
1421 break;
1422 }
1423 }
1424 memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize);
1425 }
bohu56bf82f2014-10-17 15:35:48 -07001426}
1427
1428void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1429 GLsizei* length, GLchar* infolog)
1430{
1431 GL2Encoder *ctx = (GL2Encoder*)self;
1432 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1433 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1434}
1435
1436void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1437 GLsizei* length, GLchar* infolog)
1438{
1439 GL2Encoder *ctx = (GL2Encoder*)self;
1440 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1441 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1442}
1443
keunyoungb85b2752013-03-08 12:28:03 -08001444void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1445{
1446 GL2Encoder *ctx = (GL2Encoder*)self;
1447 ctx->m_glDeleteShader_enc(self,shader);
1448 ctx->m_shared->unrefShaderData(shader);
1449}
1450
1451void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1452{
1453 GL2Encoder *ctx = (GL2Encoder*)self;
1454 ctx->m_glAttachShader_enc(self, program, shader);
1455 ctx->m_shared->attachShader(program, shader);
1456}
1457
1458void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1459{
1460 GL2Encoder *ctx = (GL2Encoder*)self;
1461 ctx->m_glDetachShader_enc(self, program, shader);
1462 ctx->m_shared->detachShader(program, shader);
1463}
1464
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001465int sArrIndexOfUniformExpr(const char* name, int* err) {
1466 *err = 0;
1467 int arrIndex = 0;
1468 int namelen = strlen(name);
1469 if (name[namelen-1] == ']') {
1470 const char *brace = strrchr(name,'[');
1471 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1472 *err = 1; return 0;
1473 }
1474 }
1475 return arrIndex;
1476}
1477
keunyoungb85b2752013-03-08 12:28:03 -08001478int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1479{
1480 if (!name) return -1;
1481
1482 GL2Encoder *ctx = (GL2Encoder*)self;
1483
1484 // if we need the uniform location WAR
1485 // parse array index from the end of the name string
1486 int arrIndex = 0;
1487 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1488 if (needLocationWAR) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001489 int err;
1490 arrIndex = sArrIndexOfUniformExpr(name, &err);
1491 if (err) return -1;
keunyoungb85b2752013-03-08 12:28:03 -08001492 }
1493
1494 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1495 if (hostLoc >= 0 && needLocationWAR) {
1496 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1497 }
1498 return hostLoc;
1499}
1500
1501bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1502{
1503 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1504 return false;
1505
1506 m_state->setActiveTextureUnit(texUnit);
1507
1508 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1509 if (newTarget != oldTarget) {
1510 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1511 m_state->disableTextureTarget(GL_TEXTURE_2D);
1512 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1513 } else {
1514 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1515 m_state->enableTextureTarget(GL_TEXTURE_2D);
1516 }
1517 m_glActiveTexture_enc(this, texUnit);
1518 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1519 m_state->getBoundTexture(newTarget));
1520 return true;
1521 }
1522
1523 return false;
1524}
1525
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001526void GL2Encoder::updateHostTexture2DBindingsFromProgramData(GLuint program) {
1527 GL2Encoder *ctx = this;
keunyoungb85b2752013-03-08 12:28:03 -08001528 GLClientState* state = ctx->m_state;
1529 GLSharedGroupPtr shared = ctx->m_shared;
1530
keunyoungb85b2752013-03-08 12:28:03 -08001531 GLenum origActiveTexture = state->getActiveTextureUnit();
1532 GLenum hostActiveTexture = origActiveTexture;
1533 GLint samplerIdx = -1;
1534 GLint samplerVal;
1535 GLenum samplerTarget;
1536 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1537 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1538 continue;
1539 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001540 samplerTarget))
keunyoungb85b2752013-03-08 12:28:03 -08001541 {
1542 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1543 }
1544 }
1545 state->setActiveTextureUnit(origActiveTexture);
1546 if (hostActiveTexture != origActiveTexture) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001547 ctx->m_glActiveTexture_enc(ctx, origActiveTexture);
keunyoungb85b2752013-03-08 12:28:03 -08001548 }
1549}
1550
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001551void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1552{
1553 GL2Encoder *ctx = (GL2Encoder*)self;
1554 GLSharedGroupPtr shared = ctx->m_shared;
1555
1556 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
1557 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1558
1559 ctx->m_glUseProgram_enc(self, program);
1560 ctx->m_state->setCurrentProgram(program);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001561 ctx->m_state->setCurrentShaderProgram(program);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001562
1563 ctx->updateHostTexture2DBindingsFromProgramData(program);
1564}
1565
keunyoungb85b2752013-03-08 12:28:03 -08001566void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
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_glUniform1f_enc(self, hostLoc, x);
1571}
1572
1573void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1574{
1575 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001576 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001577 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1578}
1579
1580void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1581{
1582 GL2Encoder *ctx = (GL2Encoder*)self;
1583 GLClientState* state = ctx->m_state;
1584 GLSharedGroupPtr shared = ctx->m_shared;
1585
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001586 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001587 ctx->m_glUniform1i_enc(self, hostLoc, x);
1588
1589 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001590 if (shared->setSamplerUniform(state->currentShaderProgram(), location, x, &target)) {
keunyoungb85b2752013-03-08 12:28:03 -08001591 GLenum origActiveTexture = state->getActiveTextureUnit();
1592 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1593 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1594 }
1595 state->setActiveTextureUnit(origActiveTexture);
1596 }
1597}
1598
1599void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
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_glUniform1iv_enc(self, hostLoc, count, v);
1604}
1605
1606void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
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_glUniform2f_enc(self, hostLoc, x, y);
1611}
1612
1613void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
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_glUniform2fv_enc(self, hostLoc, count, v);
1618}
1619
1620void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
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_glUniform2i_enc(self, hostLoc, x, y);
1625}
1626
1627void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
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_glUniform2iv_enc(self, hostLoc, count, v);
1632}
1633
1634void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
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_glUniform3f_enc(self, hostLoc, x, y, z);
1639}
1640
1641void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
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_glUniform3fv_enc(self, hostLoc, count, v);
1646}
1647
1648void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
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_glUniform3i_enc(self, hostLoc, x, y, z);
1653}
1654
1655void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
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_glUniform3iv_enc(self, hostLoc, count, v);
1660}
1661
1662void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
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_glUniform4f_enc(self, hostLoc, x, y, z, w);
1667}
1668
1669void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
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_glUniform4fv_enc(self, hostLoc, count, v);
1674}
1675
1676void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
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_glUniform4i_enc(self, hostLoc, x, y, z, w);
1681}
1682
1683void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
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_glUniform4iv_enc(self, hostLoc, count, v);
1688}
1689
1690void GL2Encoder::s_glUniformMatrix2fv(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_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1695}
1696
1697void GL2Encoder::s_glUniformMatrix3fv(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_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1702}
1703
1704void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1705{
1706 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001707 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001708 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1709}
1710
1711void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1712{
1713 GL2Encoder* ctx = (GL2Encoder*)self;
1714 GLClientState* state = ctx->m_state;
1715 GLenum err;
1716
1717 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1718
1719 ctx->m_glActiveTexture_enc(ctx, texture);
1720}
1721
1722void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1723{
1724 GL2Encoder* ctx = (GL2Encoder*)self;
1725 GLClientState* state = ctx->m_state;
1726 GLenum err;
1727 GLboolean firstUse;
1728
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001729 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -08001730 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1731
1732 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1733 ctx->m_glBindTexture_enc(ctx, target, texture);
1734 return;
1735 }
1736
1737 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1738
1739 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1740 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1741 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1742 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1743 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1744 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1745 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1746 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1747
1748 if (target != priorityTarget) {
1749 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1750 state->getBoundTexture(GL_TEXTURE_2D));
1751 }
1752 }
1753
1754 if (target == priorityTarget) {
1755 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1756 }
1757}
1758
1759void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1760{
1761 GL2Encoder* ctx = (GL2Encoder*)self;
1762 GLClientState* state = ctx->m_state;
1763
1764 state->deleteTextures(n, textures);
1765 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1766}
1767
1768void GL2Encoder::s_glGetTexParameterfv(void* self,
1769 GLenum target, GLenum pname, GLfloat* params)
1770{
1771 GL2Encoder* ctx = (GL2Encoder*)self;
1772 const GLClientState* state = ctx->m_state;
1773
1774 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1775 ctx->override2DTextureTarget(target);
1776 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001777 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001778 } else {
1779 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1780 }
1781}
1782
1783void GL2Encoder::s_glGetTexParameteriv(void* self,
1784 GLenum target, GLenum pname, GLint* params)
1785{
1786 GL2Encoder* ctx = (GL2Encoder*)self;
1787 const GLClientState* state = ctx->m_state;
1788
1789 switch (pname) {
1790 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1791 *params = 1;
1792 break;
1793
1794 default:
1795 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1796 ctx->override2DTextureTarget(target);
1797 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001798 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001799 } else {
1800 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1801 }
1802 break;
1803 }
1804}
1805
1806static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1807{
1808 switch (pname) {
1809 case GL_TEXTURE_MIN_FILTER:
1810 case GL_TEXTURE_MAG_FILTER:
1811 return param == GL_NEAREST || param == GL_LINEAR;
1812
1813 case GL_TEXTURE_WRAP_S:
1814 case GL_TEXTURE_WRAP_T:
1815 return param == GL_CLAMP_TO_EDGE;
1816
1817 default:
1818 return true;
1819 }
1820}
1821
1822void GL2Encoder::s_glTexParameterf(void* self,
1823 GLenum target, GLenum pname, GLfloat param)
1824{
1825 GL2Encoder* ctx = (GL2Encoder*)self;
1826 const GLClientState* state = ctx->m_state;
1827
1828 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1829 !isValidTextureExternalParam(pname, (GLenum)param)),
1830 GL_INVALID_ENUM);
1831
1832 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1833 ctx->override2DTextureTarget(target);
1834 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001835 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001836 } else {
1837 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1838 }
1839}
1840
1841void GL2Encoder::s_glTexParameterfv(void* self,
1842 GLenum target, GLenum pname, const GLfloat* params)
1843{
1844 GL2Encoder* ctx = (GL2Encoder*)self;
1845 const GLClientState* state = ctx->m_state;
1846
1847 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1848 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1849 GL_INVALID_ENUM);
1850
1851 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1852 ctx->override2DTextureTarget(target);
1853 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001854 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001855 } else {
1856 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1857 }
1858}
1859
1860void GL2Encoder::s_glTexParameteri(void* self,
1861 GLenum target, GLenum pname, GLint param)
1862{
1863 GL2Encoder* ctx = (GL2Encoder*)self;
1864 const GLClientState* state = ctx->m_state;
1865
1866 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1867 !isValidTextureExternalParam(pname, (GLenum)param)),
1868 GL_INVALID_ENUM);
1869
1870 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1871 ctx->override2DTextureTarget(target);
1872 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001873 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001874 } else {
1875 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
1876 }
1877}
1878
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001879static int ilog2(uint32_t x) {
1880 int p = 0;
1881 while ((1 << p) < x)
1882 p++;
1883 return p;
1884}
1885
bohu26a92982014-11-25 16:50:37 -08001886void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
1887 GLint internalformat, GLsizei width, GLsizei height, GLint border,
1888 GLenum format, GLenum type, const GLvoid* pixels)
1889{
1890 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07001891 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001892
1893 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
1894 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
1895 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
1896 // If unpack buffer is nonzero, verify unmapped state.
1897 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
1898
1899 GLint max_texture_size;
1900 GLint max_cube_map_texture_size;
1901 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
1902 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
1903 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
1904 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
1905 SET_ERROR_IF((target == GL_TEXTURE_CUBE_MAP) &&
1906 (level > ilog2(max_cube_map_texture_size)), GL_INVALID_VALUE);
1907 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
1908 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
1909 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
1910 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && width > max_cube_map_texture_size, GL_INVALID_VALUE);
1911 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && height > max_cube_map_texture_size, GL_INVALID_VALUE);
1912 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
1913 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
1914 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1915 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1916 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 0) >
1917 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
1918 GL_INVALID_OPERATION);
1919 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1920 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1921 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
1922 glSizeof(type)),
1923 GL_INVALID_OPERATION);
1924 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1925 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1926 ((uintptr_t)pixels % glSizeof(type)),
1927 GL_INVALID_OPERATION);
1928 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
1929
1930 GLenum stateTarget = target;
1931 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1932 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1933 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
1934 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1935 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1936 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
1937 stateTarget = GL_TEXTURE_CUBE_MAP;
1938
1939 state->setBoundTextureInternalFormat(stateTarget, internalformat);
1940 state->setBoundTextureFormat(stateTarget, format);
1941 state->setBoundTextureType(stateTarget, type);
1942 state->setBoundTextureDims(stateTarget, level, width, height, 1);
1943
bohu26a92982014-11-25 16:50:37 -08001944 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1945 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001946 }
Lingfeng Yang69066602016-04-12 09:29:11 -07001947
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001948 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
1949 ctx->glTexImage2DOffsetAEMU(
1950 ctx, target, level, internalformat,
1951 width, height, border,
1952 format, type, (uintptr_t)pixels);
bohu26a92982014-11-25 16:50:37 -08001953 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001954 ctx->m_glTexImage2D_enc(
1955 ctx, target, level, internalformat,
1956 width, height, border,
1957 format, type, pixels);
1958 }
1959
1960 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1961 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08001962 }
1963}
1964
Yahan Zhou2a208292016-06-22 15:36:04 -07001965void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
1966 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
1967 GLenum type, const GLvoid* pixels)
1968{
1969 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001970 GLClientState* state = ctx->m_state;
1971
1972 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
1973 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
1974 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
1975 // If unpack buffer is nonzero, verify unmapped state.
1976 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
1977
1978 GLint max_texture_size;
1979 GLint max_cube_map_texture_size;
1980 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
1981 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
1982 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
1983 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
1984 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) &&
1985 level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
1986 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
1987 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
1988
1989 GLuint tex = state->getBoundTexture(target);
1990 GLsizei neededWidth = xoffset + width;
1991 GLsizei neededHeight = yoffset + height;
1992 GLsizei neededDepth = 1;
1993
1994 if (tex && !state->queryTexEGLImageBacked(tex)) {
1995 SET_ERROR_IF(
1996 (neededWidth > state->queryTexWidth(level, tex) ||
1997 neededHeight > state->queryTexHeight(level, tex) ||
1998 neededDepth > state->queryTexDepth(level, tex)),
1999 GL_INVALID_VALUE);
2000 }
2001
2002 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2003 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2004 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2005 (state->pboNeededDataSize(width, height, 1, format, type, 0) >
2006 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2007 GL_INVALID_OPERATION);
2008 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2009 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2010 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2011 glSizeof(type)),
2012 GL_INVALID_OPERATION);
2013 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !pixels, GL_INVALID_OPERATION);
Yahan Zhou2a208292016-06-22 15:36:04 -07002014
2015 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2016 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002017 }
2018
2019 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2020 ctx->glTexSubImage2DOffsetAEMU(
2021 ctx, target, level,
2022 xoffset, yoffset, width, height,
2023 format, type, (uintptr_t)pixels);
Yahan Zhou2a208292016-06-22 15:36:04 -07002024 } else {
2025 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
2026 height, format, type, pixels);
2027 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002028
2029 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2030 ctx->restore2DTextureTarget(target);
2031 }
Yahan Zhou2a208292016-06-22 15:36:04 -07002032}
bohu26a92982014-11-25 16:50:37 -08002033
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002034void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
2035 GLenum internalformat, GLint x, GLint y,
2036 GLsizei width, GLsizei height, GLint border)
2037{
2038 GL2Encoder* ctx = (GL2Encoder*)self;
2039 GLClientState* state = ctx->m_state;
2040
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002041 SET_ERROR_IF(ctx->glCheckFramebufferStatus(ctx, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
2042 GL_INVALID_FRAMEBUFFER_OPERATION);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002043 // This is needed to work around underlying OpenGL drivers
2044 // (such as those feeding some some AMD GPUs) that expect
2045 // positive components of cube maps to be defined _before_
2046 // the negative components (otherwise a segfault occurs).
2047 GLenum extraTarget =
2048 state->copyTexImageLuminanceCubeMapAMDWorkaround
2049 (target, level, internalformat);
2050
2051 if (extraTarget) {
2052 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
2053 x, y, width, height, border);
2054 }
2055
2056 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
2057 x, y, width, height, border);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002058
2059 state->setBoundTextureInternalFormat(target, internalformat);
2060 state->setBoundTextureDims(target, level, width, height, 1);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002061}
2062
keunyoungb85b2752013-03-08 12:28:03 -08002063void GL2Encoder::s_glTexParameteriv(void* self,
2064 GLenum target, GLenum pname, const GLint* params)
2065{
2066 GL2Encoder* ctx = (GL2Encoder*)self;
2067 const GLClientState* state = ctx->m_state;
2068
2069 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2070 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2071 GL_INVALID_ENUM);
2072
2073 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2074 ctx->override2DTextureTarget(target);
2075 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002076 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002077 } else {
2078 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
2079 }
2080}
2081
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002082bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
2083 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
2084 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2085}
2086
keunyoungb85b2752013-03-08 12:28:03 -08002087void GL2Encoder::override2DTextureTarget(GLenum target)
2088{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002089 if (texture2DNeedsOverride(target)) {
2090 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2091 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08002092 }
2093}
2094
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002095void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08002096{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002097 if (texture2DNeedsOverride(target)) {
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002098 GLuint priorityEnabledBoundTexture =
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002099 m_state->getBoundTexture(
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002100 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D));
2101 GLuint texture2DBoundTexture =
2102 m_state->getBoundTexture(GL_TEXTURE_2D);
2103 if (!priorityEnabledBoundTexture) {
2104 m_glBindTexture_enc(this, GL_TEXTURE_2D, texture2DBoundTexture);
2105 } else {
2106 m_glBindTexture_enc(this, GL_TEXTURE_2D, priorityEnabledBoundTexture);
2107 }
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002108 }
keunyoungb85b2752013-03-08 12:28:03 -08002109}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002110
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002111void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2112 m_state->setBoundEGLImage(target, eglImage);
2113}
2114
2115
2116GLuint GL2Encoder::boundBuffer(GLenum target) const {
2117 return m_state->getBuffer(target);
2118}
2119
2120BufferData* GL2Encoder::getBufferData(GLenum target) const {
2121 GLuint bufferId = m_state->getBuffer(target);
2122 if (!bufferId) return NULL;
2123 return m_shared->getBufferData(bufferId);
2124}
2125
2126BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2127 if (!bufferId) return NULL;
2128 return m_shared->getBufferData(bufferId);
2129}
2130
2131bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2132 return m_shared->getBufferData(buffer)->m_mapped;
2133}
2134
2135bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2136 BufferData* buf = getBufferData(target);
2137 if (!buf) return false;
2138 return buf->m_mapped;
2139}
2140
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002141void GL2Encoder::s_glGenRenderbuffers(void* self,
2142 GLsizei n, GLuint* renderbuffers) {
2143 GL2Encoder* ctx = (GL2Encoder*)self;
2144 GLClientState* state = ctx->m_state;
2145
2146 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2147
2148 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2149 state->addRenderbuffers(n, renderbuffers);
2150}
2151
2152void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2153 GLsizei n, const GLuint* renderbuffers) {
2154 GL2Encoder* ctx = (GL2Encoder*)self;
2155 GLClientState* state = ctx->m_state;
2156
2157 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2158
2159 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002160
2161 // Nope, lets just leak those for now.
2162 // The spec has an *amazingly* convoluted set of conditions for when
2163 // render buffers are actually deleted:
2164 // 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.
2165 //
2166 // 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***
2167 //
2168 // So, just detach this one from the bound FBO, and ignore the rest.
2169 for (int i = 0; i < n; i++) {
2170 state->detachRbo(renderbuffers[i]);
2171 }
2172 // state->removeRenderbuffers(n, renderbuffers);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002173}
2174
2175void GL2Encoder::s_glBindRenderbuffer(void* self,
2176 GLenum target, GLuint renderbuffer) {
2177 GL2Encoder* ctx = (GL2Encoder*)self;
2178 GLClientState* state = ctx->m_state;
2179
2180 SET_ERROR_IF((target != GL_RENDERBUFFER),
2181 GL_INVALID_ENUM);
2182
2183 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2184 state->bindRenderbuffer(target, renderbuffer);
2185}
2186
Lingfeng Yang69066602016-04-12 09:29:11 -07002187void GL2Encoder::s_glRenderbufferStorage(void* self,
2188 GLenum target, GLenum internalformat,
2189 GLsizei width, GLsizei height) {
2190 GL2Encoder* ctx = (GL2Encoder*) self;
2191 GLClientState* state = ctx->m_state;
2192
2193 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002194 SET_ERROR_IF(
2195 !GLESv2Validation::rboFormat(ctx, internalformat),
2196 GL_INVALID_ENUM);
Lingfeng Yang69066602016-04-12 09:29:11 -07002197
2198 state->setBoundRenderbufferFormat(internalformat);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002199 state->setBoundRenderbufferSamples(0);
2200
Lingfeng Yang69066602016-04-12 09:29:11 -07002201 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
2202 width, height);
2203}
2204
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002205void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
2206 GLenum target, GLenum attachment,
2207 GLenum renderbuffertarget, GLuint renderbuffer) {
2208 GL2Encoder* ctx = (GL2Encoder*)self;
2209 GLClientState* state = ctx->m_state;
2210
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002211 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2212 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2213 state->attachRbo(target, attachment, renderbuffer);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002214
2215 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
2216}
2217
2218void GL2Encoder::s_glGenFramebuffers(void* self,
2219 GLsizei n, GLuint* framebuffers) {
2220 GL2Encoder* ctx = (GL2Encoder*)self;
2221 GLClientState* state = ctx->m_state;
2222
2223 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2224
2225 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2226 state->addFramebuffers(n, framebuffers);
2227}
2228
2229void GL2Encoder::s_glDeleteFramebuffers(void* self,
2230 GLsizei n, const GLuint* framebuffers) {
2231 GL2Encoder* ctx = (GL2Encoder*)self;
2232 GLClientState* state = ctx->m_state;
2233
2234 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2235
2236 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2237 state->removeFramebuffers(n, framebuffers);
2238}
2239
2240void GL2Encoder::s_glBindFramebuffer(void* self,
2241 GLenum target, GLuint framebuffer) {
2242 GL2Encoder* ctx = (GL2Encoder*)self;
2243 GLClientState* state = ctx->m_state;
2244
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002245 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002246
2247 state->bindFramebuffer(target, framebuffer);
2248
2249 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
2250}
2251
2252void GL2Encoder::s_glFramebufferTexture2D(void* self,
2253 GLenum target, GLenum attachment,
2254 GLenum textarget, GLuint texture, GLint level) {
2255 GL2Encoder* ctx = (GL2Encoder*)self;
2256 GLClientState* state = ctx->m_state;
2257
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002258 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2259 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2260 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002261
2262 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
2263}
2264
2265void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2266 GLenum target, GLenum attachment,
2267 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2268 GL2Encoder* ctx = (GL2Encoder*)self;
2269 GLClientState* state = ctx->m_state;
2270
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002271 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002272
2273 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2274}
2275
2276void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2277 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2278 GL2Encoder* ctx = (GL2Encoder*)self;
2279 const GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002280 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2281 SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2282 pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE &&
2283 !state->attachmentHasObject(target, attachment),
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002284 GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002285 SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL ||
2286 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE ||
2287 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) &&
2288 (!state->attachmentHasObject(target, attachment) ||
2289 state->getBoundFramebufferAttachmentType(target, attachment) !=
2290 FBO_ATTACHMENT_TEXTURE),
2291 !state->attachmentHasObject(target, attachment) ?
2292 GL_INVALID_OPERATION : GL_INVALID_ENUM);
2293 SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2294 pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2295 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
2296 state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
2297 GL_INVALID_OPERATION);
2298 SET_ERROR_IF(state->boundFramebuffer(target) &&
2299 (attachment == GL_BACK ||
2300 attachment == GL_FRONT),
2301 GL_INVALID_OPERATION);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002302 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
2303}
Lingfeng Yang69066602016-04-12 09:29:11 -07002304
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002305bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state,
Lingfeng Yang69066602016-04-12 09:29:11 -07002306 GLenum attachment) const {
2307 FboFormatInfo fbo_format_info;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002308 state->getBoundFramebufferFormat(target, attachment, &fbo_format_info);
Lingfeng Yang69066602016-04-12 09:29:11 -07002309
2310 bool res;
2311 switch (fbo_format_info.type) {
2312 case FBO_ATTACHMENT_RENDERBUFFER:
2313 switch (fbo_format_info.rb_format) {
2314 case GL_R16F:
2315 case GL_RG16F:
Lingfeng Yang69066602016-04-12 09:29:11 -07002316 case GL_RGBA16F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002317 case GL_R32F:
2318 case GL_RG32F:
2319 case GL_RGBA32F:
2320 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002321 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002322 break;
2323 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002324 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang69066602016-04-12 09:29:11 -07002325 break;
2326 case GL_STENCIL_INDEX8:
2327 if (attachment == GL_STENCIL_ATTACHMENT) {
2328 res = true;
2329 } else {
2330 res = false;
2331 }
2332 break;
2333 default:
2334 res = true;
2335 }
2336 break;
2337 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002338 switch (fbo_format_info.tex_internalformat) {
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002339 case GL_R16F:
2340 case GL_RG16F:
2341 case GL_RGBA16F:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002342 case GL_R32F:
2343 case GL_RG32F:
2344 case GL_RGBA32F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002345 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002346 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002347 break;
2348 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002349 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002350 break;
2351 case GL_RED:
2352 case GL_RG:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002353 case GL_SRGB8:
2354 case GL_RGB32UI:
2355 case GL_RGB16UI:
2356 case GL_RGB8UI:
2357 case GL_RGB32I:
2358 case GL_RGB16I:
2359 case GL_RGB8I:
2360 case GL_R8_SNORM:
2361 case GL_RG8_SNORM:
2362 case GL_RGB8_SNORM:
2363 case GL_RGBA8_SNORM:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002364 res = false;
2365 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07002366 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002367 case GL_RGB:
2368 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07002369 switch (fbo_format_info.tex_type) {
2370 case GL_FLOAT:
2371 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002372 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002373 case GL_UNSIGNED_INT_2_10_10_10_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07002374 res = false;
2375 break;
2376 default:
2377 res = true;
2378 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002379 break;
2380 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07002381 res = true;
2382 }
2383 break;
2384 case FBO_ATTACHMENT_NONE:
2385 res = true;
2386 break;
2387 default:
2388 res = true;
2389 }
2390 return res;
2391}
2392
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002393bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const {
2394 bool res = true;
2395
2396 for (int i = 0; i < state->getMaxColorAttachments(); i++) {
2397 res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i));
2398 }
2399
2400 res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT);
2401 res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT);
2402
2403 return res;
2404}
2405
Lingfeng Yang69066602016-04-12 09:29:11 -07002406GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
2407 GL2Encoder* ctx = (GL2Encoder*)self;
2408 GLClientState* state = ctx->m_state;
2409
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002410 bool fboCompleteByCodec =
2411 ctx->checkFramebufferCompleteness(target, state);
2412
2413 if (!fboCompleteByCodec) {
2414 state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
Lingfeng Yang69066602016-04-12 09:29:11 -07002415 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2416 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002417 // double check with underlying opengl to avoid craziness.
Lingfeng Yang69066602016-04-12 09:29:11 -07002418 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002419 state->setCheckFramebufferStatus(target, host_checkstatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002420 if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE;
Lingfeng Yang69066602016-04-12 09:29:11 -07002421 return host_checkstatus;
2422 }
2423}
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002424
2425void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2426 GL2Encoder* ctx = (GL2Encoder*)self;
2427 GLClientState* state = ctx->m_state;
2428 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2429
2430 ctx->m_glGenVertexArrays_enc(self, n, arrays);
2431 for (int i = 0; i < n; i++) {
2432 ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2433 }
2434 state->addVertexArrayObjects(n, arrays);
2435}
2436
2437void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2438 GL2Encoder* ctx = (GL2Encoder*)self;
2439 GLClientState* state = ctx->m_state;
2440 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2441
2442 ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2443 for (int i = 0; i < n; i++) {
2444 ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2445 }
2446 state->removeVertexArrayObjects(n, arrays);
2447}
2448
2449void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2450 ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2451 GL2Encoder* ctx = (GL2Encoder*)self;
2452 GLClientState* state = ctx->m_state;
2453 SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2454 ctx->m_glBindVertexArray_enc(self, array);
2455 state->setVertexArrayObject(array);
2456}
2457
2458void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2459 GL2Encoder* ctx = (GL2Encoder*)self;
2460 GLClientState* state = ctx->m_state;
2461
2462 // begin validation (lots)
2463
2464 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2465
2466 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2467
2468 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2469
2470 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2471 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2472
2473 GLsizeiptr bufferDataSize = buf->m_size;
2474
2475 RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2476 RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2477 RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2478 RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2479
2480 RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2481 RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2482 RET_AND_SET_ERROR_IF(
2483 (access & GL_MAP_READ_BIT) &&
2484 ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2485 (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2486 (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2487 (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2488
2489 // end validation; actually do stuff now
2490
2491 buf->m_mapped = true;
2492 buf->m_mappedAccess = access;
2493 buf->m_mappedOffset = offset;
2494 buf->m_mappedLength = length;
2495
2496 char* todo = (char*)buf->m_fixedBuffer.ptr() + offset;
2497 ctx->glMapBufferRangeAEMU(
2498 ctx, target,
2499 offset, length,
2500 access,
2501 todo);
2502
2503 return todo;
2504}
2505
2506GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
2507 GL2Encoder* ctx = (GL2Encoder*)self;
2508 GLClientState* state = ctx->m_state;
2509
2510 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
2511
2512 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2513
2514 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
2515
2516 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2517 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
2518 RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
2519
Lingfeng Yang423129e2017-01-18 09:23:12 -08002520 if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
2521 // invalide index range cache here
2522 if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) {
2523 buf->m_indexRangeCache.invalidateRange(0, buf->m_size);
2524 } else {
2525 buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength);
2526 }
2527 }
2528
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002529 GLboolean host_res = GL_TRUE;
2530
2531 ctx->glUnmapBufferAEMU(
2532 ctx, target,
2533 buf->m_mappedOffset,
2534 buf->m_mappedLength,
2535 buf->m_mappedAccess,
2536 (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
2537 &host_res);
2538
2539 buf->m_mapped = false;
2540 buf->m_mappedAccess = 0;
2541 buf->m_mappedOffset = 0;
2542 buf->m_mappedLength = 0;
2543
2544 return host_res;
2545}
2546
2547void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
2548 GL2Encoder* ctx = (GL2Encoder*)self;
2549 GLClientState* state = ctx->m_state;
2550
2551 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2552
2553 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2554 SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
2555
2556 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2557 SET_ERROR_IF(!buf, GL_INVALID_VALUE);
2558 SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
2559 SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
2560
2561 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
2562 SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
2563 SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
2564
2565 GLintptr totalOffset = buf->m_mappedOffset + offset;
Lingfeng Yang423129e2017-01-18 09:23:12 -08002566
2567 buf->m_indexRangeCache.invalidateRange(totalOffset, length);
2568
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002569 ctx->glFlushMappedBufferRangeAEMU(
2570 ctx, target,
2571 totalOffset,
2572 length,
2573 buf->m_mappedAccess,
2574 (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
2575}
2576
2577void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
2578 GL2Encoder* ctx = (GL2Encoder*)self;
2579 GLClientState* state = ctx->m_state;
2580
2581 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2582 // Filter compressed formats support.
2583 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
2584 // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
2585 GLint max_texture_size;
2586 GLint max_cube_map_texture_size;
2587 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2588 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2589 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2590 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2591 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2592 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2593 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2594 SET_ERROR_IF(border, GL_INVALID_VALUE);
2595 // If unpack buffer is nonzero, verify unmapped state.
2596 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2597 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2598 // If unpack buffer is nonzero, verify buffer data fits.
2599 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2600 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2601 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2602 GL_INVALID_OPERATION);
2603 // TODO: Fix:
2604 // If |imageSize| is inconsistent with compressed dimensions.
2605 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
2606
2607 GLenum stateTarget = target;
2608 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2609 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2610 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2611 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2612 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2613 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2614 stateTarget = GL_TEXTURE_CUBE_MAP;
2615 state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
2616 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2617
2618 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2619 ctx->glCompressedTexImage2DOffsetAEMU(
2620 ctx, target, level, internalformat,
2621 width, height, border,
2622 imageSize, (uintptr_t)data);
2623 } else {
2624 ctx->m_glCompressedTexImage2D_enc(
2625 ctx, target, level, internalformat,
2626 width, height, border,
2627 imageSize, data);
2628 }
2629}
2630
2631void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
2632 GL2Encoder* ctx = (GL2Encoder*)self;
2633 GLClientState* state = ctx->m_state;
2634
2635 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2636 // If unpack buffer is nonzero, verify unmapped state.
2637 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2638 GLint max_texture_size;
2639 GLint max_cube_map_texture_size;
2640 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2641 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2642 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2643 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2644 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2645 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2646 // If unpack buffer is nonzero, verify buffer data fits.
2647 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2648 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2649 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2650 GL_INVALID_OPERATION);
2651 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2652
2653 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2654 ctx->glCompressedTexSubImage2DOffsetAEMU(
2655 ctx, target, level,
2656 xoffset, yoffset,
2657 width, height, format,
2658 imageSize, (uintptr_t)data);
2659 } else {
2660 ctx->m_glCompressedTexSubImage2D_enc(
2661 ctx, target, level,
2662 xoffset, yoffset,
2663 width, height, format,
2664 imageSize, data);
2665 }
2666}
2667
2668void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
2669 GL2Encoder* ctx = (GL2Encoder*)self;
2670 GLClientState* state = ctx->m_state;
2671
2672 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2673
2674 // Only works with certain targets
2675 SET_ERROR_IF(
2676 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2677 target == GL_SHADER_STORAGE_BUFFER ||
2678 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2679 target == GL_UNIFORM_BUFFER),
2680 GL_INVALID_ENUM);
2681
2682 // Can't exceed range
2683 SET_ERROR_IF(index < 0 ||
2684 index >= state->getMaxIndexedBufferBindings(target),
2685 GL_INVALID_VALUE);
2686 SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
2687 SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
2688 target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
2689 (size % 4 || offset % 4),
2690 GL_INVALID_VALUE);
2691
2692 GLint ssbo_offset_align, ubo_offset_align;
2693 ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
2694 ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
2695 SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
2696 offset % ssbo_offset_align,
2697 GL_INVALID_VALUE);
2698 SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
2699 offset % ubo_offset_align,
2700 GL_INVALID_VALUE);
2701
2702 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002703 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002704 state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0);
2705 ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size);
2706}
2707
2708void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
2709 GL2Encoder* ctx = (GL2Encoder*)self;
2710 GLClientState* state = ctx->m_state;
2711
2712 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2713
2714 // Only works with certain targets
2715 SET_ERROR_IF(
2716 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2717 target == GL_SHADER_STORAGE_BUFFER ||
2718 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2719 target == GL_UNIFORM_BUFFER),
2720 GL_INVALID_ENUM);
2721 // Can't exceed range
2722 SET_ERROR_IF(index < 0 ||
2723 index >= state->getMaxIndexedBufferBindings(target),
2724 GL_INVALID_VALUE);
2725
2726 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002727 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002728 BufferData* buf = ctx->getBufferDataById(buffer);
2729 state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0);
2730 ctx->m_glBindBufferBase_enc(self, target, index, buffer);
2731}
2732
2733void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
2734 GL2Encoder* ctx = (GL2Encoder*)self;
2735 GLClientState* state = ctx->m_state;
2736
2737 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
2738 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
2739 SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
2740 readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
2741 readtarget == GL_DRAW_INDIRECT_BUFFER ||
2742 readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2743 SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
2744 writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
2745 writetarget == GL_DRAW_INDIRECT_BUFFER ||
2746 writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2747 SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
2748 SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
2749 SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
2750 SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
2751 SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
2752 SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
2753 SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
2754 SET_ERROR_IF(
2755 ctx->getBufferData(readtarget) &&
2756 (readoffset + size > ctx->getBufferData(readtarget)->m_size),
2757 GL_INVALID_VALUE);
2758 SET_ERROR_IF(
2759 ctx->getBufferData(writetarget) &&
2760 (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
2761 GL_INVALID_VALUE);
2762 SET_ERROR_IF(readtarget == writetarget &&
2763 !((writeoffset >= readoffset + size) ||
2764 (readoffset >= writeoffset + size)),
2765 GL_INVALID_VALUE);
2766
2767 ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
2768}
2769
2770void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
2771 GL2Encoder* ctx = (GL2Encoder*)self;
2772
2773 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2774 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002775 target != GL_ARRAY_BUFFER &&
2776 target != GL_ELEMENT_ARRAY_BUFFER &&
2777 target != GL_COPY_READ_BUFFER &&
2778 target != GL_COPY_WRITE_BUFFER &&
2779 target != GL_PIXEL_PACK_BUFFER &&
2780 target != GL_PIXEL_UNPACK_BUFFER &&
2781 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
2782 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002783 GL_INVALID_ENUM);
2784 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
2785 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002786 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
2787 pname != GL_BUFFER_MAPPED &&
2788 pname != GL_BUFFER_SIZE &&
2789 pname != GL_BUFFER_USAGE &&
2790 pname != GL_BUFFER_MAP_LENGTH &&
2791 pname != GL_BUFFER_MAP_OFFSET,
2792 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002793
2794 if (!params) return;
2795
2796 BufferData* buf = ctx->getBufferData(target);
2797
2798 switch (pname) {
2799 case GL_BUFFER_ACCESS_FLAGS:
2800 *params = buf ? buf->m_mappedAccess : 0;
2801 break;
2802 case GL_BUFFER_MAPPED:
2803 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
2804 break;
2805 case GL_BUFFER_SIZE:
2806 *params = buf ? buf->m_size : 0;
2807 break;
2808 case GL_BUFFER_USAGE:
2809 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
2810 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002811 case GL_BUFFER_MAP_LENGTH:
2812 *params = buf ? buf->m_mappedLength : 0;
2813 break;
2814 case GL_BUFFER_MAP_OFFSET:
2815 *params = buf ? buf->m_mappedOffset : 0;
2816 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002817 default:
2818 break;
2819 }
2820}
2821
2822void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
2823 GL2Encoder* ctx = (GL2Encoder*)self;
2824
2825 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2826 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002827 target != GL_ARRAY_BUFFER &&
2828 target != GL_ELEMENT_ARRAY_BUFFER &&
2829 target != GL_COPY_READ_BUFFER &&
2830 target != GL_COPY_WRITE_BUFFER &&
2831 target != GL_PIXEL_PACK_BUFFER &&
2832 target != GL_PIXEL_UNPACK_BUFFER &&
2833 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
2834 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002835 GL_INVALID_ENUM);
2836 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
2837 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002838 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
2839 pname != GL_BUFFER_MAPPED &&
2840 pname != GL_BUFFER_SIZE &&
2841 pname != GL_BUFFER_USAGE &&
2842 pname != GL_BUFFER_MAP_LENGTH &&
2843 pname != GL_BUFFER_MAP_OFFSET,
2844 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002845
2846 if (!params) return;
2847
2848 BufferData* buf = ctx->getBufferData(target);
2849
2850 switch (pname) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002851 case GL_BUFFER_ACCESS_FLAGS:
2852 *params = buf ? buf->m_mappedAccess : 0;
2853 break;
2854 case GL_BUFFER_MAPPED:
2855 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
2856 break;
2857 case GL_BUFFER_SIZE:
2858 *params = buf ? buf->m_size : 0;
2859 break;
2860 case GL_BUFFER_USAGE:
2861 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
2862 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002863 case GL_BUFFER_MAP_LENGTH:
2864 *params = buf ? buf->m_mappedLength : 0;
2865 break;
2866 case GL_BUFFER_MAP_OFFSET:
2867 *params = buf ? buf->m_mappedOffset : 0;
2868 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002869 default:
2870 break;
2871 }
2872}
2873
2874void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
2875 GL2Encoder* ctx = (GL2Encoder*)self;
2876 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2877 SET_ERROR_IF(
2878 target == GL_ATOMIC_COUNTER_BUFFER ||
2879 target == GL_DISPATCH_INDIRECT_BUFFER ||
2880 target == GL_DRAW_INDIRECT_BUFFER ||
2881 target == GL_SHADER_STORAGE_BUFFER,
2882 GL_INVALID_ENUM);
2883 SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
2884 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
2885 if (!params) return;
2886
2887 BufferData* buf = ctx->getBufferData(target);
2888
2889 if (!buf || !buf->m_mapped) { *params = NULL; return; }
2890
2891 *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
2892}
2893
2894static const char* const kNameDelimiter = ";";
2895
2896static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
2897
2898#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
2899
2900 std::string packed;
2901 // validate the array of char[]'s
2902 const char* currName;
2903 for (GLsizei i = 0; i < count; i++) {
2904 currName = names[i];
2905 VALIDATE(!currName, GL_INVALID_OPERATION);
2906 // check if has reasonable size
2907 size_t len = strlen(currName);
2908 VALIDATE(!len, GL_INVALID_OPERATION);
2909 // check for our delimiter, which if present
2910 // in the name, means an invalid name anyway.
2911 VALIDATE(strstr(currName, kNameDelimiter),
2912 GL_INVALID_OPERATION);
2913 packed += currName;
2914 packed += ";";
2915 }
2916
2917 *err_out = GL_NO_ERROR;
2918 return packed;
2919}
2920
2921void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
2922 GL2Encoder* ctx = (GL2Encoder*)self;
2923
2924 if (!uniformCount) return;
2925
2926 GLint err = GL_NO_ERROR;
2927 std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
2928 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
2929
2930 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
2931 std::vector<int> arrIndices;
2932 for (size_t i = 0; i < uniformCount; i++) {
2933 int err;
2934 arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
2935 if (err) {
2936 ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
2937 return;
2938 }
2939 }
2940
2941 ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
2942
2943 for (int i = 0; i < uniformCount; i++) {
2944 if (uniformIndices[i] >= 0 && needLocationWAR) {
2945 uniformIndices[i] =
2946 ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
2947 }
2948 }
2949}
2950
2951void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
2952 GL2Encoder *ctx = (GL2Encoder*)self;
2953 GLClientState* state = ctx->m_state;
2954 GLSharedGroupPtr shared = ctx->m_shared;
2955
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002956 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002957 ctx->m_glUniform1ui_enc(self, hostLoc, v0);
2958
2959 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002960 if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002961 GLenum origActiveTexture = state->getActiveTextureUnit();
2962 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
2963 ctx->m_glActiveTexture_enc(self, origActiveTexture);
2964 }
2965 state->setActiveTextureUnit(origActiveTexture);
2966 }
2967}
2968
2969void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) {
2970 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002971 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002972 ctx->m_glUniform2ui_enc(self, hostLoc, v0, v1);
2973}
2974
2975void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) {
2976 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002977 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002978 ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2);
2979}
2980
2981void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) {
2982 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002983 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002984 ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3);
2985}
2986
2987void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2988 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002989 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002990 ctx->m_glUniform1uiv_enc(self, hostLoc, count, value);
2991}
2992
2993void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2994 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002995 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002996 ctx->m_glUniform2uiv_enc(self, hostLoc, count, value);
2997}
2998
2999void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3000 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003001 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003002 ctx->m_glUniform3uiv_enc(self, hostLoc, count, value);
3003}
3004
3005void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3006 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003007 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003008 ctx->m_glUniform4uiv_enc(self, hostLoc, count, value);
3009}
3010
3011void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3012 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003013 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003014 ctx->m_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value);
3015}
3016
3017void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3018 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003019 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003020 ctx->m_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value);
3021}
3022
3023void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3024 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003025 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003026 ctx->m_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value);
3027}
3028
3029void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3030 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003031 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003032 ctx->m_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value);
3033}
3034
3035void GL2Encoder::s_glUniformMatrix3x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3036 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003037 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003038 ctx->m_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value);
3039}
3040
3041void GL2Encoder::s_glUniformMatrix4x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3042 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003043 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003044 ctx->m_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value);
3045}
3046
3047void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3048 GL2Encoder *ctx = (GL2Encoder*)self;
3049 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3050 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3051 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3052 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3053 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3054 ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3055}
3056
3057void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3058 GL2Encoder* ctx = (GL2Encoder*)self;
3059 GLClientState* state = ctx->m_state;
3060
3061 // refresh client state's # active uniforms in this block
3062 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3063 // TODO if worth it: cache uniform count and other params,
3064 // invalidate on program relinking.
3065 GLint numActiveUniforms;
3066 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3067 program, uniformBlockIndex,
3068 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3069 &numActiveUniforms);
3070 ctx->m_state->setNumActiveUniformsInUniformBlock(
3071 program, uniformBlockIndex, numActiveUniforms);
3072 }
3073
3074 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3075 program, uniformBlockIndex,
3076 pname, params);
3077}
3078
3079void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3080 GL2Encoder *ctx = (GL2Encoder *)self;
3081 assert(ctx->m_state);
3082 GLint maxIndex;
3083 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3084 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3085
3086 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3087 ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3088 }
3089}
3090
3091void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3092 GL2Encoder *ctx = (GL2Encoder *)self;
3093 assert(ctx->m_state);
3094 GLint maxIndex;
3095 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3096 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3097
3098 if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3099 ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3100 }
3101}
3102
3103void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3104 GL2Encoder *ctx = (GL2Encoder *)self;
3105 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003106 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003107 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
3108 SET_ERROR_IF(
3109 !(type == GL_BYTE ||
3110 type == GL_UNSIGNED_BYTE ||
3111 type == GL_SHORT ||
3112 type == GL_UNSIGNED_SHORT ||
3113 type == GL_INT ||
3114 type == GL_UNSIGNED_INT),
3115 GL_INVALID_ENUM);
3116 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
3117
3118 ctx->m_state->setVertexAttribBinding(index, index);
3119 ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true);
3120 GLsizei effectiveStride = stride;
3121 if (stride == 0) {
3122 effectiveStride = glSizeof(type) * size;
3123 }
3124 ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride);
3125
3126 if (ctx->m_state->currentArrayVbo() != 0) {
3127 ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer);
3128 } else {
3129 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION);
3130 // wait for client-array handler
3131 }
3132}
3133
3134void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) {
3135 GL2Encoder *ctx = (GL2Encoder *)self;
3136 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003137 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003138 ctx->m_state->setVertexAttribBinding(index, index);
3139 ctx->m_state->setVertexBindingDivisor(index, divisor);
3140 ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor);
3141}
3142
3143void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3144 GLenum target, GLsizei samples, GLenum internalformat,
3145 GLsizei width, GLsizei height) {
3146 GL2Encoder *ctx = (GL2Encoder *)self;
3147 GLClientState* state = ctx->m_state;
3148
3149 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3150 SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3151
3152 GLint max_samples;
3153 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3154 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3155
3156 state->setBoundRenderbufferFormat(internalformat);
3157 state->setBoundRenderbufferSamples(samples);
3158 ctx->m_glRenderbufferStorageMultisample_enc(
3159 self, target, samples, internalformat, width, height);
3160}
3161
3162void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3163 GL2Encoder* ctx = (GL2Encoder*)self;
3164 SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3165 SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3166 for (int i = 0; i < n; i++) {
3167 SET_ERROR_IF(
3168 bufs[i] != GL_NONE &&
3169 bufs[i] != GL_BACK &&
3170 glUtilsColorAttachmentIndex(bufs[i]) == -1,
3171 GL_INVALID_ENUM);
3172 SET_ERROR_IF(
3173 !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3174 glUtilsColorAttachmentIndex(bufs[i]) != -1,
3175 GL_INVALID_OPERATION);
3176 SET_ERROR_IF(
3177 ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3178 ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3179 glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3180 (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3181 bufs[i] != GL_NONE)),
3182 GL_INVALID_OPERATION);
3183 }
3184
3185 ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3186}
3187
3188void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3189 GL2Encoder* ctx = (GL2Encoder*)self;
3190
3191 SET_ERROR_IF(
3192 glUtilsColorAttachmentIndex(src) != -1 &&
3193 (glUtilsColorAttachmentIndex(src) >=
3194 ctx->m_state->getMaxColorAttachments()),
3195 GL_INVALID_OPERATION);
3196 SET_ERROR_IF(
3197 src != GL_NONE &&
3198 src != GL_BACK &&
3199 src > GL_COLOR_ATTACHMENT0 &&
3200 src < GL_DEPTH_ATTACHMENT &&
3201 (src - GL_COLOR_ATTACHMENT0) >
3202 ctx->m_state->getMaxColorAttachments(),
3203 GL_INVALID_OPERATION);
3204 SET_ERROR_IF(
3205 src != GL_NONE &&
3206 src != GL_BACK &&
3207 glUtilsColorAttachmentIndex(src) == -1,
3208 GL_INVALID_ENUM);
3209 SET_ERROR_IF(
3210 !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3211 src != GL_NONE &&
3212 src != GL_BACK,
3213 GL_INVALID_OPERATION);
3214 SET_ERROR_IF(
3215 ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3216 src != GL_NONE &&
3217 glUtilsColorAttachmentIndex(src) == -1,
3218 GL_INVALID_OPERATION);
3219
3220 ctx->m_glReadBuffer_enc(ctx, src);
3221}
3222
3223void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3224 GL2Encoder* ctx = (GL2Encoder*)self;
3225 GLClientState* state = ctx->m_state;
3226
3227 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3228 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3229 GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3230 SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3231 lastBoundTarget != GL_TEXTURE_3D,
3232 GL_INVALID_OPERATION);
3233 state->attachTextureObject(target, attachment, texture);
3234
3235 GLint max3DTextureSize;
3236 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3237 SET_ERROR_IF(
3238 layer >= max3DTextureSize,
3239 GL_INVALID_VALUE);
3240
3241 ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3242}
3243
3244void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3245 GL2Encoder* ctx = (GL2Encoder*)self;
3246 GLClientState* state = ctx->m_state;
3247
3248 SET_ERROR_IF(
3249 target != GL_TEXTURE_2D &&
3250 target != GL_TEXTURE_CUBE_MAP,
3251 GL_INVALID_ENUM);
3252 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3253 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3254 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3255 SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3256 GL_INVALID_OPERATION);
3257 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3258
3259 state->setBoundTextureInternalFormat(target, internalformat);
3260 state->setBoundTextureDims(target, -1, width, height, 1);
3261 state->setBoundTextureImmutableFormat(target);
3262 ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
3263}
3264
3265void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3266 GL2Encoder* ctx = (GL2Encoder*)self;
3267
3268 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3269
3270 GLint maxCount = 0;
3271 ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3272
3273 SET_ERROR_IF(
3274 bufferMode == GL_SEPARATE_ATTRIBS &&
3275 maxCount < count,
3276 GL_INVALID_VALUE);
3277 SET_ERROR_IF(
3278 bufferMode != GL_INTERLEAVED_ATTRIBS &&
3279 bufferMode != GL_SEPARATE_ATTRIBS,
3280 GL_INVALID_ENUM);
3281
3282 if (!count) return;
3283
3284 GLint err = GL_NO_ERROR;
3285 std::string packed = packVarNames(count, varyings, &err);
3286 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3287
3288 ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3289}
3290
3291void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3292 GL2Encoder* ctx = (GL2Encoder*)self;
3293 GLClientState* state = ctx->m_state;
3294 ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3295 state->setTransformFeedbackActiveUnpaused(true);
3296}
3297
3298void GL2Encoder::s_glEndTransformFeedback(void* self) {
3299 GL2Encoder* ctx = (GL2Encoder*)self;
3300 GLClientState* state = ctx->m_state;
3301 ctx->m_glEndTransformFeedback_enc(ctx);
3302 state->setTransformFeedbackActiveUnpaused(false);
3303}
3304
3305void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3306 GL2Encoder* ctx = (GL2Encoder*)self;
3307 GLClientState* state = ctx->m_state;
3308 ctx->m_glPauseTransformFeedback_enc(ctx);
3309 state->setTransformFeedbackActiveUnpaused(false);
3310}
3311
3312void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3313 GL2Encoder* ctx = (GL2Encoder*)self;
3314 GLClientState* state = ctx->m_state;
3315 ctx->m_glResumeTransformFeedback_enc(ctx);
3316 state->setTransformFeedbackActiveUnpaused(true);
3317}
3318
3319void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3320 GLsizei width, GLsizei height, GLsizei depth,
3321 GLint border, GLenum format, GLenum type, const GLvoid* data) {
3322 GL2Encoder* ctx = (GL2Encoder*)self;
3323 GLClientState* state = ctx->m_state;
3324
3325 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3326 target != GL_TEXTURE_2D_ARRAY,
3327 GL_INVALID_ENUM);
3328 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3329 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3330
3331 // If unpack buffer is nonzero, verify unmapped state.
3332 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3333
3334 GLint max_texture_size;
3335 GLint max_3d_texture_size;
3336 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3337 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3338 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3339 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3340 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3341
3342 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3343 SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3344 SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3345 SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3346 SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3347 SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3348 SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3349 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3350 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3351 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3352 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3353 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3354 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3355 GL_INVALID_OPERATION);
3356 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3357 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3358 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3359 glSizeof(type)),
3360 GL_INVALID_OPERATION);
3361 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3362
3363 state->setBoundTextureInternalFormat(target, internalFormat);
3364 state->setBoundTextureFormat(target, format);
3365 state->setBoundTextureType(target, type);
3366 state->setBoundTextureDims(target, level, width, height, depth);
3367
3368 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3369 ctx->glTexImage3DOffsetAEMU(
3370 ctx, target, level, internalFormat,
3371 width, height, depth,
3372 border, format, type, (uintptr_t)data);
3373 } else {
3374 ctx->m_glTexImage3D_enc(ctx,
3375 target, level, internalFormat,
3376 width, height, depth,
3377 border, format, type, data);
3378 }
3379}
3380
3381void 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) {
3382 GL2Encoder* ctx = (GL2Encoder*)self;
3383 GLClientState* state = ctx->m_state;
3384
3385 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3386 target != GL_TEXTURE_2D_ARRAY,
3387 GL_INVALID_ENUM);
3388 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3389 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3390 // If unpack buffer is nonzero, verify unmapped state.
3391 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3392 GLint max_texture_size;
3393 GLint max_3d_texture_size;
3394 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3395 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3396 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3397 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3398 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3399 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3400 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3401 GLuint tex = state->getBoundTexture(target);
3402 GLsizei neededWidth = xoffset + width;
3403 GLsizei neededHeight = yoffset + height;
3404 GLsizei neededDepth = zoffset + depth;
3405
3406 SET_ERROR_IF(tex &&
3407 (neededWidth > state->queryTexWidth(level, tex) ||
3408 neededHeight > state->queryTexHeight(level, tex) ||
3409 neededDepth > state->queryTexDepth(level, tex)),
3410 GL_INVALID_VALUE);
3411 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3412 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3413 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3414 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3415 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3416 GL_INVALID_OPERATION);
3417 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3418 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3419 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3420 glSizeof(type)),
3421 GL_INVALID_OPERATION);
3422 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
3423 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3424
3425 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3426 ctx->glTexSubImage3DOffsetAEMU(ctx,
3427 target, level,
3428 xoffset, yoffset, zoffset,
3429 width, height, depth,
3430 format, type, (uintptr_t)data);
3431 } else {
3432 ctx->m_glTexSubImage3D_enc(ctx,
3433 target, level,
3434 xoffset, yoffset, zoffset,
3435 width, height, depth,
3436 format, type, data);
3437 }
3438}
3439
3440void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
3441 GL2Encoder* ctx = (GL2Encoder*)self;
3442 GLClientState* state = ctx->m_state;
3443
3444 // Filter compressed formats support.
3445 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3446 // If unpack buffer is nonzero, verify unmapped state.
3447 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3448 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3449 SET_ERROR_IF(border, GL_INVALID_VALUE);
3450 // If unpack buffer is nonzero, verify buffer data fits.
3451 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3452 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3453 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3454 GL_INVALID_OPERATION);
3455 // TODO: Fix:
3456 // If |imageSize| is too small for compressed dimensions.
3457 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
3458 state->setBoundTextureInternalFormat(target, (GLint)internalformat);
3459 state->setBoundTextureDims(target, level, width, height, depth);
3460
3461 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3462 ctx->glCompressedTexImage3DOffsetAEMU(
3463 ctx, target, level, internalformat,
3464 width, height, depth, border,
3465 imageSize, (uintptr_t)data);
3466 } else {
3467 ctx->m_glCompressedTexImage3D_enc(
3468 ctx, target, level, internalformat,
3469 width, height, depth, border,
3470 imageSize, data);
3471 }
3472}
3473
3474void 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) {
3475 GL2Encoder* ctx = (GL2Encoder*)self;
3476 GLClientState* state = ctx->m_state;
3477
3478 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3479 // If unpack buffer is nonzero, verify unmapped state.
3480 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3481 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3482 // If unpack buffer is nonzero, verify buffer data fits.
3483 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3484 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3485 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3486 GL_INVALID_OPERATION);
3487 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3488
3489 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3490 ctx->glCompressedTexSubImage3DOffsetAEMU(
3491 ctx, target, level,
3492 xoffset, yoffset, zoffset,
3493 width, height, depth,
3494 format, imageSize, (uintptr_t)data);
3495 } else {
3496 ctx->m_glCompressedTexSubImage3D_enc(
3497 ctx, target, level,
3498 xoffset, yoffset, zoffset,
3499 width, height, depth,
3500 format, imageSize, data);
3501
3502 }
3503}
3504
3505void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
3506 GL2Encoder* ctx = (GL2Encoder*)self;
3507 GLClientState* state = ctx->m_state;
3508 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3509 target != GL_TEXTURE_2D_ARRAY,
3510 GL_INVALID_ENUM);
3511 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3512 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3513 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3514 SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
3515 GL_INVALID_OPERATION);
3516 SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
3517 GL_INVALID_OPERATION);
3518 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3519
3520 state->setBoundTextureInternalFormat(target, internalformat);
3521 state->setBoundTextureDims(target, -1, width, height, depth);
3522 state->setBoundTextureImmutableFormat(target);
3523 ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
3524 state->setBoundTextureImmutableFormat(target);
3525}
3526
3527void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
3528 GL2Encoder *ctx = (GL2Encoder *)self;
3529 assert(ctx->m_state != NULL);
3530 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3531 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3532
3533 bool has_client_vertex_arrays = false;
3534 bool has_indirect_arrays = false;
3535 ctx->getVBOUsage(&has_client_vertex_arrays,
3536 &has_indirect_arrays);
3537
3538 if (has_client_vertex_arrays ||
3539 (!has_client_vertex_arrays &&
3540 !has_indirect_arrays)) {
3541 ctx->sendVertexAttributes(first, count, true, primcount);
3542 ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
3543 } else {
3544 ctx->sendVertexAttributes(0, count, false, primcount);
3545 ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
3546 }
3547 ctx->m_stream->flush();
3548}
3549
3550void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
3551{
3552
3553 GL2Encoder *ctx = (GL2Encoder *)self;
3554 assert(ctx->m_state != NULL);
3555 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3556 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3557 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3558 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3559
3560 bool has_client_vertex_arrays = false;
3561 bool has_indirect_arrays = false;
3562 int nLocations = ctx->m_state->nLocations();
3563 GLintptr offset = 0;
3564
3565 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3566
3567 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3568 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3569 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3570 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3571 }
3572
3573 BufferData* buf = NULL;
3574 int minIndex = 0, maxIndex = 0;
3575
3576 // For validation/immediate index array purposes,
3577 // we need the min/max vertex index of the index array.
3578 // If the VBO != 0, this may not be the first time we have
3579 // used this particular index buffer. getBufferIndexRange
3580 // can more quickly get min/max vertex index by
3581 // caching previous results.
3582 if (ctx->m_state->currentIndexVbo() != 0) {
3583 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3584 offset = (GLintptr)indices;
3585 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3586 ctx->getBufferIndexRange(buf,
3587 indices,
3588 type,
3589 (size_t)count,
3590 (size_t)offset,
3591 &minIndex, &maxIndex);
3592 } else {
3593 // In this case, the |indices| field holds a real
3594 // array, so calculate the indices now. They will
3595 // also be needed to know how much data to
3596 // transfer to host.
3597 ctx->calcIndexRange(indices,
3598 type,
3599 count,
3600 &minIndex,
3601 &maxIndex);
3602 }
3603
3604 bool adjustIndices = true;
3605 if (ctx->m_state->currentIndexVbo() != 0) {
3606 if (!has_client_vertex_arrays) {
3607 ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
3608 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3609 ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
3610 ctx->flushDrawCall();
3611 adjustIndices = false;
3612 } else {
3613 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3614 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3615 }
3616 }
3617 if (adjustIndices) {
3618 void *adjustedIndices =
3619 ctx->recenterIndices(indices,
3620 type,
3621 count,
3622 minIndex);
3623
3624 if (has_indirect_arrays || 1) {
3625 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
3626 ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
3627 ctx->m_stream->flush();
3628 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3629 if(!has_indirect_arrays) {
3630 //ALOGD("unoptimized drawelements !!!\n");
3631 }
3632 } else {
3633 // we are all direct arrays and immidate mode index array -
3634 // rebuild the arrays and the index array;
3635 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3636 }
3637 }
3638}
3639
3640void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
3641{
3642
3643 GL2Encoder *ctx = (GL2Encoder *)self;
3644 assert(ctx->m_state != NULL);
3645 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3646 SET_ERROR_IF(end < start, GL_INVALID_VALUE);
3647 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3648 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3649 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3650
3651 bool has_client_vertex_arrays = false;
3652 bool has_indirect_arrays = false;
3653 int nLocations = ctx->m_state->nLocations();
3654 GLintptr offset = 0;
3655
3656 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3657
3658 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3659 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3660 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3661 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3662 }
3663
3664 BufferData* buf = NULL;
3665 int minIndex = 0, maxIndex = 0;
3666
3667 // For validation/immediate index array purposes,
3668 // we need the min/max vertex index of the index array.
3669 // If the VBO != 0, this may not be the first time we have
3670 // used this particular index buffer. getBufferIndexRange
3671 // can more quickly get min/max vertex index by
3672 // caching previous results.
3673 if (ctx->m_state->currentIndexVbo() != 0) {
3674 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3675 offset = (GLintptr)indices;
3676 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3677 ctx->getBufferIndexRange(buf,
3678 indices,
3679 type,
3680 (size_t)count,
3681 (size_t)offset,
3682 &minIndex, &maxIndex);
3683 } else {
3684 // In this case, the |indices| field holds a real
3685 // array, so calculate the indices now. They will
3686 // also be needed to know how much data to
3687 // transfer to host.
3688 ctx->calcIndexRange(indices,
3689 type,
3690 count,
3691 &minIndex,
3692 &maxIndex);
3693 }
3694
3695 bool adjustIndices = true;
3696 if (ctx->m_state->currentIndexVbo() != 0) {
3697 if (!has_client_vertex_arrays) {
3698 ctx->sendVertexAttributes(0, maxIndex + 1, false);
3699 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3700 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
3701 ctx->flushDrawCall();
3702 adjustIndices = false;
3703 } else {
3704 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3705 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3706 }
3707 }
3708 if (adjustIndices) {
3709 void *adjustedIndices =
3710 ctx->recenterIndices(indices,
3711 type,
3712 count,
3713 minIndex);
3714
3715 if (has_indirect_arrays || 1) {
3716 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
3717 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
3718 ctx->m_stream->flush();
3719 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3720 if(!has_indirect_arrays) {
3721 //ALOGD("unoptimized drawelements !!!\n");
3722 }
3723 } else {
3724 // we are all direct arrays and immidate mode index array -
3725 // rebuild the arrays and the index array;
3726 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3727 }
3728 }
3729}
3730
3731// struct GLStringKey {
3732// GLenum name;
3733// GLuint index;
3734// };
3735//
3736// struct GLStringKeyCompare {
3737// bool operator() (const GLStringKey& a,
3738// const GLStringKey& b) const {
3739// if (a.name != b.name) return a.name < b.name;
3740// if (a.index != b.index) return a.index < b.index;
3741// return false;
3742// }
3743// };
3744//
3745// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
3746//
3747// static GLStringStore sGLStringStore;
3748// bool sGLStringStoreInitialized = false;
3749
3750const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
3751 GL2Encoder *ctx = (GL2Encoder *)self;
3752 GLubyte *retval = (GLubyte *) "";
3753
3754 RET_AND_SET_ERROR_IF(
3755 name != GL_VENDOR &&
3756 name != GL_RENDERER &&
3757 name != GL_VERSION &&
3758 name != GL_EXTENSIONS,
3759 GL_INVALID_ENUM,
3760 retval);
3761
3762 RET_AND_SET_ERROR_IF(
3763 name == GL_VENDOR ||
3764 name == GL_RENDERER ||
3765 name == GL_VERSION ||
3766 name == GL_EXTENSIONS &&
3767 index != 0,
3768 GL_INVALID_VALUE,
3769 retval);
3770
3771 switch (name) {
3772 case GL_VENDOR:
3773 retval = gVendorString;
3774 break;
3775 case GL_RENDERER:
3776 retval = gRendererString;
3777 break;
3778 case GL_VERSION:
3779 retval = gVersionString;
3780 break;
3781 case GL_EXTENSIONS:
3782 retval = gExtensionsString;
3783 break;
3784 }
3785
3786 return retval;
3787}
3788
3789void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
3790 GL2Encoder *ctx = (GL2Encoder *)self;
3791
3792 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3793
3794 GLint linkStatus = 0;
3795 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
3796 GLint properLength = 0;
3797 ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
3798
3799 SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
3800 SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
3801
3802 ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
3803}
3804
3805void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
3806 GL2Encoder *ctx = (GL2Encoder *)self;
3807
3808 SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
3809 SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
3810 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
3811 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
3812 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
3813 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
3814 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
3815 ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
3816 GL_INVALID_OPERATION);
3817 /*
3818GL_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.
3819
3820GL_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.
3821
3822GL_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.
3823
3824GL_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.
3825*/
3826
3827 FboFormatInfo fbo_format_info;
3828 ctx->m_state->getBoundFramebufferFormat(
3829 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
3830 SET_ERROR_IF(
3831 fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3832 !GLESv2Validation::readPixelsFboFormatMatch(
3833 format, type, fbo_format_info.tex_type),
3834 GL_INVALID_OPERATION);
3835
3836 if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
3837 ctx->glReadPixelsOffsetAEMU(
3838 ctx, x, y, width, height,
3839 format, type, (uintptr_t)pixels);
3840 } else {
3841 ctx->m_glReadPixels_enc(
3842 ctx, x, y, width, height,
3843 format, type, pixels);
3844 }
3845}
3846
3847// Track enabled state for some things like:
3848// - Primitive restart
3849void GL2Encoder::s_glEnable(void* self, GLenum what) {
3850 GL2Encoder *ctx = (GL2Encoder *)self;
3851
3852 switch (what) {
3853 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
3854 ctx->m_primitiveRestartEnabled = true;
3855 break;
3856 }
3857
3858 ctx->m_glEnable_enc(ctx, what);
3859}
3860
3861void GL2Encoder::s_glDisable(void* self, GLenum what) {
3862 GL2Encoder *ctx = (GL2Encoder *)self;
3863
3864 switch (what) {
3865 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
3866 ctx->m_primitiveRestartEnabled = false;
3867 break;
3868 }
3869
3870 ctx->m_glDisable_enc(ctx, what);
3871}
3872
3873void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
3874 GL2Encoder *ctx = (GL2Encoder *)self;
3875
3876 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3877
3878 ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
3879}
3880
3881void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
3882 GL2Encoder *ctx = (GL2Encoder *)self;
3883
3884 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3885
3886 ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
3887}
3888
3889void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
3890 GL2Encoder *ctx = (GL2Encoder *)self;
3891
3892 SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3893
3894 ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
3895}
3896
3897void 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) {
3898 GL2Encoder *ctx = (GL2Encoder *)self;
3899 GLClientState* state = ctx->m_state;
3900
3901 bool validateColor = mask | GL_COLOR_BUFFER_BIT;
3902 bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
3903 bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
3904
3905 FboFormatInfo read_fbo_format_info;
3906 FboFormatInfo draw_fbo_format_info;
3907 if (validateColor) {
3908 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
3909 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
3910
3911 if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3912 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
3913 SET_ERROR_IF(
3914 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3915 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3916 !GLESv2Validation::blitFramebufferFormat(
3917 read_fbo_format_info.tex_type,
3918 draw_fbo_format_info.tex_type),
3919 GL_INVALID_OPERATION);
3920 }
3921 }
3922
3923 if (validateDepth) {
3924 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
3925 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
3926
3927 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3928 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
3929 SET_ERROR_IF(
3930 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3931 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3932 !GLESv2Validation::blitFramebufferFormat(
3933 read_fbo_format_info.rb_format,
3934 draw_fbo_format_info.rb_format),
3935 GL_INVALID_OPERATION);
3936 }
3937 }
3938
3939 if (validateStencil) {
3940 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
3941 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
3942
3943 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3944 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
3945 SET_ERROR_IF(
3946 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3947 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3948 !GLESv2Validation::blitFramebufferFormat(
3949 read_fbo_format_info.rb_format,
3950 draw_fbo_format_info.rb_format),
3951 GL_INVALID_OPERATION);
3952 }
3953 }
3954
3955 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
3956 SET_ERROR_IF(
3957 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3958 draw_fbo_format_info.rb_multisamples > 0,
3959 GL_INVALID_OPERATION);
3960 SET_ERROR_IF(
3961 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3962 draw_fbo_format_info.tex_multisamples > 0,
3963 GL_INVALID_OPERATION);
3964
3965 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
3966 SET_ERROR_IF(
3967 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3968 read_fbo_format_info.rb_multisamples > 0 &&
3969 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3970 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3971 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3972 (read_fbo_format_info.rb_format !=
3973 draw_fbo_format_info.rb_format),
3974 GL_INVALID_OPERATION);
3975 SET_ERROR_IF(
3976 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3977 read_fbo_format_info.rb_multisamples > 0 &&
3978 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3979 (srcX0 != dstX0 || srcY0 != dstY0 ||
3980 srcX1 != dstX1 || srcY1 != dstY1),
3981 GL_INVALID_OPERATION);
3982
3983 ctx->m_glBlitFramebuffer_enc(ctx,
3984 srcX0, srcY0, srcX1, srcY1,
3985 dstX0, dstY0, dstX1, dstY1,
3986 mask, filter);
3987}
3988
3989void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
3990 GL2Encoder *ctx = (GL2Encoder *)self;
3991
3992 SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
3993 pname != GL_SAMPLES,
3994 GL_INVALID_ENUM);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003995 SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003996 SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08003997 !GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
3998 !GLESv2Validation::depthRenderableFormat(ctx, internalformat) &&
3999 !GLESv2Validation::stencilRenderableFormat(ctx, internalformat),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004000 GL_INVALID_ENUM);
4001 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4002
4003 if (bufSize < 1) return;
4004
4005 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
4006 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
4007 switch (pname) {
4008 case GL_NUM_SAMPLE_COUNTS:
4009 *params = 3;
4010 break;
4011 case GL_SAMPLES:
4012 params[0] = 4;
4013 if (bufSize > 1) params[1] = 2;
4014 if (bufSize > 2) params[2] = 1;
4015 break;
4016 default:
4017 break;
4018 }
4019}
4020
4021void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
4022 GL2Encoder *ctx = (GL2Encoder *)self;
4023 GLClientState* state = ctx->m_state;
4024
4025 SET_ERROR_IF(target != GL_TEXTURE_2D &&
4026 target != GL_TEXTURE_3D &&
4027 target != GL_TEXTURE_CUBE_MAP,
4028 GL_INVALID_ENUM);
4029
4030 GLuint tex = state->getBoundTexture(target);
4031 GLenum internalformat = state->queryTexInternalFormat(tex);
4032 GLenum format = state->queryTexFormat(tex);
4033
4034 SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
4035 GL_INVALID_OPERATION);
4036 SET_ERROR_IF(tex &&
4037 !GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004038 !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4039 GLESv2Validation::filterableTexFormat(ctx, internalformat)),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004040 GL_INVALID_OPERATION);
4041
4042 ctx->m_glGenerateMipmap_enc(ctx, target);
4043}
4044
4045void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4046 GL2Encoder *ctx = (GL2Encoder *)self;
4047 GLint maxCombinedUnits;
4048 ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4049 SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4050
4051 ctx->m_glBindSampler_enc(ctx, unit, sampler);
4052}
4053
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004054GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4055 GL2Encoder *ctx = (GL2Encoder *)self;
4056 uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4057 return (GLsync)(uintptr_t)syncHandle;
4058}
4059
4060GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4061 GL2Encoder *ctx = (GL2Encoder *)self;
4062 return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4063}
4064
4065void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4066 GL2Encoder *ctx = (GL2Encoder *)self;
4067 ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4068}
4069
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004070void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) {
4071 GL2Encoder *ctx = (GL2Encoder *)self;
4072
4073 if (!sync) return;
4074
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004075 ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4076}
4077
4078GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4079 GL2Encoder *ctx = (GL2Encoder *)self;
4080 return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4081}
4082
4083void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4084 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004085
4086 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4087
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004088 return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004089}
4090
4091#define LIMIT_CASE(target, lim) \
4092 case target: \
4093 ctx->glGetIntegerv(ctx, lim, &limit); \
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004094 SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004095 break; \
4096
4097void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) {
4098 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004099 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004100
4101 GLint limit;
4102
4103 switch (target) {
4104 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4105 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4106 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4107 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4108 default:
4109 break;
4110 }
4111
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004112 const GLClientState::VertexAttribBindingVector& currBindings =
4113 state->currentVertexBufferBindings();
4114
4115 switch (target) {
4116 case GL_VERTEX_BINDING_DIVISOR:
4117 case GL_VERTEX_BINDING_OFFSET:
4118 case GL_VERTEX_BINDING_STRIDE:
4119 case GL_VERTEX_BINDING_BUFFER:
4120 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4121 break;
4122 default:
4123 break;
4124 }
4125
4126 switch (target) {
4127 case GL_VERTEX_BINDING_DIVISOR:
4128 *params = currBindings[index].divisor;
4129 return;
4130 case GL_VERTEX_BINDING_OFFSET:
4131 *params = currBindings[index].offset;
4132 return;
4133 case GL_VERTEX_BINDING_STRIDE:
4134 *params = currBindings[index].effectiveStride;
4135 return;
4136 case GL_VERTEX_BINDING_BUFFER:
4137 *params = currBindings[index].buffer;
4138 return;
4139 default:
4140 break;
4141 }
4142
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004143 ctx->m_glGetIntegeri_v_enc(self, target, index, params);
4144}
4145
4146void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
4147 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004148 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004149
4150 GLint limit;
4151
4152 switch (target) {
4153 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4154 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4155 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4156 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4157 default:
4158 break;
4159 }
4160
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004161 const GLClientState::VertexAttribBindingVector& currBindings =
4162 state->currentVertexBufferBindings();
4163
4164 switch (target) {
4165 case GL_VERTEX_BINDING_DIVISOR:
4166 case GL_VERTEX_BINDING_OFFSET:
4167 case GL_VERTEX_BINDING_STRIDE:
4168 case GL_VERTEX_BINDING_BUFFER:
4169 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4170 break;
4171 default:
4172 break;
4173 }
4174
4175 switch (target) {
4176 case GL_VERTEX_BINDING_DIVISOR:
4177 *params = currBindings[index].divisor;
4178 return;
4179 case GL_VERTEX_BINDING_OFFSET:
4180 *params = currBindings[index].offset;
4181 return;
4182 case GL_VERTEX_BINDING_STRIDE:
4183 *params = currBindings[index].effectiveStride;
4184 return;
4185 case GL_VERTEX_BINDING_BUFFER:
4186 *params = currBindings[index].buffer;
4187 return;
4188 default:
4189 break;
4190 }
4191
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004192 ctx->m_glGetInteger64i_v_enc(self, target, index, params);
4193}
4194
4195void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4196 GL2Encoder *ctx = (GL2Encoder *)self;
4197 ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4198 if (pname == GL_SHADER_SOURCE_LENGTH) {
4199 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4200 if (shaderData) {
4201 int totalLen = 0;
4202 for (int i = 0; i < shaderData->sources.size(); i++) {
4203 totalLen += shaderData->sources[i].size();
4204 }
4205 if (totalLen != 0) {
4206 *params = totalLen + 1; // account for null terminator
4207 }
4208 }
4209 }
4210}
4211
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004212void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) {
4213 GL2Encoder *ctx = (GL2Encoder*)self;
4214 GLClientState* state = ctx->m_state;
4215 GLSharedGroupPtr shared = ctx->m_shared;
4216
4217 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4218 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4219 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4220
4221 ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program);
4222 if (!state->currentProgram()) {
4223 state->setCurrentShaderProgram(program);
4224 }
4225}
4226
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004227GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4228
4229 GLint* length = NULL;
4230 GL2Encoder* ctx = (GL2Encoder*)self;
4231
4232 int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
4233 char *str = new char[len + 1];
4234 glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
4235
4236 // Do GLSharedGroup and location WorkARound-specific initialization
4237 // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4238 uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4239 ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
4240 ShaderData* sData = spData->shaderData;
4241
4242 if (!replaceSamplerExternalWith2D(str, sData)) {
4243 delete [] str;
4244 ctx->setError(GL_OUT_OF_MEMORY);
4245 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4246 return -1;
4247 }
4248
4249 GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
4250 delete [] str;
4251
4252 // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4253 GLint linkStatus = 0;
4254 ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4255 if (!linkStatus) {
4256 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4257 return -1;
4258 }
4259
4260 ctx->m_shared->associateGLShaderProgram(res, spDataId);
4261
4262 GLint numUniforms = 0;
4263 ctx->glGetProgramiv(ctx, res, GL_ACTIVE_UNIFORMS, &numUniforms);
4264 ctx->m_shared->initShaderProgramData(res, numUniforms);
4265
4266 GLint maxLength=0;
4267 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4268
4269 GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4270
4271 for (GLint i = 0; i < numUniforms; ++i) {
4272 ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4273 GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4274 ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4275 }
4276
4277 ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4278
4279 delete [] name;
4280
4281 return res;
4282}
4283
4284void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4285{
4286 GL2Encoder *ctx = (GL2Encoder*)self;
4287 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4288 ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4289}
4290
4291void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4292{
4293 GL2Encoder *ctx = (GL2Encoder*)self;
4294 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4295 ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4296}
4297
4298void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4299{
4300 GL2Encoder *ctx = (GL2Encoder*)self;
4301 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004302 ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004303
4304 GLClientState* state = ctx->m_state;
4305 GLSharedGroupPtr shared = ctx->m_shared;
4306 GLenum target;
4307
4308 if (shared->setSamplerUniform(program, location, v0, &target)) {
4309 GLenum origActiveTexture = state->getActiveTextureUnit();
4310 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4311 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4312 }
4313 state->setActiveTextureUnit(origActiveTexture);
4314 }
4315}
4316
4317void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4318{
4319 GL2Encoder *ctx = (GL2Encoder*)self;
4320 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4321 ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4322}
4323
4324void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4325{
4326 GL2Encoder *ctx = (GL2Encoder*)self;
4327 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4328 ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4329
4330 GLClientState* state = ctx->m_state;
4331 GLSharedGroupPtr shared = ctx->m_shared;
4332 GLenum target;
4333
4334 if (shared->setSamplerUniform(program, location, v0, &target)) {
4335 GLenum origActiveTexture = state->getActiveTextureUnit();
4336 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4337 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4338 }
4339 state->setActiveTextureUnit(origActiveTexture);
4340 }
4341}
4342
4343void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4344{
4345 GL2Encoder *ctx = (GL2Encoder*)self;
4346 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4347 ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
4348}
4349
4350void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
4351{
4352 GL2Encoder *ctx = (GL2Encoder*)self;
4353 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4354 ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
4355}
4356
4357void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4358{
4359 GL2Encoder *ctx = (GL2Encoder*)self;
4360 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4361 ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
4362}
4363
4364void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
4365{
4366 GL2Encoder *ctx = (GL2Encoder*)self;
4367 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4368 ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
4369}
4370
4371void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4372{
4373 GL2Encoder *ctx = (GL2Encoder*)self;
4374 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4375 ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
4376}
4377
4378void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
4379{
4380 GL2Encoder *ctx = (GL2Encoder*)self;
4381 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4382 ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
4383}
4384
4385void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4386{
4387 GL2Encoder *ctx = (GL2Encoder*)self;
4388 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4389 ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
4390}
4391
4392void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
4393{
4394 GL2Encoder *ctx = (GL2Encoder*)self;
4395 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4396 ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
4397}
4398
4399void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4400{
4401 GL2Encoder *ctx = (GL2Encoder*)self;
4402 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4403 ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
4404}
4405
4406void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
4407{
4408 GL2Encoder *ctx = (GL2Encoder*)self;
4409 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4410 ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
4411}
4412
4413void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4414{
4415 GL2Encoder *ctx = (GL2Encoder*)self;
4416 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4417 ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
4418}
4419
4420void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
4421{
4422 GL2Encoder *ctx = (GL2Encoder*)self;
4423 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4424 ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
4425}
4426
4427void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4428{
4429 GL2Encoder *ctx = (GL2Encoder*)self;
4430 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4431 ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
4432}
4433
4434void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
4435{
4436 GL2Encoder *ctx = (GL2Encoder*)self;
4437 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4438 ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
4439}
4440
4441void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4442{
4443 GL2Encoder *ctx = (GL2Encoder*)self;
4444 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4445 ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
4446}
4447
4448void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
4449{
4450 GL2Encoder *ctx = (GL2Encoder*)self;
4451 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4452 ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
4453}
4454
4455void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4456{
4457 GL2Encoder *ctx = (GL2Encoder*)self;
4458 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4459 ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
4460}
4461
4462void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
4463{
4464 GL2Encoder *ctx = (GL2Encoder*)self;
4465 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4466 ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
4467}
4468
4469void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4470{
4471 GL2Encoder *ctx = (GL2Encoder*)self;
4472 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4473 ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
4474}
4475
4476void GL2Encoder::s_glProgramUniformMatrix2fv(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_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
4481}
4482
4483void GL2Encoder::s_glProgramUniformMatrix2x3fv(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_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
4488}
4489
4490void GL2Encoder::s_glProgramUniformMatrix2x4fv(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_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
4495}
4496
4497void GL2Encoder::s_glProgramUniformMatrix3fv(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_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
4502}
4503
4504void GL2Encoder::s_glProgramUniformMatrix3x2fv(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_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
4509}
4510
4511void GL2Encoder::s_glProgramUniformMatrix3x4fv(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_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
4516}
4517
4518void GL2Encoder::s_glProgramUniformMatrix4fv(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_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
4523}
4524
4525void GL2Encoder::s_glProgramUniformMatrix4x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4526{
4527 GL2Encoder *ctx = (GL2Encoder*)self;
4528 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4529 ctx->m_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
4530}
4531
4532void GL2Encoder::s_glProgramUniformMatrix4x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4533{
4534 GL2Encoder *ctx = (GL2Encoder*)self;
4535 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4536 ctx->m_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
4537}
4538
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004539void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) {
4540 GL2Encoder* ctx = (GL2Encoder*)self;
4541 ctx->m_glProgramParameteri_enc(self, program, pname, value);
4542}
4543
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004544void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
4545{
4546 GL2Encoder *ctx = (GL2Encoder*)self;
4547 GLClientState* state = ctx->m_state;
4548 GLSharedGroupPtr shared = ctx->m_shared;
4549
4550 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4551 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4552 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4553
4554 ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
4555 state->associateProgramWithPipeline(program, pipeline);
4556
4557 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4558 if (state->currentProgram()) {
4559 return;
4560 }
4561
4562 // Otherwise, update host texture 2D bindings.
4563 ctx->updateHostTexture2DBindingsFromProgramData(program);
4564}
4565
4566void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
4567{
4568 GL2Encoder *ctx = (GL2Encoder*)self;
4569 GLClientState* state = ctx->m_state;
4570
4571 ctx->m_glBindProgramPipeline_enc(self, pipeline);
4572
4573 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4574 if (!pipeline || state->currentProgram()) {
4575 return;
4576 }
4577
4578 GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
4579 for (; it != state->programPipelineEnd(); ++it) {
4580 if (it->second == pipeline) {
4581 ctx->updateHostTexture2DBindingsFromProgramData(it->first);
4582 }
4583 }
4584}
4585
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004586void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
4587 GL2Encoder *ctx = (GL2Encoder*)self;
4588 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4589 if (bufSize == 0) {
4590 if (length) *length = 0;
4591 return;
4592 }
4593
4594 // Avoid modifying |name| if |*length| < bufSize.
4595 GLint* intermediate = new GLint[bufSize];
4596 GLsizei* myLength = length ? length : new GLsizei;
4597 bool needFreeLength = length == NULL;
4598
4599 ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
4600 GLsizei writtenInts = *myLength;
4601 memcpy(params, intermediate, writtenInts * sizeof(GLint));
4602
4603 delete [] intermediate;
4604 if (needFreeLength)
4605 delete myLength;
4606}
4607
4608GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
4609 GL2Encoder *ctx = (GL2Encoder*)self;
4610 return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
4611}
4612
4613GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
4614 GL2Encoder *ctx = (GL2Encoder*)self;
4615 return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
4616}
4617
4618void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
4619 GL2Encoder *ctx = (GL2Encoder*)self;
4620 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4621 if (bufSize == 0) {
4622 if (length) *length = 0;
4623 return;
4624 }
4625
4626 // Avoid modifying |name| if |*length| < bufSize.
4627 char* intermediate = new char[bufSize];
4628 GLsizei* myLength = length ? length : new GLsizei;
4629 bool needFreeLength = length == NULL;
4630
4631 ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
4632 GLsizei writtenStrLen = *myLength;
4633 memcpy(name, intermediate, writtenStrLen + 1);
4634
4635 delete [] intermediate;
4636 if (needFreeLength)
4637 delete myLength;
4638}
4639
4640void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
4641 GL2Encoder *ctx = (GL2Encoder*)self;
4642 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4643 if (bufSize == 0) {
4644 if (length) *length = 0;
4645 return;
4646 }
4647
4648 // Avoid modifying |infoLog| if |*length| < bufSize.
4649 GLchar* intermediate = new GLchar[bufSize];
4650 GLsizei* myLength = length ? length : new GLsizei;
4651 bool needFreeLength = length == NULL;
4652
4653 ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
4654 GLsizei writtenStrLen = *myLength;
4655 memcpy(infoLog, intermediate, writtenStrLen + 1);
4656
4657 delete [] intermediate;
4658 if (needFreeLength)
4659 delete myLength;
4660}
4661
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004662void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
4663 GL2Encoder *ctx = (GL2Encoder*)self;
4664 GLClientState* state = ctx->m_state;
4665
Lingfeng Yang07289902017-01-27 12:26:19 -08004666 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004667 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4668
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004669 state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false);
4670 ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset);
4671}
4672
4673void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
4674 GL2Encoder *ctx = (GL2Encoder*)self;
4675 GLClientState* state = ctx->m_state;
4676
Lingfeng Yang07289902017-01-27 12:26:19 -08004677 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004678 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4679
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004680 state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true);
4681 ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset);
4682}
4683
4684void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004685 GL2Encoder *ctx = (GL2Encoder*)self;
4686 GLClientState* state = ctx->m_state;
4687
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004688 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4689
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004690 state->setVertexBindingDivisor(bindingindex, divisor);
4691 ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor);
4692}
4693
4694void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) {
4695 GL2Encoder *ctx = (GL2Encoder*)self;
4696 GLClientState* state = ctx->m_state;
Lingfeng Yang07289902017-01-27 12:26:19 -08004697 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004698 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004699
4700 state->setVertexAttribBinding(attribindex, bindingindex);
4701 ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex);
4702}
4703
4704void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
4705 GL2Encoder *ctx = (GL2Encoder*)self;
4706 GLClientState* state = ctx->m_state;
4707
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004708 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
4709
4710 GLint maxStride;
4711 ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
4712 SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE);
4713
4714 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4715
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004716 state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride);
4717 ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride);
4718}
4719
4720void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) {
4721 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004722 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004723
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004724 bool hasClientArrays = false;
4725 ctx->getVBOUsage(&hasClientArrays, NULL);
4726
4727 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
4728 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4729 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
4730
4731 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004732 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004733 // BufferData* buf = ctx->getBufferData(target);
4734 // if (buf) {
4735 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
4736 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004737 ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect);
4738 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004739 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
4740 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004741 ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize);
4742 }
4743}
4744
4745void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) {
4746 GL2Encoder *ctx = (GL2Encoder*)self;
4747
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004748 GLClientState* state = ctx->m_state;
4749
4750 bool hasClientArrays = false;
4751 ctx->getVBOUsage(&hasClientArrays, NULL);
4752
4753 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
4754 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4755 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
4756
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004757 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004758
4759 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004760 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004761 // BufferData* buf = ctx->getBufferData(target);
4762 // if (buf) {
4763 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
4764 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004765 ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect);
4766 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004767 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
4768 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004769 ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize);
4770 }
4771
4772}
4773
4774void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
4775 GL2Encoder *ctx = (GL2Encoder*)self;
4776 GLClientState* state = ctx->m_state;
4777
4778 SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
4779 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
4780 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
4781 SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
4782 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004783 GLint max_samples;
4784 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
4785 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004786
4787 state->setBoundTextureInternalFormat(target, internalformat);
4788 state->setBoundTextureDims(target, 0, width, height, 1);
4789 state->setBoundTextureImmutableFormat(target);
4790 state->setBoundTextureSamples(target, samples);
4791
4792 ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
4793}
4794