blob: daa972fe0c24b0d7e3503f160b8fae9a4009e796 [file] [log] [blame]
keunyoungb85b2752013-03-08 12:28:03 -08001/*
2* Copyright (C) 2011 The Android Open Source Project
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17#include "GL2Encoder.h"
Lingfeng Yang46153ab2017-01-09 13:37:22 -080018#include "GLESv2Validation.h"
19
20#include <string>
21#include <map>
22
keunyoungb85b2752013-03-08 12:28:03 -080023#include <assert.h>
24#include <ctype.h>
25
Lingfeng Yang69066602016-04-12 09:29:11 -070026#include <GLES2/gl2.h>
27#include <GLES2/gl2ext.h>
28#include <GLES2/gl2platform.h>
29
30#include <GLES3/gl3.h>
Lingfeng Yang46153ab2017-01-09 13:37:22 -080031#include <GLES3/gl31.h>
Lingfeng Yang69066602016-04-12 09:29:11 -070032
keunyoungb85b2752013-03-08 12:28:03 -080033#ifndef MIN
34#define MIN(a, b) ((a) < (b) ? (a) : (b))
35#endif
36
37static GLubyte *gVendorString= (GLubyte *) "Android";
Lingfeng Yang46153ab2017-01-09 13:37:22 -080038static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 3.0";
39static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 3.0";
Nicolas Capensfe2d51a2015-11-20 15:10:09 -050040static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external ";
keunyoungb85b2752013-03-08 12:28:03 -080041
Lingfeng Yang07289902017-01-27 12:26:19 -080042#define SET_ERROR_IF(condition, err) if((condition)) { \
keunyoungb85b2752013-03-08 12:28:03 -080043 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
Lingfeng Yang07289902017-01-27 12:26:19 -080044 ctx->setError(err); \
45 return; \
keunyoungb85b2752013-03-08 12:28:03 -080046 }
47
Lingfeng Yang07289902017-01-27 12:26:19 -080048#define SET_ERROR_WITH_MESSAGE_IF(condition, err, generator, genargs) if ((condition)) { \
49 std::string msg = generator genargs; \
50 ALOGE("%s:%s:%d GL error 0x%x\n" \
51 "Info: %s\n", __FILE__, __FUNCTION__, __LINE__, err, msg.c_str()); \
52 ctx->setError(err); \
53 return; \
54 } \
keunyoungb85b2752013-03-08 12:28:03 -080055
Lingfeng Yang07289902017-01-27 12:26:19 -080056#define RET_AND_SET_ERROR_IF(condition, err, ret) if((condition)) { \
keunyoungb85b2752013-03-08 12:28:03 -080057 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
Lingfeng Yang07289902017-01-27 12:26:19 -080058 ctx->setError(err); \
59 return ret; \
60 } \
keunyoungb85b2752013-03-08 12:28:03 -080061
Lingfeng Yang07289902017-01-27 12:26:19 -080062#define RET_AND_SET_ERROR_WITH_MESSAGE_IF(condition, err, ret, generator, genargs) if((condition)) { \
63 std::string msg = generator genargs; \
64 ALOGE("%s:%s:%d GL error 0x%x\n" \
65 "Info: %s\n", __FILE__, __FUNCTION__, __LINE__, err, msg.c_str()); \
66 ctx->setError(err); \
67 return ret; \
68 } \
keunyoungb85b2752013-03-08 12:28:03 -080069
Yahan Zhoub7f09082016-03-10 11:45:02 -080070GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
71 : gl2_encoder_context_t(stream, protocol)
keunyoungb85b2752013-03-08 12:28:03 -080072{
Lingfeng Yange6556dc2017-01-09 12:04:12 -080073 m_currMajorVersion = 2;
74 m_currMinorVersion = 0;
keunyoungb85b2752013-03-08 12:28:03 -080075 m_initialized = false;
76 m_state = NULL;
77 m_error = GL_NO_ERROR;
78 m_num_compressedTextureFormats = 0;
Lizhe Liue41f4ef2015-05-27 11:13:23 +080079 m_max_cubeMapTextureSize = 0;
80 m_max_renderBufferSize = 0;
81 m_max_textureSize = 0;
Lingfeng Yang46153ab2017-01-09 13:37:22 -080082 m_max_3d_textureSize = 0;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -080083 m_max_vertexAttribStride = 0;
keunyoungb85b2752013-03-08 12:28:03 -080084 m_compressedTextureFormats = NULL;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010085
Lingfeng Yang46153ab2017-01-09 13:37:22 -080086 m_ssbo_offset_align = 0;
87 m_ubo_offset_align = 0;
88
Lingfeng Yangde51dfb2016-10-17 22:48:59 -070089 m_drawCallFlushCount = 0;
90 m_primitiveRestartEnabled = false;
91 m_primitiveRestartIndex = 0;
92
Lingfeng Yang07289902017-01-27 12:26:19 -080093 // overrides
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010094#define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name
Lingfeng Yange6556dc2017-01-09 12:04:12 -080095#define OVERRIDE_CUSTOM(name) this-> name = &s_##name
96#define OVERRIDEWITH(name, target) do { \
97 m_##target##_enc = this-> target; \
98 this-> target = &s_##name; \
99} while(0)
100#define OVERRIDEOES(name) OVERRIDEWITH(name, name##OES)
bohu56bf82f2014-10-17 15:35:48 -0700101
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100102 OVERRIDE(glFlush);
103 OVERRIDE(glPixelStorei);
104 OVERRIDE(glGetString);
105 OVERRIDE(glBindBuffer);
106 OVERRIDE(glBufferData);
107 OVERRIDE(glBufferSubData);
108 OVERRIDE(glDeleteBuffers);
109 OVERRIDE(glDrawArrays);
110 OVERRIDE(glDrawElements);
111 OVERRIDE(glGetIntegerv);
112 OVERRIDE(glGetFloatv);
113 OVERRIDE(glGetBooleanv);
114 OVERRIDE(glVertexAttribPointer);
115 OVERRIDE(glEnableVertexAttribArray);
116 OVERRIDE(glDisableVertexAttribArray);
117 OVERRIDE(glGetVertexAttribiv);
118 OVERRIDE(glGetVertexAttribfv);
119 OVERRIDE(glGetVertexAttribPointerv);
keunyoungb85b2752013-03-08 12:28:03 -0800120
Bo Hu73568cd2015-01-20 16:29:50 -0800121 this->glShaderBinary = &s_glShaderBinary;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100122 this->glShaderSource = &s_glShaderSource;
123 this->glFinish = &s_glFinish;
keunyoungb85b2752013-03-08 12:28:03 -0800124
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100125 OVERRIDE(glGetError);
126 OVERRIDE(glLinkProgram);
127 OVERRIDE(glDeleteProgram);
128 OVERRIDE(glGetUniformiv);
129 OVERRIDE(glGetUniformfv);
130 OVERRIDE(glCreateProgram);
131 OVERRIDE(glCreateShader);
132 OVERRIDE(glDeleteShader);
133 OVERRIDE(glAttachShader);
134 OVERRIDE(glDetachShader);
135 OVERRIDE(glGetAttachedShaders);
136 OVERRIDE(glGetShaderSource);
137 OVERRIDE(glGetShaderInfoLog);
138 OVERRIDE(glGetProgramInfoLog);
139
140 OVERRIDE(glGetUniformLocation);
141 OVERRIDE(glUseProgram);
142
143 OVERRIDE(glUniform1f);
144 OVERRIDE(glUniform1fv);
145 OVERRIDE(glUniform1i);
146 OVERRIDE(glUniform1iv);
147 OVERRIDE(glUniform2f);
148 OVERRIDE(glUniform2fv);
149 OVERRIDE(glUniform2i);
150 OVERRIDE(glUniform2iv);
151 OVERRIDE(glUniform3f);
152 OVERRIDE(glUniform3fv);
153 OVERRIDE(glUniform3i);
154 OVERRIDE(glUniform3iv);
155 OVERRIDE(glUniform4f);
156 OVERRIDE(glUniform4fv);
157 OVERRIDE(glUniform4i);
158 OVERRIDE(glUniform4iv);
159 OVERRIDE(glUniformMatrix2fv);
160 OVERRIDE(glUniformMatrix3fv);
161 OVERRIDE(glUniformMatrix4fv);
162
163 OVERRIDE(glActiveTexture);
164 OVERRIDE(glBindTexture);
165 OVERRIDE(glDeleteTextures);
166 OVERRIDE(glGetTexParameterfv);
167 OVERRIDE(glGetTexParameteriv);
168 OVERRIDE(glTexParameterf);
169 OVERRIDE(glTexParameterfv);
170 OVERRIDE(glTexParameteri);
171 OVERRIDE(glTexParameteriv);
bohu26a92982014-11-25 16:50:37 -0800172 OVERRIDE(glTexImage2D);
Yahan Zhou2a208292016-06-22 15:36:04 -0700173 OVERRIDE(glTexSubImage2D);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -0700174 OVERRIDE(glCopyTexImage2D);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700175
176 OVERRIDE(glGenRenderbuffers);
177 OVERRIDE(glDeleteRenderbuffers);
178 OVERRIDE(glBindRenderbuffer);
Lingfeng Yang69066602016-04-12 09:29:11 -0700179 OVERRIDE(glRenderbufferStorage);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700180 OVERRIDE(glFramebufferRenderbuffer);
181
182 OVERRIDE(glGenFramebuffers);
183 OVERRIDE(glDeleteFramebuffers);
184 OVERRIDE(glBindFramebuffer);
185 OVERRIDE(glFramebufferTexture2D);
186 OVERRIDE(glFramebufferTexture3DOES);
187 OVERRIDE(glGetFramebufferAttachmentParameteriv);
Lingfeng Yang69066602016-04-12 09:29:11 -0700188
189 OVERRIDE(glCheckFramebufferStatus);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800190
191 OVERRIDE(glGenVertexArrays);
192 OVERRIDE(glDeleteVertexArrays);
193 OVERRIDE(glBindVertexArray);
194 OVERRIDEOES(glGenVertexArrays);
195 OVERRIDEOES(glDeleteVertexArrays);
196 OVERRIDEOES(glBindVertexArray);
197
198 OVERRIDE_CUSTOM(glMapBufferRange);
199 OVERRIDE_CUSTOM(glUnmapBuffer);
200 OVERRIDE_CUSTOM(glFlushMappedBufferRange);
201
202 OVERRIDE(glCompressedTexImage2D);
203 OVERRIDE(glCompressedTexSubImage2D);
204
205 OVERRIDE(glBindBufferRange);
206 OVERRIDE(glBindBufferBase);
207
208 OVERRIDE(glCopyBufferSubData);
209
210 OVERRIDE(glGetBufferParameteriv);
211 OVERRIDE(glGetBufferParameteri64v);
212 OVERRIDE(glGetBufferPointerv);
213
214 OVERRIDE_CUSTOM(glGetUniformIndices);
215
216 OVERRIDE(glUniform1ui);
217 OVERRIDE(glUniform2ui);
218 OVERRIDE(glUniform3ui);
219 OVERRIDE(glUniform4ui);
220 OVERRIDE(glUniform1uiv);
221 OVERRIDE(glUniform2uiv);
222 OVERRIDE(glUniform3uiv);
223 OVERRIDE(glUniform4uiv);
224 OVERRIDE(glUniformMatrix2x3fv);
225 OVERRIDE(glUniformMatrix3x2fv);
226 OVERRIDE(glUniformMatrix2x4fv);
227 OVERRIDE(glUniformMatrix4x2fv);
228 OVERRIDE(glUniformMatrix3x4fv);
229 OVERRIDE(glUniformMatrix4x3fv);
230
231 OVERRIDE(glGetUniformuiv);
232 OVERRIDE(glGetActiveUniformBlockiv);
233
234 OVERRIDE(glGetVertexAttribIiv);
235 OVERRIDE(glGetVertexAttribIuiv);
236
237 OVERRIDE_CUSTOM(glVertexAttribIPointer);
238
239 OVERRIDE(glVertexAttribDivisor);
240
241 OVERRIDE(glRenderbufferStorageMultisample);
242 OVERRIDE(glDrawBuffers);
243 OVERRIDE(glReadBuffer);
244 OVERRIDE(glFramebufferTextureLayer);
245 OVERRIDE(glTexStorage2D);
246
247 OVERRIDE_CUSTOM(glTransformFeedbackVaryings);
248 OVERRIDE(glBeginTransformFeedback);
249 OVERRIDE(glEndTransformFeedback);
250 OVERRIDE(glPauseTransformFeedback);
251 OVERRIDE(glResumeTransformFeedback);
252
253 OVERRIDE(glTexImage3D);
254 OVERRIDE(glTexSubImage3D);
255 OVERRIDE(glTexStorage3D);
256 OVERRIDE(glCompressedTexImage3D);
257 OVERRIDE(glCompressedTexSubImage3D);
258
259 OVERRIDE(glDrawArraysInstanced);
260 OVERRIDE_CUSTOM(glDrawElementsInstanced);
261 OVERRIDE_CUSTOM(glDrawRangeElements);
262
263 OVERRIDE_CUSTOM(glGetStringi);
264 OVERRIDE(glGetProgramBinary);
265 OVERRIDE(glReadPixels);
266
267 OVERRIDE(glEnable);
268 OVERRIDE(glDisable);
269 OVERRIDE(glClearBufferiv);
270 OVERRIDE(glClearBufferuiv);
271 OVERRIDE(glClearBufferfv);
272 OVERRIDE(glBlitFramebuffer);
273 OVERRIDE_CUSTOM(glGetInternalformativ);
274
275 OVERRIDE(glGenerateMipmap);
276
277 OVERRIDE(glBindSampler);
278
Lingfeng Yangf000ab42017-01-11 18:31:38 -0800279 OVERRIDE_CUSTOM(glFenceSync);
280 OVERRIDE_CUSTOM(glClientWaitSync);
281 OVERRIDE_CUSTOM(glWaitSync);
282 OVERRIDE_CUSTOM(glDeleteSync);
283 OVERRIDE_CUSTOM(glIsSync);
284 OVERRIDE_CUSTOM(glGetSynciv);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800285
286 OVERRIDE(glGetIntegeri_v);
287 OVERRIDE(glGetInteger64i_v);
288
289 OVERRIDE(glGetShaderiv);
290
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800291 OVERRIDE(glActiveShaderProgram);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800292 OVERRIDE_CUSTOM(glCreateShaderProgramv);
293 OVERRIDE(glProgramUniform1f);
294 OVERRIDE(glProgramUniform1fv);
295 OVERRIDE(glProgramUniform1i);
296 OVERRIDE(glProgramUniform1iv);
297 OVERRIDE(glProgramUniform1ui);
298 OVERRIDE(glProgramUniform1uiv);
299 OVERRIDE(glProgramUniform2f);
300 OVERRIDE(glProgramUniform2fv);
301 OVERRIDE(glProgramUniform2i);
302 OVERRIDE(glProgramUniform2iv);
303 OVERRIDE(glProgramUniform2ui);
304 OVERRIDE(glProgramUniform2uiv);
305 OVERRIDE(glProgramUniform3f);
306 OVERRIDE(glProgramUniform3fv);
307 OVERRIDE(glProgramUniform3i);
308 OVERRIDE(glProgramUniform3iv);
309 OVERRIDE(glProgramUniform3ui);
310 OVERRIDE(glProgramUniform3uiv);
311 OVERRIDE(glProgramUniform4f);
312 OVERRIDE(glProgramUniform4fv);
313 OVERRIDE(glProgramUniform4i);
314 OVERRIDE(glProgramUniform4iv);
315 OVERRIDE(glProgramUniform4ui);
316 OVERRIDE(glProgramUniform4uiv);
317 OVERRIDE(glProgramUniformMatrix2fv);
318 OVERRIDE(glProgramUniformMatrix2x3fv);
319 OVERRIDE(glProgramUniformMatrix2x4fv);
320 OVERRIDE(glProgramUniformMatrix3fv);
321 OVERRIDE(glProgramUniformMatrix3x2fv);
322 OVERRIDE(glProgramUniformMatrix3x4fv);
323 OVERRIDE(glProgramUniformMatrix4fv);
324 OVERRIDE(glProgramUniformMatrix4x2fv);
325 OVERRIDE(glProgramUniformMatrix4x3fv);
326
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800327 OVERRIDE(glProgramParameteri);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800328 OVERRIDE(glUseProgramStages);
329 OVERRIDE(glBindProgramPipeline);
330
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800331 OVERRIDE(glGetProgramResourceiv);
332 OVERRIDE(glGetProgramResourceIndex);
333 OVERRIDE(glGetProgramResourceLocation);
334 OVERRIDE(glGetProgramResourceName);
335 OVERRIDE(glGetProgramPipelineInfoLog);
336
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800337 OVERRIDE(glVertexAttribFormat);
338 OVERRIDE(glVertexAttribIFormat);
339 OVERRIDE(glVertexBindingDivisor);
340 OVERRIDE(glVertexAttribBinding);
341 OVERRIDE(glBindVertexBuffer);
342
343 OVERRIDE_CUSTOM(glDrawArraysIndirect);
344 OVERRIDE_CUSTOM(glDrawElementsIndirect);
345
346 OVERRIDE(glTexStorage2DMultisample);
keunyoungb85b2752013-03-08 12:28:03 -0800347}
348
349GL2Encoder::~GL2Encoder()
350{
351 delete m_compressedTextureFormats;
352}
353
354GLenum GL2Encoder::s_glGetError(void * self)
355{
356 GL2Encoder *ctx = (GL2Encoder *)self;
357 GLenum err = ctx->getError();
358 if(err != GL_NO_ERROR) {
359 ctx->setError(GL_NO_ERROR);
360 return err;
361 }
362
363 return ctx->m_glGetError_enc(self);
Yahan Zhouae30fe82016-08-10 21:15:45 +0000364
keunyoungb85b2752013-03-08 12:28:03 -0800365}
366
367void GL2Encoder::s_glFlush(void *self)
368{
369 GL2Encoder *ctx = (GL2Encoder *) self;
370 ctx->m_glFlush_enc(self);
371 ctx->m_stream->flush();
372}
373
374const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
375{
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800376 GL2Encoder *ctx = (GL2Encoder *)self;
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100377
keunyoungb85b2752013-03-08 12:28:03 -0800378 GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800379 RET_AND_SET_ERROR_IF(
380 name != GL_VENDOR &&
381 name != GL_RENDERER &&
382 name != GL_VERSION &&
383 name != GL_EXTENSIONS,
384 GL_INVALID_ENUM,
385 retval);
keunyoungb85b2752013-03-08 12:28:03 -0800386 switch(name) {
387 case GL_VENDOR:
388 retval = gVendorString;
389 break;
390 case GL_RENDERER:
391 retval = gRendererString;
392 break;
393 case GL_VERSION:
394 retval = gVersionString;
395 break;
396 case GL_EXTENSIONS:
397 retval = gExtensionsString;
398 break;
399 }
400 return retval;
401}
402
403void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
404{
405 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800406 SET_ERROR_IF(!GLESv2Validation::pixelStoreParam(ctx, param), GL_INVALID_ENUM);
407 SET_ERROR_IF(!GLESv2Validation::pixelStoreValue(param, value), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800408 ctx->m_glPixelStorei_enc(ctx, param, value);
409 assert(ctx->m_state != NULL);
410 ctx->m_state->setPixelStore(param, value);
411}
keunyoungb85b2752013-03-08 12:28:03 -0800412void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
413{
414 GL2Encoder *ctx = (GL2Encoder *) self;
415 assert(ctx->m_state != NULL);
416 ctx->m_state->bindBuffer(target, id);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800417 ctx->m_state->addBuffer(id);
keunyoungb85b2752013-03-08 12:28:03 -0800418 // TODO set error state if needed;
419 ctx->m_glBindBuffer_enc(self, target, id);
420}
421
422void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
423{
424 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800425 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800426 GLuint bufferId = ctx->m_state->getBuffer(target);
427 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
428 SET_ERROR_IF(size<0, GL_INVALID_VALUE);
429
430 ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800431 ctx->m_shared->setBufferUsage(bufferId, usage);
keunyoungb85b2752013-03-08 12:28:03 -0800432 ctx->m_glBufferData_enc(self, target, size, data, usage);
433}
434
435void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
436{
437 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800438 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800439 GLuint bufferId = ctx->m_state->getBuffer(target);
440 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800441 SET_ERROR_IF(ctx->isBufferTargetMapped(target), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800442
443 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
444 SET_ERROR_IF(res, res);
445
446 ctx->m_glBufferSubData_enc(self, target, offset, size, data);
447}
448
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800449void GL2Encoder::s_glGenBuffers(void* self, GLsizei n, GLuint* buffers) {
450 GL2Encoder *ctx = (GL2Encoder *) self;
451 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
452 ctx->m_glGenBuffers_enc(self, n, buffers);
453 for (int i = 0; i < n; i++) {
454 ctx->m_state->addBuffer(buffers[i]);
455 }
456}
457
keunyoungb85b2752013-03-08 12:28:03 -0800458void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
459{
460 GL2Encoder *ctx = (GL2Encoder *) self;
461 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
462 for (int i=0; i<n; i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800463 // Technically if the buffer is mapped, we should unmap it, but we won't
464 // use it anymore after this :)
keunyoungb85b2752013-03-08 12:28:03 -0800465 ctx->m_shared->deleteBufferData(buffers[i]);
bohub0f0cdf2014-11-06 18:08:07 -0800466 ctx->m_state->unBindBuffer(buffers[i]);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800467 ctx->m_state->removeBuffer(buffers[i]);
keunyoungb85b2752013-03-08 12:28:03 -0800468 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
469 }
470}
471
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700472static bool isValidVertexAttribIndex(void *self, GLuint indx)
473{
Lingfeng Yang07289902017-01-27 12:26:19 -0800474 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700475 GLint maxIndex;
476 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
477 return indx < maxIndex;
478}
479
Lingfeng Yang07289902017-01-27 12:26:19 -0800480#define VALIDATE_VERTEX_ATTRIB_INDEX(index) \
481 SET_ERROR_WITH_MESSAGE_IF( \
482 !isValidVertexAttribIndex(self, index), GL_INVALID_VALUE, \
483 GLESv2Validation::vertexAttribIndexRangeErrorMsg, (ctx, index)); \
484
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100485void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
keunyoungb85b2752013-03-08 12:28:03 -0800486{
487 GL2Encoder *ctx = (GL2Encoder *)self;
488 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -0800489 VALIDATE_VERTEX_ATTRIB_INDEX(indx);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700490 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800491 SET_ERROR_IF(!GLESv2Validation::vertexAttribType(ctx, type), GL_INVALID_ENUM);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700492 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800493 SET_ERROR_IF((type == GL_INT_2_10_10_10_REV ||
494 type == GL_UNSIGNED_INT_2_10_10_10_REV) &&
495 size != 4,
496 GL_INVALID_OPERATION);
497 ctx->m_state->setVertexAttribBinding(indx, indx);
498 ctx->m_state->setVertexAttribFormat(indx, size, type, normalized, 0, false);
499
500 GLsizei effectiveStride = stride;
501 if (stride == 0) {
502 effectiveStride = glSizeof(type) * size;
503 switch (type) {
504 case GL_INT_2_10_10_10_REV:
505 case GL_UNSIGNED_INT_2_10_10_10_REV:
506 effectiveStride /= 4;
507 break;
508 default:
509 break;
510 }
511 }
512
513 ctx->m_state->bindIndexedBuffer(0, indx, ctx->m_state->currentArrayVbo(), (uintptr_t)ptr, 0, stride, effectiveStride);
514
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800515 if (ctx->m_state->currentArrayVbo() != 0) {
516 ctx->glVertexAttribPointerOffset(ctx, indx, size, type, normalized, stride, (uintptr_t)ptr);
517 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800518 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && ptr, GL_INVALID_OPERATION);
519 // wait for client-array handler
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800520 }
keunyoungb85b2752013-03-08 12:28:03 -0800521}
522
523void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
524{
525 GL2Encoder *ctx = (GL2Encoder *) self;
526 assert(ctx->m_state != NULL);
527 GLClientState* state = ctx->m_state;
528
529 switch (param) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800530 case GL_MAJOR_VERSION:
531 *ptr = ctx->m_currMajorVersion;
532 break;
533 case GL_MINOR_VERSION:
534 *ptr = ctx->m_currMinorVersion;
535 break;
keunyoungb85b2752013-03-08 12:28:03 -0800536 case GL_NUM_SHADER_BINARY_FORMATS:
537 *ptr = 0;
538 break;
539 case GL_SHADER_BINARY_FORMATS:
540 // do nothing
541 break;
542
543 case GL_COMPRESSED_TEXTURE_FORMATS: {
544 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
545 if (ctx->m_num_compressedTextureFormats > 0 &&
546 compressedTextureFormats != NULL) {
547 memcpy(ptr, compressedTextureFormats,
548 ctx->m_num_compressedTextureFormats * sizeof(GLint));
549 }
550 break;
551 }
552
553 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
554 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
555 case GL_MAX_TEXTURE_IMAGE_UNITS:
556 ctx->m_glGetIntegerv_enc(self, param, ptr);
557 *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
558 break;
559
560 case GL_TEXTURE_BINDING_2D:
561 *ptr = state->getBoundTexture(GL_TEXTURE_2D);
562 break;
563 case GL_TEXTURE_BINDING_EXTERNAL_OES:
564 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
565 break;
566
Lingfeng Yangb0176982016-03-01 21:27:49 -0800567 case GL_MAX_VERTEX_ATTRIBS:
568 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
569 ctx->m_glGetIntegerv_enc(self, param, ptr);
570 ctx->m_state->setMaxVertexAttribs(*ptr);
Yahan Zhoua5c36842016-06-01 12:49:39 -0700571 }
572 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800573 case GL_MAX_VERTEX_ATTRIB_STRIDE:
574 if (ctx->m_max_vertexAttribStride != 0) {
575 *ptr = ctx->m_max_vertexAttribStride;
576 } else {
577 ctx->m_glGetIntegerv_enc(self, param, ptr);
578 ctx->m_max_vertexAttribStride = *ptr;
579 }
580 break;
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800581 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
582 if (ctx->m_max_cubeMapTextureSize != 0) {
583 *ptr = ctx->m_max_cubeMapTextureSize;
584 } else {
585 ctx->m_glGetIntegerv_enc(self, param, ptr);
586 ctx->m_max_cubeMapTextureSize = *ptr;
587 }
588 break;
589 case GL_MAX_RENDERBUFFER_SIZE:
590 if (ctx->m_max_renderBufferSize != 0) {
591 *ptr = ctx->m_max_renderBufferSize;
592 } else {
593 ctx->m_glGetIntegerv_enc(self, param, ptr);
594 ctx->m_max_renderBufferSize = *ptr;
595 }
596 break;
597 case GL_MAX_TEXTURE_SIZE:
598 if (ctx->m_max_textureSize != 0) {
599 *ptr = ctx->m_max_textureSize;
600 } else {
601 ctx->m_glGetIntegerv_enc(self, param, ptr);
602 ctx->m_max_textureSize = *ptr;
Lingfeng Yangb0176982016-03-01 21:27:49 -0800603 }
604 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800605 case GL_MAX_3D_TEXTURE_SIZE:
606 if (ctx->m_max_3d_textureSize != 0) {
607 *ptr = ctx->m_max_3d_textureSize;
608 } else {
609 ctx->m_glGetIntegerv_enc(self, param, ptr);
610 ctx->m_max_3d_textureSize = *ptr;
611 }
612 break;
613 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
614 if (ctx->m_ssbo_offset_align != 0) {
615 *ptr = ctx->m_ssbo_offset_align;
616 } else {
617 ctx->m_glGetIntegerv_enc(self, param, ptr);
618 ctx->m_ssbo_offset_align = *ptr;
619 }
620 break;
621 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
622 if (ctx->m_ubo_offset_align != 0) {
623 *ptr = ctx->m_ubo_offset_align;
624 } else {
625 ctx->m_glGetIntegerv_enc(self, param, ptr);
626 ctx->m_ubo_offset_align = *ptr;
627 }
628 break;
629 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
630 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
631 case GL_MAX_SAMPLES:
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800632 case GL_MAX_COLOR_TEXTURE_SAMPLES:
633 case GL_MAX_INTEGER_SAMPLES:
634 case GL_MAX_DEPTH_TEXTURE_SAMPLES:
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800635 *ptr = 4;
636 break;
keunyoungb85b2752013-03-08 12:28:03 -0800637 default:
638 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
639 ctx->m_glGetIntegerv_enc(self, param, ptr);
640 }
641 break;
642 }
643}
644
645
646void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
647{
648 GL2Encoder *ctx = (GL2Encoder *)self;
649 assert(ctx->m_state != NULL);
650 GLClientState* state = ctx->m_state;
651
652 switch (param) {
653 case GL_NUM_SHADER_BINARY_FORMATS:
654 *ptr = 0;
655 break;
656 case GL_SHADER_BINARY_FORMATS:
657 // do nothing
658 break;
659
660 case GL_COMPRESSED_TEXTURE_FORMATS: {
661 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
662 if (ctx->m_num_compressedTextureFormats > 0 &&
663 compressedTextureFormats != NULL) {
664 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
665 ptr[i] = (GLfloat) compressedTextureFormats[i];
666 }
667 }
668 break;
669 }
670
671 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
672 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
673 case GL_MAX_TEXTURE_IMAGE_UNITS:
674 ctx->m_glGetFloatv_enc(self, param, ptr);
675 *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
676 break;
677
678 case GL_TEXTURE_BINDING_2D:
679 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
680 break;
681 case GL_TEXTURE_BINDING_EXTERNAL_OES:
682 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
683 break;
684
685 default:
686 if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
687 ctx->m_glGetFloatv_enc(self, param, ptr);
688 }
689 break;
690 }
691}
692
693
694void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
695{
696 GL2Encoder *ctx = (GL2Encoder *)self;
697 assert(ctx->m_state != NULL);
698 GLClientState* state = ctx->m_state;
699
700 switch (param) {
701 case GL_NUM_SHADER_BINARY_FORMATS:
702 *ptr = GL_FALSE;
703 break;
704 case GL_SHADER_BINARY_FORMATS:
705 // do nothing
706 break;
707
708 case GL_COMPRESSED_TEXTURE_FORMATS: {
709 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
710 if (ctx->m_num_compressedTextureFormats > 0 &&
711 compressedTextureFormats != NULL) {
712 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
713 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
714 }
715 }
716 break;
717 }
718
719 case GL_TEXTURE_BINDING_2D:
720 *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
721 break;
722 case GL_TEXTURE_BINDING_EXTERNAL_OES:
723 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
724 ? GL_TRUE : GL_FALSE;
725 break;
726
727 default:
728 if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
729 ctx->m_glGetBooleanv_enc(self, param, ptr);
730 }
bohu05101d22014-11-17 16:28:42 -0800731 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
keunyoungb85b2752013-03-08 12:28:03 -0800732 break;
733 }
734}
735
736
737void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
738{
739 GL2Encoder *ctx = (GL2Encoder *)self;
740 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -0800741 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800742 ctx->m_glEnableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800743 ctx->m_state->enable(index, 1);
744}
745
746void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
747{
748 GL2Encoder *ctx = (GL2Encoder *)self;
749 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -0800750 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800751 ctx->m_glDisableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800752 ctx->m_state->enable(index, 0);
753}
754
755
756void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
757{
758 GL2Encoder *ctx = (GL2Encoder *)self;
759 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700760 GLint maxIndex;
761 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
762 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800763
764 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
765 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
766 }
767}
768
769void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
770{
771 GL2Encoder *ctx = (GL2Encoder *)self;
772 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700773 GLint maxIndex;
774 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
775 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800776
777 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
778 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
779 }
780}
781
782void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
783{
784 GL2Encoder *ctx = (GL2Encoder *)self;
785 if (ctx->m_state == NULL) return;
Lingfeng Yang5e100432016-04-08 12:46:42 -0700786 GLint maxIndex;
787 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
788 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
789 SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100790 (void)pname;
791
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800792 *pointer = (GLvoid*)(ctx->m_state->getCurrAttributeBindingInfo(index).offset);
keunyoungb85b2752013-03-08 12:28:03 -0800793}
794
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700795void GL2Encoder::calcIndexRange(const void* indices,
796 GLenum type,
797 GLsizei count,
798 int* minIndex_out,
799 int* maxIndex_out) {
800 switch(type) {
801 case GL_BYTE:
802 case GL_UNSIGNED_BYTE:
803 GLUtils::minmaxExcept(
804 (unsigned char *)indices, count,
805 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800806 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned char>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700807 break;
808 case GL_SHORT:
809 case GL_UNSIGNED_SHORT:
810 GLUtils::minmaxExcept(
811 (unsigned short *)indices, count,
812 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800813 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned short>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700814 break;
815 case GL_INT:
816 case GL_UNSIGNED_INT:
817 GLUtils::minmaxExcept(
818 (unsigned int *)indices, count,
819 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800820 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned int>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700821 break;
822 default:
823 ALOGE("unsupported index buffer type %d\n", type);
824 }
825}
826
827void* GL2Encoder::recenterIndices(const void* src,
828 GLenum type,
829 GLsizei count,
830 int minIndex) {
831
832 void* adjustedIndices = (void*)src;
833
834 if (minIndex != 0) {
835 adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count);
836 switch(type) {
837 case GL_BYTE:
838 case GL_UNSIGNED_BYTE:
839 GLUtils::shiftIndicesExcept(
840 (unsigned char *)src,
841 (unsigned char *)adjustedIndices,
842 count, -minIndex,
843 m_primitiveRestartEnabled,
844 (unsigned char)m_primitiveRestartIndex);
845 break;
846 case GL_SHORT:
847 case GL_UNSIGNED_SHORT:
848 GLUtils::shiftIndicesExcept(
849 (unsigned short *)src,
850 (unsigned short *)adjustedIndices,
851 count, -minIndex,
852 m_primitiveRestartEnabled,
853 (unsigned short)m_primitiveRestartIndex);
854 break;
855 case GL_INT:
856 case GL_UNSIGNED_INT:
857 GLUtils::shiftIndicesExcept(
858 (unsigned int *)src,
859 (unsigned int *)adjustedIndices,
860 count, -minIndex,
861 m_primitiveRestartEnabled,
862 (unsigned int)m_primitiveRestartIndex);
863 break;
864 default:
865 ALOGE("unsupported index buffer type %d\n", type);
866 }
867 }
868
869 return adjustedIndices;
870}
871
872void GL2Encoder::getBufferIndexRange(BufferData* buf,
873 const void* dataWithOffset,
874 GLenum type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -0800875 size_t count,
876 size_t offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700877 int* minIndex_out,
878 int* maxIndex_out) {
879
880 if (buf->m_indexRangeCache.findRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -0800881 type, offset, count,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700882 m_primitiveRestartEnabled,
883 minIndex_out,
884 maxIndex_out)) {
885 return;
886 }
887
888 calcIndexRange(dataWithOffset, type, count, minIndex_out, maxIndex_out);
889
890 buf->m_indexRangeCache.addRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -0800891 type, offset, count, m_primitiveRestartEnabled,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700892 *minIndex_out, *maxIndex_out);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800893
894 ALOGV("%s: got range [%u %u] pr? %d", __FUNCTION__, *minIndex_out, *maxIndex_out, m_primitiveRestartEnabled);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700895}
keunyoungb85b2752013-03-08 12:28:03 -0800896
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800897// For detecting legacy usage of glVertexAttribPointer
898void GL2Encoder::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) const {
899 if (hasClientArrays) *hasClientArrays = false;
900 if (hasVBOs) *hasVBOs = false;
901
902 for (int i = 0; i < m_state->nLocations(); i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800903 const GLClientState::VertexAttribState& state = m_state->getState(i);
904 if (state.enabled) {
905 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
906 GLuint bufferObject = curr_binding.buffer;
907 if (bufferObject == 0 && curr_binding.offset && hasClientArrays) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800908 *hasClientArrays = true;
909 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800910 if (bufferObject != 0 && hasVBOs) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800911 *hasVBOs = true;
912 }
913 }
914 }
915}
916
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800917void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count, bool hasClientArrays, GLsizei primcount)
keunyoungb85b2752013-03-08 12:28:03 -0800918{
919 assert(m_state);
920
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800921 GLuint currentVao = m_state->currentVertexArrayObject();
Lingfeng Yang398162b2016-05-26 14:18:33 -0700922 GLuint lastBoundVbo = m_state->currentArrayVbo();
keunyoungb85b2752013-03-08 12:28:03 -0800923 for (int i = 0; i < m_state->nLocations(); i++) {
924 bool enableDirty;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800925 const GLClientState::VertexAttribState& state = m_state->getStateAndEnableDirty(i, &enableDirty);
keunyoungb85b2752013-03-08 12:28:03 -0800926
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800927 if (!enableDirty && !state.enabled) {
keunyoungb85b2752013-03-08 12:28:03 -0800928 continue;
929 }
930
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800931 if (state.enabled) {
932 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
933 GLuint bufferObject = curr_binding.buffer;
934 if (hasClientArrays && lastBoundVbo != bufferObject) {
935 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, bufferObject);
936 lastBoundVbo = bufferObject;
Lingfeng Yang398162b2016-05-26 14:18:33 -0700937 }
keunyoungb85b2752013-03-08 12:28:03 -0800938
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800939 int divisor = curr_binding.divisor;
940 int stride = curr_binding.stride;
941 int effectiveStride = curr_binding.effectiveStride;
942 uintptr_t offset = curr_binding.offset;
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)) {
2098 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2099 m_state->getBoundTexture(
2100 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)));
2101 }
keunyoungb85b2752013-03-08 12:28:03 -08002102}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002103
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002104void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2105 m_state->setBoundEGLImage(target, eglImage);
2106}
2107
2108
2109GLuint GL2Encoder::boundBuffer(GLenum target) const {
2110 return m_state->getBuffer(target);
2111}
2112
2113BufferData* GL2Encoder::getBufferData(GLenum target) const {
2114 GLuint bufferId = m_state->getBuffer(target);
2115 if (!bufferId) return NULL;
2116 return m_shared->getBufferData(bufferId);
2117}
2118
2119BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2120 if (!bufferId) return NULL;
2121 return m_shared->getBufferData(bufferId);
2122}
2123
2124bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2125 return m_shared->getBufferData(buffer)->m_mapped;
2126}
2127
2128bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2129 BufferData* buf = getBufferData(target);
2130 if (!buf) return false;
2131 return buf->m_mapped;
2132}
2133
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002134void GL2Encoder::s_glGenRenderbuffers(void* self,
2135 GLsizei n, GLuint* renderbuffers) {
2136 GL2Encoder* ctx = (GL2Encoder*)self;
2137 GLClientState* state = ctx->m_state;
2138
2139 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2140
2141 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2142 state->addRenderbuffers(n, renderbuffers);
2143}
2144
2145void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2146 GLsizei n, const GLuint* renderbuffers) {
2147 GL2Encoder* ctx = (GL2Encoder*)self;
2148 GLClientState* state = ctx->m_state;
2149
2150 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2151
2152 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002153
2154 // Nope, lets just leak those for now.
2155 // The spec has an *amazingly* convoluted set of conditions for when
2156 // render buffers are actually deleted:
2157 // 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.
2158 //
2159 // 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***
2160 //
2161 // So, just detach this one from the bound FBO, and ignore the rest.
2162 for (int i = 0; i < n; i++) {
2163 state->detachRbo(renderbuffers[i]);
2164 }
2165 // state->removeRenderbuffers(n, renderbuffers);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002166}
2167
2168void GL2Encoder::s_glBindRenderbuffer(void* self,
2169 GLenum target, GLuint renderbuffer) {
2170 GL2Encoder* ctx = (GL2Encoder*)self;
2171 GLClientState* state = ctx->m_state;
2172
2173 SET_ERROR_IF((target != GL_RENDERBUFFER),
2174 GL_INVALID_ENUM);
2175
2176 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2177 state->bindRenderbuffer(target, renderbuffer);
2178}
2179
Lingfeng Yang69066602016-04-12 09:29:11 -07002180void GL2Encoder::s_glRenderbufferStorage(void* self,
2181 GLenum target, GLenum internalformat,
2182 GLsizei width, GLsizei height) {
2183 GL2Encoder* ctx = (GL2Encoder*) self;
2184 GLClientState* state = ctx->m_state;
2185
2186 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002187 SET_ERROR_IF(
2188 !GLESv2Validation::rboFormat(ctx, internalformat),
2189 GL_INVALID_ENUM);
Lingfeng Yang69066602016-04-12 09:29:11 -07002190
2191 state->setBoundRenderbufferFormat(internalformat);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002192 state->setBoundRenderbufferSamples(0);
2193
Lingfeng Yang69066602016-04-12 09:29:11 -07002194 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
2195 width, height);
2196}
2197
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002198void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
2199 GLenum target, GLenum attachment,
2200 GLenum renderbuffertarget, GLuint renderbuffer) {
2201 GL2Encoder* ctx = (GL2Encoder*)self;
2202 GLClientState* state = ctx->m_state;
2203
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002204 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2205 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2206 state->attachRbo(target, attachment, renderbuffer);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002207
2208 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
2209}
2210
2211void GL2Encoder::s_glGenFramebuffers(void* self,
2212 GLsizei n, GLuint* framebuffers) {
2213 GL2Encoder* ctx = (GL2Encoder*)self;
2214 GLClientState* state = ctx->m_state;
2215
2216 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2217
2218 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2219 state->addFramebuffers(n, framebuffers);
2220}
2221
2222void GL2Encoder::s_glDeleteFramebuffers(void* self,
2223 GLsizei n, const GLuint* framebuffers) {
2224 GL2Encoder* ctx = (GL2Encoder*)self;
2225 GLClientState* state = ctx->m_state;
2226
2227 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2228
2229 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2230 state->removeFramebuffers(n, framebuffers);
2231}
2232
2233void GL2Encoder::s_glBindFramebuffer(void* self,
2234 GLenum target, GLuint framebuffer) {
2235 GL2Encoder* ctx = (GL2Encoder*)self;
2236 GLClientState* state = ctx->m_state;
2237
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002238 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002239
2240 state->bindFramebuffer(target, framebuffer);
2241
2242 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
2243}
2244
2245void GL2Encoder::s_glFramebufferTexture2D(void* self,
2246 GLenum target, GLenum attachment,
2247 GLenum textarget, GLuint texture, GLint level) {
2248 GL2Encoder* ctx = (GL2Encoder*)self;
2249 GLClientState* state = ctx->m_state;
2250
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002251 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2252 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2253 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002254
2255 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
2256}
2257
2258void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2259 GLenum target, GLenum attachment,
2260 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2261 GL2Encoder* ctx = (GL2Encoder*)self;
2262 GLClientState* state = ctx->m_state;
2263
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002264 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002265
2266 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2267}
2268
2269void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2270 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2271 GL2Encoder* ctx = (GL2Encoder*)self;
2272 const GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002273 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2274 SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2275 pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE &&
2276 !state->attachmentHasObject(target, attachment),
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002277 GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002278 SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL ||
2279 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE ||
2280 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) &&
2281 (!state->attachmentHasObject(target, attachment) ||
2282 state->getBoundFramebufferAttachmentType(target, attachment) !=
2283 FBO_ATTACHMENT_TEXTURE),
2284 !state->attachmentHasObject(target, attachment) ?
2285 GL_INVALID_OPERATION : GL_INVALID_ENUM);
2286 SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2287 pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2288 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
2289 state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
2290 GL_INVALID_OPERATION);
2291 SET_ERROR_IF(state->boundFramebuffer(target) &&
2292 (attachment == GL_BACK ||
2293 attachment == GL_FRONT),
2294 GL_INVALID_OPERATION);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002295 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
2296}
Lingfeng Yang69066602016-04-12 09:29:11 -07002297
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002298bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state,
Lingfeng Yang69066602016-04-12 09:29:11 -07002299 GLenum attachment) const {
2300 FboFormatInfo fbo_format_info;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002301 state->getBoundFramebufferFormat(target, attachment, &fbo_format_info);
Lingfeng Yang69066602016-04-12 09:29:11 -07002302
2303 bool res;
2304 switch (fbo_format_info.type) {
2305 case FBO_ATTACHMENT_RENDERBUFFER:
2306 switch (fbo_format_info.rb_format) {
2307 case GL_R16F:
2308 case GL_RG16F:
Lingfeng Yang69066602016-04-12 09:29:11 -07002309 case GL_RGBA16F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002310 case GL_R32F:
2311 case GL_RG32F:
2312 case GL_RGBA32F:
2313 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002314 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002315 break;
2316 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002317 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang69066602016-04-12 09:29:11 -07002318 break;
2319 case GL_STENCIL_INDEX8:
2320 if (attachment == GL_STENCIL_ATTACHMENT) {
2321 res = true;
2322 } else {
2323 res = false;
2324 }
2325 break;
2326 default:
2327 res = true;
2328 }
2329 break;
2330 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002331 switch (fbo_format_info.tex_internalformat) {
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002332 case GL_R16F:
2333 case GL_RG16F:
2334 case GL_RGBA16F:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002335 case GL_R32F:
2336 case GL_RG32F:
2337 case GL_RGBA32F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002338 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002339 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002340 break;
2341 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002342 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002343 break;
2344 case GL_RED:
2345 case GL_RG:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002346 case GL_SRGB8:
2347 case GL_RGB32UI:
2348 case GL_RGB16UI:
2349 case GL_RGB8UI:
2350 case GL_RGB32I:
2351 case GL_RGB16I:
2352 case GL_RGB8I:
2353 case GL_R8_SNORM:
2354 case GL_RG8_SNORM:
2355 case GL_RGB8_SNORM:
2356 case GL_RGBA8_SNORM:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002357 res = false;
2358 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07002359 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002360 case GL_RGB:
2361 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07002362 switch (fbo_format_info.tex_type) {
2363 case GL_FLOAT:
2364 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002365 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002366 case GL_UNSIGNED_INT_2_10_10_10_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07002367 res = false;
2368 break;
2369 default:
2370 res = true;
2371 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002372 break;
2373 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07002374 res = true;
2375 }
2376 break;
2377 case FBO_ATTACHMENT_NONE:
2378 res = true;
2379 break;
2380 default:
2381 res = true;
2382 }
2383 return res;
2384}
2385
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002386bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const {
2387 bool res = true;
2388
2389 for (int i = 0; i < state->getMaxColorAttachments(); i++) {
2390 res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i));
2391 }
2392
2393 res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT);
2394 res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT);
2395
2396 return res;
2397}
2398
Lingfeng Yang69066602016-04-12 09:29:11 -07002399GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
2400 GL2Encoder* ctx = (GL2Encoder*)self;
2401 GLClientState* state = ctx->m_state;
2402
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002403 bool fboCompleteByCodec =
2404 ctx->checkFramebufferCompleteness(target, state);
2405
2406 if (!fboCompleteByCodec) {
2407 state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
Lingfeng Yang69066602016-04-12 09:29:11 -07002408 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2409 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002410 // double check with underlying opengl to avoid craziness.
Lingfeng Yang69066602016-04-12 09:29:11 -07002411 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002412 state->setCheckFramebufferStatus(target, host_checkstatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002413 if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE;
Lingfeng Yang69066602016-04-12 09:29:11 -07002414 return host_checkstatus;
2415 }
2416}
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002417
2418void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2419 GL2Encoder* ctx = (GL2Encoder*)self;
2420 GLClientState* state = ctx->m_state;
2421 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2422
2423 ctx->m_glGenVertexArrays_enc(self, n, arrays);
2424 for (int i = 0; i < n; i++) {
2425 ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2426 }
2427 state->addVertexArrayObjects(n, arrays);
2428}
2429
2430void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2431 GL2Encoder* ctx = (GL2Encoder*)self;
2432 GLClientState* state = ctx->m_state;
2433 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2434
2435 ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2436 for (int i = 0; i < n; i++) {
2437 ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2438 }
2439 state->removeVertexArrayObjects(n, arrays);
2440}
2441
2442void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2443 ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2444 GL2Encoder* ctx = (GL2Encoder*)self;
2445 GLClientState* state = ctx->m_state;
2446 SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2447 ctx->m_glBindVertexArray_enc(self, array);
2448 state->setVertexArrayObject(array);
2449}
2450
2451void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2452 GL2Encoder* ctx = (GL2Encoder*)self;
2453 GLClientState* state = ctx->m_state;
2454
2455 // begin validation (lots)
2456
2457 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2458
2459 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2460
2461 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2462
2463 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2464 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2465
2466 GLsizeiptr bufferDataSize = buf->m_size;
2467
2468 RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2469 RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2470 RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2471 RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2472
2473 RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2474 RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2475 RET_AND_SET_ERROR_IF(
2476 (access & GL_MAP_READ_BIT) &&
2477 ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2478 (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2479 (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2480 (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2481
2482 // end validation; actually do stuff now
2483
2484 buf->m_mapped = true;
2485 buf->m_mappedAccess = access;
2486 buf->m_mappedOffset = offset;
2487 buf->m_mappedLength = length;
2488
2489 char* todo = (char*)buf->m_fixedBuffer.ptr() + offset;
2490 ctx->glMapBufferRangeAEMU(
2491 ctx, target,
2492 offset, length,
2493 access,
2494 todo);
2495
2496 return todo;
2497}
2498
2499GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
2500 GL2Encoder* ctx = (GL2Encoder*)self;
2501 GLClientState* state = ctx->m_state;
2502
2503 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
2504
2505 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2506
2507 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
2508
2509 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2510 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
2511 RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
2512
Lingfeng Yang423129e2017-01-18 09:23:12 -08002513 if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
2514 // invalide index range cache here
2515 if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) {
2516 buf->m_indexRangeCache.invalidateRange(0, buf->m_size);
2517 } else {
2518 buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength);
2519 }
2520 }
2521
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002522 GLboolean host_res = GL_TRUE;
2523
2524 ctx->glUnmapBufferAEMU(
2525 ctx, target,
2526 buf->m_mappedOffset,
2527 buf->m_mappedLength,
2528 buf->m_mappedAccess,
2529 (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
2530 &host_res);
2531
2532 buf->m_mapped = false;
2533 buf->m_mappedAccess = 0;
2534 buf->m_mappedOffset = 0;
2535 buf->m_mappedLength = 0;
2536
2537 return host_res;
2538}
2539
2540void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
2541 GL2Encoder* ctx = (GL2Encoder*)self;
2542 GLClientState* state = ctx->m_state;
2543
2544 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2545
2546 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2547 SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
2548
2549 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2550 SET_ERROR_IF(!buf, GL_INVALID_VALUE);
2551 SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
2552 SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
2553
2554 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
2555 SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
2556 SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
2557
2558 GLintptr totalOffset = buf->m_mappedOffset + offset;
Lingfeng Yang423129e2017-01-18 09:23:12 -08002559
2560 buf->m_indexRangeCache.invalidateRange(totalOffset, length);
2561
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002562 ctx->glFlushMappedBufferRangeAEMU(
2563 ctx, target,
2564 totalOffset,
2565 length,
2566 buf->m_mappedAccess,
2567 (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
2568}
2569
2570void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
2571 GL2Encoder* ctx = (GL2Encoder*)self;
2572 GLClientState* state = ctx->m_state;
2573
2574 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2575 // Filter compressed formats support.
2576 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
2577 // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
2578 GLint max_texture_size;
2579 GLint max_cube_map_texture_size;
2580 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2581 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2582 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2583 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2584 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2585 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2586 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2587 SET_ERROR_IF(border, GL_INVALID_VALUE);
2588 // If unpack buffer is nonzero, verify unmapped state.
2589 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2590 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2591 // If unpack buffer is nonzero, verify buffer data fits.
2592 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2593 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2594 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2595 GL_INVALID_OPERATION);
2596 // TODO: Fix:
2597 // If |imageSize| is inconsistent with compressed dimensions.
2598 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
2599
2600 GLenum stateTarget = target;
2601 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2602 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2603 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2604 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2605 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2606 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2607 stateTarget = GL_TEXTURE_CUBE_MAP;
2608 state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
2609 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2610
2611 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2612 ctx->glCompressedTexImage2DOffsetAEMU(
2613 ctx, target, level, internalformat,
2614 width, height, border,
2615 imageSize, (uintptr_t)data);
2616 } else {
2617 ctx->m_glCompressedTexImage2D_enc(
2618 ctx, target, level, internalformat,
2619 width, height, border,
2620 imageSize, data);
2621 }
2622}
2623
2624void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
2625 GL2Encoder* ctx = (GL2Encoder*)self;
2626 GLClientState* state = ctx->m_state;
2627
2628 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2629 // If unpack buffer is nonzero, verify unmapped state.
2630 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2631 GLint max_texture_size;
2632 GLint max_cube_map_texture_size;
2633 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2634 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2635 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2636 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2637 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2638 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2639 // If unpack buffer is nonzero, verify buffer data fits.
2640 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2641 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2642 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2643 GL_INVALID_OPERATION);
2644 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2645
2646 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2647 ctx->glCompressedTexSubImage2DOffsetAEMU(
2648 ctx, target, level,
2649 xoffset, yoffset,
2650 width, height, format,
2651 imageSize, (uintptr_t)data);
2652 } else {
2653 ctx->m_glCompressedTexSubImage2D_enc(
2654 ctx, target, level,
2655 xoffset, yoffset,
2656 width, height, format,
2657 imageSize, data);
2658 }
2659}
2660
2661void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
2662 GL2Encoder* ctx = (GL2Encoder*)self;
2663 GLClientState* state = ctx->m_state;
2664
2665 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2666
2667 // Only works with certain targets
2668 SET_ERROR_IF(
2669 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2670 target == GL_SHADER_STORAGE_BUFFER ||
2671 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2672 target == GL_UNIFORM_BUFFER),
2673 GL_INVALID_ENUM);
2674
2675 // Can't exceed range
2676 SET_ERROR_IF(index < 0 ||
2677 index >= state->getMaxIndexedBufferBindings(target),
2678 GL_INVALID_VALUE);
2679 SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
2680 SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
2681 target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
2682 (size % 4 || offset % 4),
2683 GL_INVALID_VALUE);
2684
2685 GLint ssbo_offset_align, ubo_offset_align;
2686 ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
2687 ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
2688 SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
2689 offset % ssbo_offset_align,
2690 GL_INVALID_VALUE);
2691 SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
2692 offset % ubo_offset_align,
2693 GL_INVALID_VALUE);
2694
2695 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002696 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002697 state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0);
2698 ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size);
2699}
2700
2701void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
2702 GL2Encoder* ctx = (GL2Encoder*)self;
2703 GLClientState* state = ctx->m_state;
2704
2705 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2706
2707 // Only works with certain targets
2708 SET_ERROR_IF(
2709 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2710 target == GL_SHADER_STORAGE_BUFFER ||
2711 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2712 target == GL_UNIFORM_BUFFER),
2713 GL_INVALID_ENUM);
2714 // Can't exceed range
2715 SET_ERROR_IF(index < 0 ||
2716 index >= state->getMaxIndexedBufferBindings(target),
2717 GL_INVALID_VALUE);
2718
2719 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002720 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002721 BufferData* buf = ctx->getBufferDataById(buffer);
2722 state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0);
2723 ctx->m_glBindBufferBase_enc(self, target, index, buffer);
2724}
2725
2726void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
2727 GL2Encoder* ctx = (GL2Encoder*)self;
2728 GLClientState* state = ctx->m_state;
2729
2730 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
2731 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
2732 SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
2733 readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
2734 readtarget == GL_DRAW_INDIRECT_BUFFER ||
2735 readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2736 SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
2737 writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
2738 writetarget == GL_DRAW_INDIRECT_BUFFER ||
2739 writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2740 SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
2741 SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
2742 SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
2743 SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
2744 SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
2745 SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
2746 SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
2747 SET_ERROR_IF(
2748 ctx->getBufferData(readtarget) &&
2749 (readoffset + size > ctx->getBufferData(readtarget)->m_size),
2750 GL_INVALID_VALUE);
2751 SET_ERROR_IF(
2752 ctx->getBufferData(writetarget) &&
2753 (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
2754 GL_INVALID_VALUE);
2755 SET_ERROR_IF(readtarget == writetarget &&
2756 !((writeoffset >= readoffset + size) ||
2757 (readoffset >= writeoffset + size)),
2758 GL_INVALID_VALUE);
2759
2760 ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
2761}
2762
2763void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
2764 GL2Encoder* ctx = (GL2Encoder*)self;
2765
2766 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2767 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002768 target != GL_ARRAY_BUFFER &&
2769 target != GL_ELEMENT_ARRAY_BUFFER &&
2770 target != GL_COPY_READ_BUFFER &&
2771 target != GL_COPY_WRITE_BUFFER &&
2772 target != GL_PIXEL_PACK_BUFFER &&
2773 target != GL_PIXEL_UNPACK_BUFFER &&
2774 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
2775 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002776 GL_INVALID_ENUM);
2777 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
2778 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002779 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
2780 pname != GL_BUFFER_MAPPED &&
2781 pname != GL_BUFFER_SIZE &&
2782 pname != GL_BUFFER_USAGE &&
2783 pname != GL_BUFFER_MAP_LENGTH &&
2784 pname != GL_BUFFER_MAP_OFFSET,
2785 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002786
2787 if (!params) return;
2788
2789 BufferData* buf = ctx->getBufferData(target);
2790
2791 switch (pname) {
2792 case GL_BUFFER_ACCESS_FLAGS:
2793 *params = buf ? buf->m_mappedAccess : 0;
2794 break;
2795 case GL_BUFFER_MAPPED:
2796 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
2797 break;
2798 case GL_BUFFER_SIZE:
2799 *params = buf ? buf->m_size : 0;
2800 break;
2801 case GL_BUFFER_USAGE:
2802 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
2803 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002804 case GL_BUFFER_MAP_LENGTH:
2805 *params = buf ? buf->m_mappedLength : 0;
2806 break;
2807 case GL_BUFFER_MAP_OFFSET:
2808 *params = buf ? buf->m_mappedOffset : 0;
2809 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002810 default:
2811 break;
2812 }
2813}
2814
2815void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
2816 GL2Encoder* ctx = (GL2Encoder*)self;
2817
2818 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2819 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002820 target != GL_ARRAY_BUFFER &&
2821 target != GL_ELEMENT_ARRAY_BUFFER &&
2822 target != GL_COPY_READ_BUFFER &&
2823 target != GL_COPY_WRITE_BUFFER &&
2824 target != GL_PIXEL_PACK_BUFFER &&
2825 target != GL_PIXEL_UNPACK_BUFFER &&
2826 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
2827 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002828 GL_INVALID_ENUM);
2829 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
2830 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002831 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
2832 pname != GL_BUFFER_MAPPED &&
2833 pname != GL_BUFFER_SIZE &&
2834 pname != GL_BUFFER_USAGE &&
2835 pname != GL_BUFFER_MAP_LENGTH &&
2836 pname != GL_BUFFER_MAP_OFFSET,
2837 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002838
2839 if (!params) return;
2840
2841 BufferData* buf = ctx->getBufferData(target);
2842
2843 switch (pname) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002844 case GL_BUFFER_ACCESS_FLAGS:
2845 *params = buf ? buf->m_mappedAccess : 0;
2846 break;
2847 case GL_BUFFER_MAPPED:
2848 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
2849 break;
2850 case GL_BUFFER_SIZE:
2851 *params = buf ? buf->m_size : 0;
2852 break;
2853 case GL_BUFFER_USAGE:
2854 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
2855 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002856 case GL_BUFFER_MAP_LENGTH:
2857 *params = buf ? buf->m_mappedLength : 0;
2858 break;
2859 case GL_BUFFER_MAP_OFFSET:
2860 *params = buf ? buf->m_mappedOffset : 0;
2861 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002862 default:
2863 break;
2864 }
2865}
2866
2867void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
2868 GL2Encoder* ctx = (GL2Encoder*)self;
2869 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2870 SET_ERROR_IF(
2871 target == GL_ATOMIC_COUNTER_BUFFER ||
2872 target == GL_DISPATCH_INDIRECT_BUFFER ||
2873 target == GL_DRAW_INDIRECT_BUFFER ||
2874 target == GL_SHADER_STORAGE_BUFFER,
2875 GL_INVALID_ENUM);
2876 SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
2877 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
2878 if (!params) return;
2879
2880 BufferData* buf = ctx->getBufferData(target);
2881
2882 if (!buf || !buf->m_mapped) { *params = NULL; return; }
2883
2884 *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
2885}
2886
2887static const char* const kNameDelimiter = ";";
2888
2889static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
2890
2891#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
2892
2893 std::string packed;
2894 // validate the array of char[]'s
2895 const char* currName;
2896 for (GLsizei i = 0; i < count; i++) {
2897 currName = names[i];
2898 VALIDATE(!currName, GL_INVALID_OPERATION);
2899 // check if has reasonable size
2900 size_t len = strlen(currName);
2901 VALIDATE(!len, GL_INVALID_OPERATION);
2902 // check for our delimiter, which if present
2903 // in the name, means an invalid name anyway.
2904 VALIDATE(strstr(currName, kNameDelimiter),
2905 GL_INVALID_OPERATION);
2906 packed += currName;
2907 packed += ";";
2908 }
2909
2910 *err_out = GL_NO_ERROR;
2911 return packed;
2912}
2913
2914void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
2915 GL2Encoder* ctx = (GL2Encoder*)self;
2916
2917 if (!uniformCount) return;
2918
2919 GLint err = GL_NO_ERROR;
2920 std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
2921 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
2922
2923 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
2924 std::vector<int> arrIndices;
2925 for (size_t i = 0; i < uniformCount; i++) {
2926 int err;
2927 arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
2928 if (err) {
2929 ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
2930 return;
2931 }
2932 }
2933
2934 ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
2935
2936 for (int i = 0; i < uniformCount; i++) {
2937 if (uniformIndices[i] >= 0 && needLocationWAR) {
2938 uniformIndices[i] =
2939 ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
2940 }
2941 }
2942}
2943
2944void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
2945 GL2Encoder *ctx = (GL2Encoder*)self;
2946 GLClientState* state = ctx->m_state;
2947 GLSharedGroupPtr shared = ctx->m_shared;
2948
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002949 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002950 ctx->m_glUniform1ui_enc(self, hostLoc, v0);
2951
2952 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002953 if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002954 GLenum origActiveTexture = state->getActiveTextureUnit();
2955 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
2956 ctx->m_glActiveTexture_enc(self, origActiveTexture);
2957 }
2958 state->setActiveTextureUnit(origActiveTexture);
2959 }
2960}
2961
2962void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) {
2963 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002964 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002965 ctx->m_glUniform2ui_enc(self, hostLoc, v0, v1);
2966}
2967
2968void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) {
2969 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002970 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002971 ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2);
2972}
2973
2974void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) {
2975 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002976 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002977 ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3);
2978}
2979
2980void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2981 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002982 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002983 ctx->m_glUniform1uiv_enc(self, hostLoc, count, value);
2984}
2985
2986void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2987 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002988 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002989 ctx->m_glUniform2uiv_enc(self, hostLoc, count, value);
2990}
2991
2992void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2993 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002994 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002995 ctx->m_glUniform3uiv_enc(self, hostLoc, count, value);
2996}
2997
2998void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2999 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003000 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003001 ctx->m_glUniform4uiv_enc(self, hostLoc, count, value);
3002}
3003
3004void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3005 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003006 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003007 ctx->m_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value);
3008}
3009
3010void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3011 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003012 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003013 ctx->m_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value);
3014}
3015
3016void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3017 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003018 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003019 ctx->m_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value);
3020}
3021
3022void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3023 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003024 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003025 ctx->m_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value);
3026}
3027
3028void GL2Encoder::s_glUniformMatrix3x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3029 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003030 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003031 ctx->m_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value);
3032}
3033
3034void GL2Encoder::s_glUniformMatrix4x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3035 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003036 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003037 ctx->m_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value);
3038}
3039
3040void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3041 GL2Encoder *ctx = (GL2Encoder*)self;
3042 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3043 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3044 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3045 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3046 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3047 ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3048}
3049
3050void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3051 GL2Encoder* ctx = (GL2Encoder*)self;
3052 GLClientState* state = ctx->m_state;
3053
3054 // refresh client state's # active uniforms in this block
3055 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3056 // TODO if worth it: cache uniform count and other params,
3057 // invalidate on program relinking.
3058 GLint numActiveUniforms;
3059 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3060 program, uniformBlockIndex,
3061 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3062 &numActiveUniforms);
3063 ctx->m_state->setNumActiveUniformsInUniformBlock(
3064 program, uniformBlockIndex, numActiveUniforms);
3065 }
3066
3067 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3068 program, uniformBlockIndex,
3069 pname, params);
3070}
3071
3072void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3073 GL2Encoder *ctx = (GL2Encoder *)self;
3074 assert(ctx->m_state);
3075 GLint maxIndex;
3076 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3077 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3078
3079 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3080 ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3081 }
3082}
3083
3084void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3085 GL2Encoder *ctx = (GL2Encoder *)self;
3086 assert(ctx->m_state);
3087 GLint maxIndex;
3088 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3089 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3090
3091 if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3092 ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3093 }
3094}
3095
3096void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3097 GL2Encoder *ctx = (GL2Encoder *)self;
3098 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003099 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003100 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
3101 SET_ERROR_IF(
3102 !(type == GL_BYTE ||
3103 type == GL_UNSIGNED_BYTE ||
3104 type == GL_SHORT ||
3105 type == GL_UNSIGNED_SHORT ||
3106 type == GL_INT ||
3107 type == GL_UNSIGNED_INT),
3108 GL_INVALID_ENUM);
3109 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
3110
3111 ctx->m_state->setVertexAttribBinding(index, index);
3112 ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true);
3113 GLsizei effectiveStride = stride;
3114 if (stride == 0) {
3115 effectiveStride = glSizeof(type) * size;
3116 }
3117 ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride);
3118
3119 if (ctx->m_state->currentArrayVbo() != 0) {
3120 ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer);
3121 } else {
3122 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION);
3123 // wait for client-array handler
3124 }
3125}
3126
3127void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) {
3128 GL2Encoder *ctx = (GL2Encoder *)self;
3129 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003130 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003131 ctx->m_state->setVertexAttribBinding(index, index);
3132 ctx->m_state->setVertexBindingDivisor(index, divisor);
3133 ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor);
3134}
3135
3136void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3137 GLenum target, GLsizei samples, GLenum internalformat,
3138 GLsizei width, GLsizei height) {
3139 GL2Encoder *ctx = (GL2Encoder *)self;
3140 GLClientState* state = ctx->m_state;
3141
3142 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3143 SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3144
3145 GLint max_samples;
3146 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3147 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3148
3149 state->setBoundRenderbufferFormat(internalformat);
3150 state->setBoundRenderbufferSamples(samples);
3151 ctx->m_glRenderbufferStorageMultisample_enc(
3152 self, target, samples, internalformat, width, height);
3153}
3154
3155void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3156 GL2Encoder* ctx = (GL2Encoder*)self;
3157 SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3158 SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3159 for (int i = 0; i < n; i++) {
3160 SET_ERROR_IF(
3161 bufs[i] != GL_NONE &&
3162 bufs[i] != GL_BACK &&
3163 glUtilsColorAttachmentIndex(bufs[i]) == -1,
3164 GL_INVALID_ENUM);
3165 SET_ERROR_IF(
3166 !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3167 glUtilsColorAttachmentIndex(bufs[i]) != -1,
3168 GL_INVALID_OPERATION);
3169 SET_ERROR_IF(
3170 ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3171 ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3172 glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3173 (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3174 bufs[i] != GL_NONE)),
3175 GL_INVALID_OPERATION);
3176 }
3177
3178 ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3179}
3180
3181void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3182 GL2Encoder* ctx = (GL2Encoder*)self;
3183
3184 SET_ERROR_IF(
3185 glUtilsColorAttachmentIndex(src) != -1 &&
3186 (glUtilsColorAttachmentIndex(src) >=
3187 ctx->m_state->getMaxColorAttachments()),
3188 GL_INVALID_OPERATION);
3189 SET_ERROR_IF(
3190 src != GL_NONE &&
3191 src != GL_BACK &&
3192 src > GL_COLOR_ATTACHMENT0 &&
3193 src < GL_DEPTH_ATTACHMENT &&
3194 (src - GL_COLOR_ATTACHMENT0) >
3195 ctx->m_state->getMaxColorAttachments(),
3196 GL_INVALID_OPERATION);
3197 SET_ERROR_IF(
3198 src != GL_NONE &&
3199 src != GL_BACK &&
3200 glUtilsColorAttachmentIndex(src) == -1,
3201 GL_INVALID_ENUM);
3202 SET_ERROR_IF(
3203 !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3204 src != GL_NONE &&
3205 src != GL_BACK,
3206 GL_INVALID_OPERATION);
3207 SET_ERROR_IF(
3208 ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3209 src != GL_NONE &&
3210 glUtilsColorAttachmentIndex(src) == -1,
3211 GL_INVALID_OPERATION);
3212
3213 ctx->m_glReadBuffer_enc(ctx, src);
3214}
3215
3216void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3217 GL2Encoder* ctx = (GL2Encoder*)self;
3218 GLClientState* state = ctx->m_state;
3219
3220 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3221 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3222 GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3223 SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3224 lastBoundTarget != GL_TEXTURE_3D,
3225 GL_INVALID_OPERATION);
3226 state->attachTextureObject(target, attachment, texture);
3227
3228 GLint max3DTextureSize;
3229 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3230 SET_ERROR_IF(
3231 layer >= max3DTextureSize,
3232 GL_INVALID_VALUE);
3233
3234 ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3235}
3236
3237void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3238 GL2Encoder* ctx = (GL2Encoder*)self;
3239 GLClientState* state = ctx->m_state;
3240
3241 SET_ERROR_IF(
3242 target != GL_TEXTURE_2D &&
3243 target != GL_TEXTURE_CUBE_MAP,
3244 GL_INVALID_ENUM);
3245 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3246 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3247 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3248 SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3249 GL_INVALID_OPERATION);
3250 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3251
3252 state->setBoundTextureInternalFormat(target, internalformat);
3253 state->setBoundTextureDims(target, -1, width, height, 1);
3254 state->setBoundTextureImmutableFormat(target);
3255 ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
3256}
3257
3258void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3259 GL2Encoder* ctx = (GL2Encoder*)self;
3260
3261 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3262
3263 GLint maxCount = 0;
3264 ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3265
3266 SET_ERROR_IF(
3267 bufferMode == GL_SEPARATE_ATTRIBS &&
3268 maxCount < count,
3269 GL_INVALID_VALUE);
3270 SET_ERROR_IF(
3271 bufferMode != GL_INTERLEAVED_ATTRIBS &&
3272 bufferMode != GL_SEPARATE_ATTRIBS,
3273 GL_INVALID_ENUM);
3274
3275 if (!count) return;
3276
3277 GLint err = GL_NO_ERROR;
3278 std::string packed = packVarNames(count, varyings, &err);
3279 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3280
3281 ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3282}
3283
3284void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3285 GL2Encoder* ctx = (GL2Encoder*)self;
3286 GLClientState* state = ctx->m_state;
3287 ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3288 state->setTransformFeedbackActiveUnpaused(true);
3289}
3290
3291void GL2Encoder::s_glEndTransformFeedback(void* self) {
3292 GL2Encoder* ctx = (GL2Encoder*)self;
3293 GLClientState* state = ctx->m_state;
3294 ctx->m_glEndTransformFeedback_enc(ctx);
3295 state->setTransformFeedbackActiveUnpaused(false);
3296}
3297
3298void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3299 GL2Encoder* ctx = (GL2Encoder*)self;
3300 GLClientState* state = ctx->m_state;
3301 ctx->m_glPauseTransformFeedback_enc(ctx);
3302 state->setTransformFeedbackActiveUnpaused(false);
3303}
3304
3305void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3306 GL2Encoder* ctx = (GL2Encoder*)self;
3307 GLClientState* state = ctx->m_state;
3308 ctx->m_glResumeTransformFeedback_enc(ctx);
3309 state->setTransformFeedbackActiveUnpaused(true);
3310}
3311
3312void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3313 GLsizei width, GLsizei height, GLsizei depth,
3314 GLint border, GLenum format, GLenum type, const GLvoid* data) {
3315 GL2Encoder* ctx = (GL2Encoder*)self;
3316 GLClientState* state = ctx->m_state;
3317
3318 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3319 target != GL_TEXTURE_2D_ARRAY,
3320 GL_INVALID_ENUM);
3321 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3322 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3323
3324 // If unpack buffer is nonzero, verify unmapped state.
3325 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3326
3327 GLint max_texture_size;
3328 GLint max_3d_texture_size;
3329 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3330 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3331 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3332 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3333 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3334
3335 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3336 SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3337 SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3338 SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3339 SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3340 SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3341 SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3342 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3343 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3344 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3345 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3346 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3347 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3348 GL_INVALID_OPERATION);
3349 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3350 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3351 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3352 glSizeof(type)),
3353 GL_INVALID_OPERATION);
3354 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3355
3356 state->setBoundTextureInternalFormat(target, internalFormat);
3357 state->setBoundTextureFormat(target, format);
3358 state->setBoundTextureType(target, type);
3359 state->setBoundTextureDims(target, level, width, height, depth);
3360
3361 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3362 ctx->glTexImage3DOffsetAEMU(
3363 ctx, target, level, internalFormat,
3364 width, height, depth,
3365 border, format, type, (uintptr_t)data);
3366 } else {
3367 ctx->m_glTexImage3D_enc(ctx,
3368 target, level, internalFormat,
3369 width, height, depth,
3370 border, format, type, data);
3371 }
3372}
3373
3374void 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) {
3375 GL2Encoder* ctx = (GL2Encoder*)self;
3376 GLClientState* state = ctx->m_state;
3377
3378 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3379 target != GL_TEXTURE_2D_ARRAY,
3380 GL_INVALID_ENUM);
3381 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3382 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3383 // If unpack buffer is nonzero, verify unmapped state.
3384 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3385 GLint max_texture_size;
3386 GLint max_3d_texture_size;
3387 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3388 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3389 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3390 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3391 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3392 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3393 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3394 GLuint tex = state->getBoundTexture(target);
3395 GLsizei neededWidth = xoffset + width;
3396 GLsizei neededHeight = yoffset + height;
3397 GLsizei neededDepth = zoffset + depth;
3398
3399 SET_ERROR_IF(tex &&
3400 (neededWidth > state->queryTexWidth(level, tex) ||
3401 neededHeight > state->queryTexHeight(level, tex) ||
3402 neededDepth > state->queryTexDepth(level, tex)),
3403 GL_INVALID_VALUE);
3404 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3405 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3406 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3407 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3408 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3409 GL_INVALID_OPERATION);
3410 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3411 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3412 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3413 glSizeof(type)),
3414 GL_INVALID_OPERATION);
3415 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
3416 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3417
3418 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3419 ctx->glTexSubImage3DOffsetAEMU(ctx,
3420 target, level,
3421 xoffset, yoffset, zoffset,
3422 width, height, depth,
3423 format, type, (uintptr_t)data);
3424 } else {
3425 ctx->m_glTexSubImage3D_enc(ctx,
3426 target, level,
3427 xoffset, yoffset, zoffset,
3428 width, height, depth,
3429 format, type, data);
3430 }
3431}
3432
3433void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
3434 GL2Encoder* ctx = (GL2Encoder*)self;
3435 GLClientState* state = ctx->m_state;
3436
3437 // Filter compressed formats support.
3438 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3439 // If unpack buffer is nonzero, verify unmapped state.
3440 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3441 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3442 SET_ERROR_IF(border, GL_INVALID_VALUE);
3443 // If unpack buffer is nonzero, verify buffer data fits.
3444 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3445 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3446 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3447 GL_INVALID_OPERATION);
3448 // TODO: Fix:
3449 // If |imageSize| is too small for compressed dimensions.
3450 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
3451 state->setBoundTextureInternalFormat(target, (GLint)internalformat);
3452 state->setBoundTextureDims(target, level, width, height, depth);
3453
3454 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3455 ctx->glCompressedTexImage3DOffsetAEMU(
3456 ctx, target, level, internalformat,
3457 width, height, depth, border,
3458 imageSize, (uintptr_t)data);
3459 } else {
3460 ctx->m_glCompressedTexImage3D_enc(
3461 ctx, target, level, internalformat,
3462 width, height, depth, border,
3463 imageSize, data);
3464 }
3465}
3466
3467void 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) {
3468 GL2Encoder* ctx = (GL2Encoder*)self;
3469 GLClientState* state = ctx->m_state;
3470
3471 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3472 // If unpack buffer is nonzero, verify unmapped state.
3473 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3474 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3475 // If unpack buffer is nonzero, verify buffer data fits.
3476 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3477 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3478 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3479 GL_INVALID_OPERATION);
3480 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3481
3482 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3483 ctx->glCompressedTexSubImage3DOffsetAEMU(
3484 ctx, target, level,
3485 xoffset, yoffset, zoffset,
3486 width, height, depth,
3487 format, imageSize, (uintptr_t)data);
3488 } else {
3489 ctx->m_glCompressedTexSubImage3D_enc(
3490 ctx, target, level,
3491 xoffset, yoffset, zoffset,
3492 width, height, depth,
3493 format, imageSize, data);
3494
3495 }
3496}
3497
3498void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
3499 GL2Encoder* ctx = (GL2Encoder*)self;
3500 GLClientState* state = ctx->m_state;
3501 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3502 target != GL_TEXTURE_2D_ARRAY,
3503 GL_INVALID_ENUM);
3504 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3505 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3506 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3507 SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
3508 GL_INVALID_OPERATION);
3509 SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
3510 GL_INVALID_OPERATION);
3511 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3512
3513 state->setBoundTextureInternalFormat(target, internalformat);
3514 state->setBoundTextureDims(target, -1, width, height, depth);
3515 state->setBoundTextureImmutableFormat(target);
3516 ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
3517 state->setBoundTextureImmutableFormat(target);
3518}
3519
3520void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
3521 GL2Encoder *ctx = (GL2Encoder *)self;
3522 assert(ctx->m_state != NULL);
3523 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3524 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3525
3526 bool has_client_vertex_arrays = false;
3527 bool has_indirect_arrays = false;
3528 ctx->getVBOUsage(&has_client_vertex_arrays,
3529 &has_indirect_arrays);
3530
3531 if (has_client_vertex_arrays ||
3532 (!has_client_vertex_arrays &&
3533 !has_indirect_arrays)) {
3534 ctx->sendVertexAttributes(first, count, true, primcount);
3535 ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
3536 } else {
3537 ctx->sendVertexAttributes(0, count, false, primcount);
3538 ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
3539 }
3540 ctx->m_stream->flush();
3541}
3542
3543void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
3544{
3545
3546 GL2Encoder *ctx = (GL2Encoder *)self;
3547 assert(ctx->m_state != NULL);
3548 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3549 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3550 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3551 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3552
3553 bool has_client_vertex_arrays = false;
3554 bool has_indirect_arrays = false;
3555 int nLocations = ctx->m_state->nLocations();
3556 GLintptr offset = 0;
3557
3558 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3559
3560 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3561 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3562 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3563 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3564 }
3565
3566 BufferData* buf = NULL;
3567 int minIndex = 0, maxIndex = 0;
3568
3569 // For validation/immediate index array purposes,
3570 // we need the min/max vertex index of the index array.
3571 // If the VBO != 0, this may not be the first time we have
3572 // used this particular index buffer. getBufferIndexRange
3573 // can more quickly get min/max vertex index by
3574 // caching previous results.
3575 if (ctx->m_state->currentIndexVbo() != 0) {
3576 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3577 offset = (GLintptr)indices;
3578 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3579 ctx->getBufferIndexRange(buf,
3580 indices,
3581 type,
3582 (size_t)count,
3583 (size_t)offset,
3584 &minIndex, &maxIndex);
3585 } else {
3586 // In this case, the |indices| field holds a real
3587 // array, so calculate the indices now. They will
3588 // also be needed to know how much data to
3589 // transfer to host.
3590 ctx->calcIndexRange(indices,
3591 type,
3592 count,
3593 &minIndex,
3594 &maxIndex);
3595 }
3596
3597 bool adjustIndices = true;
3598 if (ctx->m_state->currentIndexVbo() != 0) {
3599 if (!has_client_vertex_arrays) {
3600 ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
3601 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3602 ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
3603 ctx->flushDrawCall();
3604 adjustIndices = false;
3605 } else {
3606 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3607 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3608 }
3609 }
3610 if (adjustIndices) {
3611 void *adjustedIndices =
3612 ctx->recenterIndices(indices,
3613 type,
3614 count,
3615 minIndex);
3616
3617 if (has_indirect_arrays || 1) {
3618 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
3619 ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
3620 ctx->m_stream->flush();
3621 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3622 if(!has_indirect_arrays) {
3623 //ALOGD("unoptimized drawelements !!!\n");
3624 }
3625 } else {
3626 // we are all direct arrays and immidate mode index array -
3627 // rebuild the arrays and the index array;
3628 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3629 }
3630 }
3631}
3632
3633void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
3634{
3635
3636 GL2Encoder *ctx = (GL2Encoder *)self;
3637 assert(ctx->m_state != NULL);
3638 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3639 SET_ERROR_IF(end < start, GL_INVALID_VALUE);
3640 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3641 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3642 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3643
3644 bool has_client_vertex_arrays = false;
3645 bool has_indirect_arrays = false;
3646 int nLocations = ctx->m_state->nLocations();
3647 GLintptr offset = 0;
3648
3649 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3650
3651 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3652 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3653 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3654 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3655 }
3656
3657 BufferData* buf = NULL;
3658 int minIndex = 0, maxIndex = 0;
3659
3660 // For validation/immediate index array purposes,
3661 // we need the min/max vertex index of the index array.
3662 // If the VBO != 0, this may not be the first time we have
3663 // used this particular index buffer. getBufferIndexRange
3664 // can more quickly get min/max vertex index by
3665 // caching previous results.
3666 if (ctx->m_state->currentIndexVbo() != 0) {
3667 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3668 offset = (GLintptr)indices;
3669 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3670 ctx->getBufferIndexRange(buf,
3671 indices,
3672 type,
3673 (size_t)count,
3674 (size_t)offset,
3675 &minIndex, &maxIndex);
3676 } else {
3677 // In this case, the |indices| field holds a real
3678 // array, so calculate the indices now. They will
3679 // also be needed to know how much data to
3680 // transfer to host.
3681 ctx->calcIndexRange(indices,
3682 type,
3683 count,
3684 &minIndex,
3685 &maxIndex);
3686 }
3687
3688 bool adjustIndices = true;
3689 if (ctx->m_state->currentIndexVbo() != 0) {
3690 if (!has_client_vertex_arrays) {
3691 ctx->sendVertexAttributes(0, maxIndex + 1, false);
3692 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3693 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
3694 ctx->flushDrawCall();
3695 adjustIndices = false;
3696 } else {
3697 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3698 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3699 }
3700 }
3701 if (adjustIndices) {
3702 void *adjustedIndices =
3703 ctx->recenterIndices(indices,
3704 type,
3705 count,
3706 minIndex);
3707
3708 if (has_indirect_arrays || 1) {
3709 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
3710 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
3711 ctx->m_stream->flush();
3712 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3713 if(!has_indirect_arrays) {
3714 //ALOGD("unoptimized drawelements !!!\n");
3715 }
3716 } else {
3717 // we are all direct arrays and immidate mode index array -
3718 // rebuild the arrays and the index array;
3719 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3720 }
3721 }
3722}
3723
3724// struct GLStringKey {
3725// GLenum name;
3726// GLuint index;
3727// };
3728//
3729// struct GLStringKeyCompare {
3730// bool operator() (const GLStringKey& a,
3731// const GLStringKey& b) const {
3732// if (a.name != b.name) return a.name < b.name;
3733// if (a.index != b.index) return a.index < b.index;
3734// return false;
3735// }
3736// };
3737//
3738// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
3739//
3740// static GLStringStore sGLStringStore;
3741// bool sGLStringStoreInitialized = false;
3742
3743const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
3744 GL2Encoder *ctx = (GL2Encoder *)self;
3745 GLubyte *retval = (GLubyte *) "";
3746
3747 RET_AND_SET_ERROR_IF(
3748 name != GL_VENDOR &&
3749 name != GL_RENDERER &&
3750 name != GL_VERSION &&
3751 name != GL_EXTENSIONS,
3752 GL_INVALID_ENUM,
3753 retval);
3754
3755 RET_AND_SET_ERROR_IF(
3756 name == GL_VENDOR ||
3757 name == GL_RENDERER ||
3758 name == GL_VERSION ||
3759 name == GL_EXTENSIONS &&
3760 index != 0,
3761 GL_INVALID_VALUE,
3762 retval);
3763
3764 switch (name) {
3765 case GL_VENDOR:
3766 retval = gVendorString;
3767 break;
3768 case GL_RENDERER:
3769 retval = gRendererString;
3770 break;
3771 case GL_VERSION:
3772 retval = gVersionString;
3773 break;
3774 case GL_EXTENSIONS:
3775 retval = gExtensionsString;
3776 break;
3777 }
3778
3779 return retval;
3780}
3781
3782void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
3783 GL2Encoder *ctx = (GL2Encoder *)self;
3784
3785 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3786
3787 GLint linkStatus = 0;
3788 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
3789 GLint properLength = 0;
3790 ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
3791
3792 SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
3793 SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
3794
3795 ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
3796}
3797
3798void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
3799 GL2Encoder *ctx = (GL2Encoder *)self;
3800
3801 SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
3802 SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
3803 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
3804 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
3805 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
3806 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
3807 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
3808 ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
3809 GL_INVALID_OPERATION);
3810 /*
3811GL_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.
3812
3813GL_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.
3814
3815GL_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.
3816
3817GL_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.
3818*/
3819
3820 FboFormatInfo fbo_format_info;
3821 ctx->m_state->getBoundFramebufferFormat(
3822 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
3823 SET_ERROR_IF(
3824 fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3825 !GLESv2Validation::readPixelsFboFormatMatch(
3826 format, type, fbo_format_info.tex_type),
3827 GL_INVALID_OPERATION);
3828
3829 if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
3830 ctx->glReadPixelsOffsetAEMU(
3831 ctx, x, y, width, height,
3832 format, type, (uintptr_t)pixels);
3833 } else {
3834 ctx->m_glReadPixels_enc(
3835 ctx, x, y, width, height,
3836 format, type, pixels);
3837 }
3838}
3839
3840// Track enabled state for some things like:
3841// - Primitive restart
3842void GL2Encoder::s_glEnable(void* self, GLenum what) {
3843 GL2Encoder *ctx = (GL2Encoder *)self;
3844
3845 switch (what) {
3846 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
3847 ctx->m_primitiveRestartEnabled = true;
3848 break;
3849 }
3850
3851 ctx->m_glEnable_enc(ctx, what);
3852}
3853
3854void GL2Encoder::s_glDisable(void* self, GLenum what) {
3855 GL2Encoder *ctx = (GL2Encoder *)self;
3856
3857 switch (what) {
3858 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
3859 ctx->m_primitiveRestartEnabled = false;
3860 break;
3861 }
3862
3863 ctx->m_glDisable_enc(ctx, what);
3864}
3865
3866void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
3867 GL2Encoder *ctx = (GL2Encoder *)self;
3868
3869 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3870
3871 ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
3872}
3873
3874void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
3875 GL2Encoder *ctx = (GL2Encoder *)self;
3876
3877 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3878
3879 ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
3880}
3881
3882void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
3883 GL2Encoder *ctx = (GL2Encoder *)self;
3884
3885 SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3886
3887 ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
3888}
3889
3890void 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) {
3891 GL2Encoder *ctx = (GL2Encoder *)self;
3892 GLClientState* state = ctx->m_state;
3893
3894 bool validateColor = mask | GL_COLOR_BUFFER_BIT;
3895 bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
3896 bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
3897
3898 FboFormatInfo read_fbo_format_info;
3899 FboFormatInfo draw_fbo_format_info;
3900 if (validateColor) {
3901 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
3902 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
3903
3904 if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3905 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
3906 SET_ERROR_IF(
3907 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3908 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3909 !GLESv2Validation::blitFramebufferFormat(
3910 read_fbo_format_info.tex_type,
3911 draw_fbo_format_info.tex_type),
3912 GL_INVALID_OPERATION);
3913 }
3914 }
3915
3916 if (validateDepth) {
3917 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
3918 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
3919
3920 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3921 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
3922 SET_ERROR_IF(
3923 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3924 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3925 !GLESv2Validation::blitFramebufferFormat(
3926 read_fbo_format_info.rb_format,
3927 draw_fbo_format_info.rb_format),
3928 GL_INVALID_OPERATION);
3929 }
3930 }
3931
3932 if (validateStencil) {
3933 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
3934 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
3935
3936 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3937 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
3938 SET_ERROR_IF(
3939 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3940 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3941 !GLESv2Validation::blitFramebufferFormat(
3942 read_fbo_format_info.rb_format,
3943 draw_fbo_format_info.rb_format),
3944 GL_INVALID_OPERATION);
3945 }
3946 }
3947
3948 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
3949 SET_ERROR_IF(
3950 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3951 draw_fbo_format_info.rb_multisamples > 0,
3952 GL_INVALID_OPERATION);
3953 SET_ERROR_IF(
3954 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3955 draw_fbo_format_info.tex_multisamples > 0,
3956 GL_INVALID_OPERATION);
3957
3958 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
3959 SET_ERROR_IF(
3960 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3961 read_fbo_format_info.rb_multisamples > 0 &&
3962 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3963 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3964 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3965 (read_fbo_format_info.rb_format !=
3966 draw_fbo_format_info.rb_format),
3967 GL_INVALID_OPERATION);
3968 SET_ERROR_IF(
3969 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3970 read_fbo_format_info.rb_multisamples > 0 &&
3971 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3972 (srcX0 != dstX0 || srcY0 != dstY0 ||
3973 srcX1 != dstX1 || srcY1 != dstY1),
3974 GL_INVALID_OPERATION);
3975
3976 ctx->m_glBlitFramebuffer_enc(ctx,
3977 srcX0, srcY0, srcX1, srcY1,
3978 dstX0, dstY0, dstX1, dstY1,
3979 mask, filter);
3980}
3981
3982void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
3983 GL2Encoder *ctx = (GL2Encoder *)self;
3984
3985 SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
3986 pname != GL_SAMPLES,
3987 GL_INVALID_ENUM);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003988 SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003989 SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08003990 !GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
3991 !GLESv2Validation::depthRenderableFormat(ctx, internalformat) &&
3992 !GLESv2Validation::stencilRenderableFormat(ctx, internalformat),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003993 GL_INVALID_ENUM);
3994 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
3995
3996 if (bufSize < 1) return;
3997
3998 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
3999 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
4000 switch (pname) {
4001 case GL_NUM_SAMPLE_COUNTS:
4002 *params = 3;
4003 break;
4004 case GL_SAMPLES:
4005 params[0] = 4;
4006 if (bufSize > 1) params[1] = 2;
4007 if (bufSize > 2) params[2] = 1;
4008 break;
4009 default:
4010 break;
4011 }
4012}
4013
4014void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
4015 GL2Encoder *ctx = (GL2Encoder *)self;
4016 GLClientState* state = ctx->m_state;
4017
4018 SET_ERROR_IF(target != GL_TEXTURE_2D &&
4019 target != GL_TEXTURE_3D &&
4020 target != GL_TEXTURE_CUBE_MAP,
4021 GL_INVALID_ENUM);
4022
4023 GLuint tex = state->getBoundTexture(target);
4024 GLenum internalformat = state->queryTexInternalFormat(tex);
4025 GLenum format = state->queryTexFormat(tex);
4026
4027 SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
4028 GL_INVALID_OPERATION);
4029 SET_ERROR_IF(tex &&
4030 !GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004031 !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4032 GLESv2Validation::filterableTexFormat(ctx, internalformat)),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004033 GL_INVALID_OPERATION);
4034
4035 ctx->m_glGenerateMipmap_enc(ctx, target);
4036}
4037
4038void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4039 GL2Encoder *ctx = (GL2Encoder *)self;
4040 GLint maxCombinedUnits;
4041 ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4042 SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4043
4044 ctx->m_glBindSampler_enc(ctx, unit, sampler);
4045}
4046
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004047GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4048 GL2Encoder *ctx = (GL2Encoder *)self;
4049 uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4050 return (GLsync)(uintptr_t)syncHandle;
4051}
4052
4053GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4054 GL2Encoder *ctx = (GL2Encoder *)self;
4055 return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4056}
4057
4058void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4059 GL2Encoder *ctx = (GL2Encoder *)self;
4060 ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4061}
4062
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004063void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) {
4064 GL2Encoder *ctx = (GL2Encoder *)self;
4065
4066 if (!sync) return;
4067
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004068 ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4069}
4070
4071GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4072 GL2Encoder *ctx = (GL2Encoder *)self;
4073 return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4074}
4075
4076void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4077 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004078
4079 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4080
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004081 return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004082}
4083
4084#define LIMIT_CASE(target, lim) \
4085 case target: \
4086 ctx->glGetIntegerv(ctx, lim, &limit); \
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004087 SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004088 break; \
4089
4090void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) {
4091 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004092 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004093
4094 GLint limit;
4095
4096 switch (target) {
4097 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4098 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4099 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4100 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4101 default:
4102 break;
4103 }
4104
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004105 const GLClientState::VertexAttribBindingVector& currBindings =
4106 state->currentVertexBufferBindings();
4107
4108 switch (target) {
4109 case GL_VERTEX_BINDING_DIVISOR:
4110 case GL_VERTEX_BINDING_OFFSET:
4111 case GL_VERTEX_BINDING_STRIDE:
4112 case GL_VERTEX_BINDING_BUFFER:
4113 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4114 break;
4115 default:
4116 break;
4117 }
4118
4119 switch (target) {
4120 case GL_VERTEX_BINDING_DIVISOR:
4121 *params = currBindings[index].divisor;
4122 return;
4123 case GL_VERTEX_BINDING_OFFSET:
4124 *params = currBindings[index].offset;
4125 return;
4126 case GL_VERTEX_BINDING_STRIDE:
4127 *params = currBindings[index].effectiveStride;
4128 return;
4129 case GL_VERTEX_BINDING_BUFFER:
4130 *params = currBindings[index].buffer;
4131 return;
4132 default:
4133 break;
4134 }
4135
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004136 ctx->m_glGetIntegeri_v_enc(self, target, index, params);
4137}
4138
4139void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
4140 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004141 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004142
4143 GLint limit;
4144
4145 switch (target) {
4146 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4147 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4148 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4149 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4150 default:
4151 break;
4152 }
4153
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004154 const GLClientState::VertexAttribBindingVector& currBindings =
4155 state->currentVertexBufferBindings();
4156
4157 switch (target) {
4158 case GL_VERTEX_BINDING_DIVISOR:
4159 case GL_VERTEX_BINDING_OFFSET:
4160 case GL_VERTEX_BINDING_STRIDE:
4161 case GL_VERTEX_BINDING_BUFFER:
4162 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4163 break;
4164 default:
4165 break;
4166 }
4167
4168 switch (target) {
4169 case GL_VERTEX_BINDING_DIVISOR:
4170 *params = currBindings[index].divisor;
4171 return;
4172 case GL_VERTEX_BINDING_OFFSET:
4173 *params = currBindings[index].offset;
4174 return;
4175 case GL_VERTEX_BINDING_STRIDE:
4176 *params = currBindings[index].effectiveStride;
4177 return;
4178 case GL_VERTEX_BINDING_BUFFER:
4179 *params = currBindings[index].buffer;
4180 return;
4181 default:
4182 break;
4183 }
4184
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004185 ctx->m_glGetInteger64i_v_enc(self, target, index, params);
4186}
4187
4188void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4189 GL2Encoder *ctx = (GL2Encoder *)self;
4190 ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4191 if (pname == GL_SHADER_SOURCE_LENGTH) {
4192 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4193 if (shaderData) {
4194 int totalLen = 0;
4195 for (int i = 0; i < shaderData->sources.size(); i++) {
4196 totalLen += shaderData->sources[i].size();
4197 }
4198 if (totalLen != 0) {
4199 *params = totalLen + 1; // account for null terminator
4200 }
4201 }
4202 }
4203}
4204
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004205void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) {
4206 GL2Encoder *ctx = (GL2Encoder*)self;
4207 GLClientState* state = ctx->m_state;
4208 GLSharedGroupPtr shared = ctx->m_shared;
4209
4210 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4211 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4212 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4213
4214 ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program);
4215 if (!state->currentProgram()) {
4216 state->setCurrentShaderProgram(program);
4217 }
4218}
4219
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004220GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4221
4222 GLint* length = NULL;
4223 GL2Encoder* ctx = (GL2Encoder*)self;
4224
4225 int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
4226 char *str = new char[len + 1];
4227 glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
4228
4229 // Do GLSharedGroup and location WorkARound-specific initialization
4230 // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4231 uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4232 ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
4233 ShaderData* sData = spData->shaderData;
4234
4235 if (!replaceSamplerExternalWith2D(str, sData)) {
4236 delete [] str;
4237 ctx->setError(GL_OUT_OF_MEMORY);
4238 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4239 return -1;
4240 }
4241
4242 GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
4243 delete [] str;
4244
4245 // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4246 GLint linkStatus = 0;
4247 ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4248 if (!linkStatus) {
4249 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4250 return -1;
4251 }
4252
4253 ctx->m_shared->associateGLShaderProgram(res, spDataId);
4254
4255 GLint numUniforms = 0;
4256 ctx->glGetProgramiv(ctx, res, GL_ACTIVE_UNIFORMS, &numUniforms);
4257 ctx->m_shared->initShaderProgramData(res, numUniforms);
4258
4259 GLint maxLength=0;
4260 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4261
4262 GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4263
4264 for (GLint i = 0; i < numUniforms; ++i) {
4265 ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4266 GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4267 ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4268 }
4269
4270 ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4271
4272 delete [] name;
4273
4274 return res;
4275}
4276
4277void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4278{
4279 GL2Encoder *ctx = (GL2Encoder*)self;
4280 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4281 ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4282}
4283
4284void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4285{
4286 GL2Encoder *ctx = (GL2Encoder*)self;
4287 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4288 ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4289}
4290
4291void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4292{
4293 GL2Encoder *ctx = (GL2Encoder*)self;
4294 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004295 ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004296
4297 GLClientState* state = ctx->m_state;
4298 GLSharedGroupPtr shared = ctx->m_shared;
4299 GLenum target;
4300
4301 if (shared->setSamplerUniform(program, location, v0, &target)) {
4302 GLenum origActiveTexture = state->getActiveTextureUnit();
4303 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4304 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4305 }
4306 state->setActiveTextureUnit(origActiveTexture);
4307 }
4308}
4309
4310void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4311{
4312 GL2Encoder *ctx = (GL2Encoder*)self;
4313 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4314 ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4315}
4316
4317void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4318{
4319 GL2Encoder *ctx = (GL2Encoder*)self;
4320 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4321 ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4322
4323 GLClientState* state = ctx->m_state;
4324 GLSharedGroupPtr shared = ctx->m_shared;
4325 GLenum target;
4326
4327 if (shared->setSamplerUniform(program, location, v0, &target)) {
4328 GLenum origActiveTexture = state->getActiveTextureUnit();
4329 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4330 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4331 }
4332 state->setActiveTextureUnit(origActiveTexture);
4333 }
4334}
4335
4336void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4337{
4338 GL2Encoder *ctx = (GL2Encoder*)self;
4339 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4340 ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
4341}
4342
4343void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
4344{
4345 GL2Encoder *ctx = (GL2Encoder*)self;
4346 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4347 ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
4348}
4349
4350void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4351{
4352 GL2Encoder *ctx = (GL2Encoder*)self;
4353 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4354 ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
4355}
4356
4357void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
4358{
4359 GL2Encoder *ctx = (GL2Encoder*)self;
4360 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4361 ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
4362}
4363
4364void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4365{
4366 GL2Encoder *ctx = (GL2Encoder*)self;
4367 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4368 ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
4369}
4370
4371void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
4372{
4373 GL2Encoder *ctx = (GL2Encoder*)self;
4374 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4375 ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
4376}
4377
4378void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4379{
4380 GL2Encoder *ctx = (GL2Encoder*)self;
4381 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4382 ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
4383}
4384
4385void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
4386{
4387 GL2Encoder *ctx = (GL2Encoder*)self;
4388 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4389 ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
4390}
4391
4392void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4393{
4394 GL2Encoder *ctx = (GL2Encoder*)self;
4395 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4396 ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
4397}
4398
4399void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
4400{
4401 GL2Encoder *ctx = (GL2Encoder*)self;
4402 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4403 ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
4404}
4405
4406void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4407{
4408 GL2Encoder *ctx = (GL2Encoder*)self;
4409 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4410 ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
4411}
4412
4413void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
4414{
4415 GL2Encoder *ctx = (GL2Encoder*)self;
4416 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4417 ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
4418}
4419
4420void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4421{
4422 GL2Encoder *ctx = (GL2Encoder*)self;
4423 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4424 ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
4425}
4426
4427void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
4428{
4429 GL2Encoder *ctx = (GL2Encoder*)self;
4430 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4431 ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
4432}
4433
4434void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4435{
4436 GL2Encoder *ctx = (GL2Encoder*)self;
4437 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4438 ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
4439}
4440
4441void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
4442{
4443 GL2Encoder *ctx = (GL2Encoder*)self;
4444 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4445 ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
4446}
4447
4448void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4449{
4450 GL2Encoder *ctx = (GL2Encoder*)self;
4451 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4452 ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
4453}
4454
4455void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
4456{
4457 GL2Encoder *ctx = (GL2Encoder*)self;
4458 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4459 ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
4460}
4461
4462void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4463{
4464 GL2Encoder *ctx = (GL2Encoder*)self;
4465 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4466 ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
4467}
4468
4469void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4470{
4471 GL2Encoder *ctx = (GL2Encoder*)self;
4472 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4473 ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
4474}
4475
4476void GL2Encoder::s_glProgramUniformMatrix2x3fv(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_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
4481}
4482
4483void GL2Encoder::s_glProgramUniformMatrix2x4fv(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_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
4488}
4489
4490void GL2Encoder::s_glProgramUniformMatrix3fv(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_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
4495}
4496
4497void GL2Encoder::s_glProgramUniformMatrix3x2fv(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_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
4502}
4503
4504void GL2Encoder::s_glProgramUniformMatrix3x4fv(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_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
4509}
4510
4511void GL2Encoder::s_glProgramUniformMatrix4fv(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_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
4516}
4517
4518void GL2Encoder::s_glProgramUniformMatrix4x2fv(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_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
4523}
4524
4525void GL2Encoder::s_glProgramUniformMatrix4x3fv(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_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
4530}
4531
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004532void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) {
4533 GL2Encoder* ctx = (GL2Encoder*)self;
4534 ctx->m_glProgramParameteri_enc(self, program, pname, value);
4535}
4536
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004537void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
4538{
4539 GL2Encoder *ctx = (GL2Encoder*)self;
4540 GLClientState* state = ctx->m_state;
4541 GLSharedGroupPtr shared = ctx->m_shared;
4542
4543 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4544 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4545 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4546
4547 ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
4548 state->associateProgramWithPipeline(program, pipeline);
4549
4550 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4551 if (state->currentProgram()) {
4552 return;
4553 }
4554
4555 // Otherwise, update host texture 2D bindings.
4556 ctx->updateHostTexture2DBindingsFromProgramData(program);
4557}
4558
4559void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
4560{
4561 GL2Encoder *ctx = (GL2Encoder*)self;
4562 GLClientState* state = ctx->m_state;
4563
4564 ctx->m_glBindProgramPipeline_enc(self, pipeline);
4565
4566 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4567 if (!pipeline || state->currentProgram()) {
4568 return;
4569 }
4570
4571 GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
4572 for (; it != state->programPipelineEnd(); ++it) {
4573 if (it->second == pipeline) {
4574 ctx->updateHostTexture2DBindingsFromProgramData(it->first);
4575 }
4576 }
4577}
4578
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004579void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
4580 GL2Encoder *ctx = (GL2Encoder*)self;
4581 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4582 if (bufSize == 0) {
4583 if (length) *length = 0;
4584 return;
4585 }
4586
4587 // Avoid modifying |name| if |*length| < bufSize.
4588 GLint* intermediate = new GLint[bufSize];
4589 GLsizei* myLength = length ? length : new GLsizei;
4590 bool needFreeLength = length == NULL;
4591
4592 ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
4593 GLsizei writtenInts = *myLength;
4594 memcpy(params, intermediate, writtenInts * sizeof(GLint));
4595
4596 delete [] intermediate;
4597 if (needFreeLength)
4598 delete myLength;
4599}
4600
4601GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
4602 GL2Encoder *ctx = (GL2Encoder*)self;
4603 return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
4604}
4605
4606GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
4607 GL2Encoder *ctx = (GL2Encoder*)self;
4608 return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
4609}
4610
4611void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
4612 GL2Encoder *ctx = (GL2Encoder*)self;
4613 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4614 if (bufSize == 0) {
4615 if (length) *length = 0;
4616 return;
4617 }
4618
4619 // Avoid modifying |name| if |*length| < bufSize.
4620 char* intermediate = new char[bufSize];
4621 GLsizei* myLength = length ? length : new GLsizei;
4622 bool needFreeLength = length == NULL;
4623
4624 ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
4625 GLsizei writtenStrLen = *myLength;
4626 memcpy(name, intermediate, writtenStrLen + 1);
4627
4628 delete [] intermediate;
4629 if (needFreeLength)
4630 delete myLength;
4631}
4632
4633void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
4634 GL2Encoder *ctx = (GL2Encoder*)self;
4635 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4636 if (bufSize == 0) {
4637 if (length) *length = 0;
4638 return;
4639 }
4640
4641 // Avoid modifying |infoLog| if |*length| < bufSize.
4642 GLchar* intermediate = new GLchar[bufSize];
4643 GLsizei* myLength = length ? length : new GLsizei;
4644 bool needFreeLength = length == NULL;
4645
4646 ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
4647 GLsizei writtenStrLen = *myLength;
4648 memcpy(infoLog, intermediate, writtenStrLen + 1);
4649
4650 delete [] intermediate;
4651 if (needFreeLength)
4652 delete myLength;
4653}
4654
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004655void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
4656 GL2Encoder *ctx = (GL2Encoder*)self;
4657 GLClientState* state = ctx->m_state;
4658
Lingfeng Yang07289902017-01-27 12:26:19 -08004659 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004660 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4661
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004662 state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false);
4663 ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset);
4664}
4665
4666void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
4667 GL2Encoder *ctx = (GL2Encoder*)self;
4668 GLClientState* state = ctx->m_state;
4669
Lingfeng Yang07289902017-01-27 12:26:19 -08004670 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004671 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4672
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004673 state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true);
4674 ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset);
4675}
4676
4677void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004678 GL2Encoder *ctx = (GL2Encoder*)self;
4679 GLClientState* state = ctx->m_state;
4680
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004681 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4682
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004683 state->setVertexBindingDivisor(bindingindex, divisor);
4684 ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor);
4685}
4686
4687void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) {
4688 GL2Encoder *ctx = (GL2Encoder*)self;
4689 GLClientState* state = ctx->m_state;
Lingfeng Yang07289902017-01-27 12:26:19 -08004690 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004691 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004692
4693 state->setVertexAttribBinding(attribindex, bindingindex);
4694 ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex);
4695}
4696
4697void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
4698 GL2Encoder *ctx = (GL2Encoder*)self;
4699 GLClientState* state = ctx->m_state;
4700
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004701 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
4702
4703 GLint maxStride;
4704 ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
4705 SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE);
4706
4707 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4708
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004709 state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride);
4710 ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride);
4711}
4712
4713void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) {
4714 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004715 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004716
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004717 bool hasClientArrays = false;
4718 ctx->getVBOUsage(&hasClientArrays, NULL);
4719
4720 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
4721 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4722 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
4723
4724 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004725 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004726 // BufferData* buf = ctx->getBufferData(target);
4727 // if (buf) {
4728 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
4729 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004730 ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect);
4731 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004732 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
4733 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004734 ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize);
4735 }
4736}
4737
4738void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) {
4739 GL2Encoder *ctx = (GL2Encoder*)self;
4740
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004741 GLClientState* state = ctx->m_state;
4742
4743 bool hasClientArrays = false;
4744 ctx->getVBOUsage(&hasClientArrays, NULL);
4745
4746 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
4747 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4748 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
4749
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004750 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004751
4752 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004753 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004754 // BufferData* buf = ctx->getBufferData(target);
4755 // if (buf) {
4756 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
4757 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004758 ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect);
4759 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004760 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
4761 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004762 ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize);
4763 }
4764
4765}
4766
4767void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
4768 GL2Encoder *ctx = (GL2Encoder*)self;
4769 GLClientState* state = ctx->m_state;
4770
4771 SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
4772 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
4773 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
4774 SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
4775 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004776 GLint max_samples;
4777 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
4778 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004779
4780 state->setBoundTextureInternalFormat(target, internalformat);
4781 state->setBoundTextureDims(target, 0, width, height, 1);
4782 state->setBoundTextureImmutableFormat(target);
4783 state->setBoundTextureSamples(target, samples);
4784
4785 ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
4786}
4787