blob: 5a3a62da2b78c38957364c8ed78e1c6c31ddcf19 [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 Yangf6cc30a2016-12-02 17:43:01 +000042#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); \
44 ctx->setError(err); \
45 return; \
46 }
47
48
49#define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) { \
50 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
51 ctx->setError(err); \
52 return ret; \
53 }
54
55
Yahan Zhoub7f09082016-03-10 11:45:02 -080056GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
57 : gl2_encoder_context_t(stream, protocol)
keunyoungb85b2752013-03-08 12:28:03 -080058{
Lingfeng Yange6556dc2017-01-09 12:04:12 -080059 m_currMajorVersion = 2;
60 m_currMinorVersion = 0;
keunyoungb85b2752013-03-08 12:28:03 -080061 m_initialized = false;
62 m_state = NULL;
63 m_error = GL_NO_ERROR;
64 m_num_compressedTextureFormats = 0;
Lizhe Liue41f4ef2015-05-27 11:13:23 +080065 m_max_cubeMapTextureSize = 0;
66 m_max_renderBufferSize = 0;
67 m_max_textureSize = 0;
Lingfeng Yang46153ab2017-01-09 13:37:22 -080068 m_max_3d_textureSize = 0;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -080069 m_max_vertexAttribStride = 0;
keunyoungb85b2752013-03-08 12:28:03 -080070 m_compressedTextureFormats = NULL;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010071
Lingfeng Yang46153ab2017-01-09 13:37:22 -080072 m_ssbo_offset_align = 0;
73 m_ubo_offset_align = 0;
74
Lingfeng Yangde51dfb2016-10-17 22:48:59 -070075 m_drawCallFlushCount = 0;
76 m_primitiveRestartEnabled = false;
77 m_primitiveRestartIndex = 0;
78
keunyoungb85b2752013-03-08 12:28:03 -080079 //overrides
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010080#define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name
Lingfeng Yange6556dc2017-01-09 12:04:12 -080081#define OVERRIDE_CUSTOM(name) this-> name = &s_##name
82#define OVERRIDEWITH(name, target) do { \
83 m_##target##_enc = this-> target; \
84 this-> target = &s_##name; \
85} while(0)
86#define OVERRIDEOES(name) OVERRIDEWITH(name, name##OES)
bohu56bf82f2014-10-17 15:35:48 -070087
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010088 OVERRIDE(glFlush);
89 OVERRIDE(glPixelStorei);
90 OVERRIDE(glGetString);
91 OVERRIDE(glBindBuffer);
92 OVERRIDE(glBufferData);
93 OVERRIDE(glBufferSubData);
94 OVERRIDE(glDeleteBuffers);
95 OVERRIDE(glDrawArrays);
96 OVERRIDE(glDrawElements);
97 OVERRIDE(glGetIntegerv);
98 OVERRIDE(glGetFloatv);
99 OVERRIDE(glGetBooleanv);
100 OVERRIDE(glVertexAttribPointer);
101 OVERRIDE(glEnableVertexAttribArray);
102 OVERRIDE(glDisableVertexAttribArray);
103 OVERRIDE(glGetVertexAttribiv);
104 OVERRIDE(glGetVertexAttribfv);
105 OVERRIDE(glGetVertexAttribPointerv);
keunyoungb85b2752013-03-08 12:28:03 -0800106
Bo Hu73568cd2015-01-20 16:29:50 -0800107 this->glShaderBinary = &s_glShaderBinary;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100108 this->glShaderSource = &s_glShaderSource;
109 this->glFinish = &s_glFinish;
keunyoungb85b2752013-03-08 12:28:03 -0800110
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100111 OVERRIDE(glGetError);
112 OVERRIDE(glLinkProgram);
113 OVERRIDE(glDeleteProgram);
114 OVERRIDE(glGetUniformiv);
115 OVERRIDE(glGetUniformfv);
116 OVERRIDE(glCreateProgram);
117 OVERRIDE(glCreateShader);
118 OVERRIDE(glDeleteShader);
119 OVERRIDE(glAttachShader);
120 OVERRIDE(glDetachShader);
121 OVERRIDE(glGetAttachedShaders);
122 OVERRIDE(glGetShaderSource);
123 OVERRIDE(glGetShaderInfoLog);
124 OVERRIDE(glGetProgramInfoLog);
125
126 OVERRIDE(glGetUniformLocation);
127 OVERRIDE(glUseProgram);
128
129 OVERRIDE(glUniform1f);
130 OVERRIDE(glUniform1fv);
131 OVERRIDE(glUniform1i);
132 OVERRIDE(glUniform1iv);
133 OVERRIDE(glUniform2f);
134 OVERRIDE(glUniform2fv);
135 OVERRIDE(glUniform2i);
136 OVERRIDE(glUniform2iv);
137 OVERRIDE(glUniform3f);
138 OVERRIDE(glUniform3fv);
139 OVERRIDE(glUniform3i);
140 OVERRIDE(glUniform3iv);
141 OVERRIDE(glUniform4f);
142 OVERRIDE(glUniform4fv);
143 OVERRIDE(glUniform4i);
144 OVERRIDE(glUniform4iv);
145 OVERRIDE(glUniformMatrix2fv);
146 OVERRIDE(glUniformMatrix3fv);
147 OVERRIDE(glUniformMatrix4fv);
148
149 OVERRIDE(glActiveTexture);
150 OVERRIDE(glBindTexture);
151 OVERRIDE(glDeleteTextures);
152 OVERRIDE(glGetTexParameterfv);
153 OVERRIDE(glGetTexParameteriv);
154 OVERRIDE(glTexParameterf);
155 OVERRIDE(glTexParameterfv);
156 OVERRIDE(glTexParameteri);
157 OVERRIDE(glTexParameteriv);
bohu26a92982014-11-25 16:50:37 -0800158 OVERRIDE(glTexImage2D);
Yahan Zhou2a208292016-06-22 15:36:04 -0700159 OVERRIDE(glTexSubImage2D);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -0700160 OVERRIDE(glCopyTexImage2D);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700161
162 OVERRIDE(glGenRenderbuffers);
163 OVERRIDE(glDeleteRenderbuffers);
164 OVERRIDE(glBindRenderbuffer);
Lingfeng Yang69066602016-04-12 09:29:11 -0700165 OVERRIDE(glRenderbufferStorage);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700166 OVERRIDE(glFramebufferRenderbuffer);
167
168 OVERRIDE(glGenFramebuffers);
169 OVERRIDE(glDeleteFramebuffers);
170 OVERRIDE(glBindFramebuffer);
171 OVERRIDE(glFramebufferTexture2D);
172 OVERRIDE(glFramebufferTexture3DOES);
173 OVERRIDE(glGetFramebufferAttachmentParameteriv);
Lingfeng Yang69066602016-04-12 09:29:11 -0700174
175 OVERRIDE(glCheckFramebufferStatus);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800176
177 OVERRIDE(glGenVertexArrays);
178 OVERRIDE(glDeleteVertexArrays);
179 OVERRIDE(glBindVertexArray);
180 OVERRIDEOES(glGenVertexArrays);
181 OVERRIDEOES(glDeleteVertexArrays);
182 OVERRIDEOES(glBindVertexArray);
183
184 OVERRIDE_CUSTOM(glMapBufferRange);
185 OVERRIDE_CUSTOM(glUnmapBuffer);
186 OVERRIDE_CUSTOM(glFlushMappedBufferRange);
187
188 OVERRIDE(glCompressedTexImage2D);
189 OVERRIDE(glCompressedTexSubImage2D);
190
191 OVERRIDE(glBindBufferRange);
192 OVERRIDE(glBindBufferBase);
193
194 OVERRIDE(glCopyBufferSubData);
195
196 OVERRIDE(glGetBufferParameteriv);
197 OVERRIDE(glGetBufferParameteri64v);
198 OVERRIDE(glGetBufferPointerv);
199
200 OVERRIDE_CUSTOM(glGetUniformIndices);
201
202 OVERRIDE(glUniform1ui);
203 OVERRIDE(glUniform2ui);
204 OVERRIDE(glUniform3ui);
205 OVERRIDE(glUniform4ui);
206 OVERRIDE(glUniform1uiv);
207 OVERRIDE(glUniform2uiv);
208 OVERRIDE(glUniform3uiv);
209 OVERRIDE(glUniform4uiv);
210 OVERRIDE(glUniformMatrix2x3fv);
211 OVERRIDE(glUniformMatrix3x2fv);
212 OVERRIDE(glUniformMatrix2x4fv);
213 OVERRIDE(glUniformMatrix4x2fv);
214 OVERRIDE(glUniformMatrix3x4fv);
215 OVERRIDE(glUniformMatrix4x3fv);
216
217 OVERRIDE(glGetUniformuiv);
218 OVERRIDE(glGetActiveUniformBlockiv);
219
220 OVERRIDE(glGetVertexAttribIiv);
221 OVERRIDE(glGetVertexAttribIuiv);
222
223 OVERRIDE_CUSTOM(glVertexAttribIPointer);
224
225 OVERRIDE(glVertexAttribDivisor);
226
227 OVERRIDE(glRenderbufferStorageMultisample);
228 OVERRIDE(glDrawBuffers);
229 OVERRIDE(glReadBuffer);
230 OVERRIDE(glFramebufferTextureLayer);
231 OVERRIDE(glTexStorage2D);
232
233 OVERRIDE_CUSTOM(glTransformFeedbackVaryings);
234 OVERRIDE(glBeginTransformFeedback);
235 OVERRIDE(glEndTransformFeedback);
236 OVERRIDE(glPauseTransformFeedback);
237 OVERRIDE(glResumeTransformFeedback);
238
239 OVERRIDE(glTexImage3D);
240 OVERRIDE(glTexSubImage3D);
241 OVERRIDE(glTexStorage3D);
242 OVERRIDE(glCompressedTexImage3D);
243 OVERRIDE(glCompressedTexSubImage3D);
244
245 OVERRIDE(glDrawArraysInstanced);
246 OVERRIDE_CUSTOM(glDrawElementsInstanced);
247 OVERRIDE_CUSTOM(glDrawRangeElements);
248
249 OVERRIDE_CUSTOM(glGetStringi);
250 OVERRIDE(glGetProgramBinary);
251 OVERRIDE(glReadPixels);
252
253 OVERRIDE(glEnable);
254 OVERRIDE(glDisable);
255 OVERRIDE(glClearBufferiv);
256 OVERRIDE(glClearBufferuiv);
257 OVERRIDE(glClearBufferfv);
258 OVERRIDE(glBlitFramebuffer);
259 OVERRIDE_CUSTOM(glGetInternalformativ);
260
261 OVERRIDE(glGenerateMipmap);
262
263 OVERRIDE(glBindSampler);
264
Lingfeng Yangf000ab42017-01-11 18:31:38 -0800265 OVERRIDE_CUSTOM(glFenceSync);
266 OVERRIDE_CUSTOM(glClientWaitSync);
267 OVERRIDE_CUSTOM(glWaitSync);
268 OVERRIDE_CUSTOM(glDeleteSync);
269 OVERRIDE_CUSTOM(glIsSync);
270 OVERRIDE_CUSTOM(glGetSynciv);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800271
272 OVERRIDE(glGetIntegeri_v);
273 OVERRIDE(glGetInteger64i_v);
274
275 OVERRIDE(glGetShaderiv);
276
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800277 OVERRIDE(glActiveShaderProgram);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800278 OVERRIDE_CUSTOM(glCreateShaderProgramv);
279 OVERRIDE(glProgramUniform1f);
280 OVERRIDE(glProgramUniform1fv);
281 OVERRIDE(glProgramUniform1i);
282 OVERRIDE(glProgramUniform1iv);
283 OVERRIDE(glProgramUniform1ui);
284 OVERRIDE(glProgramUniform1uiv);
285 OVERRIDE(glProgramUniform2f);
286 OVERRIDE(glProgramUniform2fv);
287 OVERRIDE(glProgramUniform2i);
288 OVERRIDE(glProgramUniform2iv);
289 OVERRIDE(glProgramUniform2ui);
290 OVERRIDE(glProgramUniform2uiv);
291 OVERRIDE(glProgramUniform3f);
292 OVERRIDE(glProgramUniform3fv);
293 OVERRIDE(glProgramUniform3i);
294 OVERRIDE(glProgramUniform3iv);
295 OVERRIDE(glProgramUniform3ui);
296 OVERRIDE(glProgramUniform3uiv);
297 OVERRIDE(glProgramUniform4f);
298 OVERRIDE(glProgramUniform4fv);
299 OVERRIDE(glProgramUniform4i);
300 OVERRIDE(glProgramUniform4iv);
301 OVERRIDE(glProgramUniform4ui);
302 OVERRIDE(glProgramUniform4uiv);
303 OVERRIDE(glProgramUniformMatrix2fv);
304 OVERRIDE(glProgramUniformMatrix2x3fv);
305 OVERRIDE(glProgramUniformMatrix2x4fv);
306 OVERRIDE(glProgramUniformMatrix3fv);
307 OVERRIDE(glProgramUniformMatrix3x2fv);
308 OVERRIDE(glProgramUniformMatrix3x4fv);
309 OVERRIDE(glProgramUniformMatrix4fv);
310 OVERRIDE(glProgramUniformMatrix4x2fv);
311 OVERRIDE(glProgramUniformMatrix4x3fv);
312
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800313 OVERRIDE(glProgramParameteri);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800314 OVERRIDE(glUseProgramStages);
315 OVERRIDE(glBindProgramPipeline);
316
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800317 OVERRIDE(glGetProgramResourceiv);
318 OVERRIDE(glGetProgramResourceIndex);
319 OVERRIDE(glGetProgramResourceLocation);
320 OVERRIDE(glGetProgramResourceName);
321 OVERRIDE(glGetProgramPipelineInfoLog);
322
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800323 OVERRIDE(glVertexAttribFormat);
324 OVERRIDE(glVertexAttribIFormat);
325 OVERRIDE(glVertexBindingDivisor);
326 OVERRIDE(glVertexAttribBinding);
327 OVERRIDE(glBindVertexBuffer);
328
329 OVERRIDE_CUSTOM(glDrawArraysIndirect);
330 OVERRIDE_CUSTOM(glDrawElementsIndirect);
331
332 OVERRIDE(glTexStorage2DMultisample);
keunyoungb85b2752013-03-08 12:28:03 -0800333}
334
335GL2Encoder::~GL2Encoder()
336{
337 delete m_compressedTextureFormats;
338}
339
340GLenum GL2Encoder::s_glGetError(void * self)
341{
342 GL2Encoder *ctx = (GL2Encoder *)self;
343 GLenum err = ctx->getError();
344 if(err != GL_NO_ERROR) {
345 ctx->setError(GL_NO_ERROR);
346 return err;
347 }
348
349 return ctx->m_glGetError_enc(self);
Yahan Zhouae30fe82016-08-10 21:15:45 +0000350
keunyoungb85b2752013-03-08 12:28:03 -0800351}
352
353void GL2Encoder::s_glFlush(void *self)
354{
355 GL2Encoder *ctx = (GL2Encoder *) self;
356 ctx->m_glFlush_enc(self);
357 ctx->m_stream->flush();
358}
359
360const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
361{
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800362 GL2Encoder *ctx = (GL2Encoder *)self;
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100363
keunyoungb85b2752013-03-08 12:28:03 -0800364 GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800365 RET_AND_SET_ERROR_IF(
366 name != GL_VENDOR &&
367 name != GL_RENDERER &&
368 name != GL_VERSION &&
369 name != GL_EXTENSIONS,
370 GL_INVALID_ENUM,
371 retval);
keunyoungb85b2752013-03-08 12:28:03 -0800372 switch(name) {
373 case GL_VENDOR:
374 retval = gVendorString;
375 break;
376 case GL_RENDERER:
377 retval = gRendererString;
378 break;
379 case GL_VERSION:
380 retval = gVersionString;
381 break;
382 case GL_EXTENSIONS:
383 retval = gExtensionsString;
384 break;
385 }
386 return retval;
387}
388
389void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
390{
391 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800392 SET_ERROR_IF(!GLESv2Validation::pixelStoreParam(ctx, param), GL_INVALID_ENUM);
393 SET_ERROR_IF(!GLESv2Validation::pixelStoreValue(param, value), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800394 ctx->m_glPixelStorei_enc(ctx, param, value);
395 assert(ctx->m_state != NULL);
396 ctx->m_state->setPixelStore(param, value);
397}
keunyoungb85b2752013-03-08 12:28:03 -0800398void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
399{
400 GL2Encoder *ctx = (GL2Encoder *) self;
401 assert(ctx->m_state != NULL);
402 ctx->m_state->bindBuffer(target, id);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800403 ctx->m_state->addBuffer(id);
keunyoungb85b2752013-03-08 12:28:03 -0800404 // TODO set error state if needed;
405 ctx->m_glBindBuffer_enc(self, target, id);
406}
407
408void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
409{
410 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800411 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800412 GLuint bufferId = ctx->m_state->getBuffer(target);
413 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
414 SET_ERROR_IF(size<0, GL_INVALID_VALUE);
415
416 ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800417 ctx->m_shared->setBufferUsage(bufferId, usage);
keunyoungb85b2752013-03-08 12:28:03 -0800418 ctx->m_glBufferData_enc(self, target, size, data, usage);
419}
420
421void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
422{
423 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800424 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800425 GLuint bufferId = ctx->m_state->getBuffer(target);
426 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800427 SET_ERROR_IF(ctx->isBufferTargetMapped(target), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800428
429 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
430 SET_ERROR_IF(res, res);
431
432 ctx->m_glBufferSubData_enc(self, target, offset, size, data);
433}
434
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800435void GL2Encoder::s_glGenBuffers(void* self, GLsizei n, GLuint* buffers) {
436 GL2Encoder *ctx = (GL2Encoder *) self;
437 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
438 ctx->m_glGenBuffers_enc(self, n, buffers);
439 for (int i = 0; i < n; i++) {
440 ctx->m_state->addBuffer(buffers[i]);
441 }
442}
443
keunyoungb85b2752013-03-08 12:28:03 -0800444void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
445{
446 GL2Encoder *ctx = (GL2Encoder *) self;
447 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
448 for (int i=0; i<n; i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800449 // Technically if the buffer is mapped, we should unmap it, but we won't
450 // use it anymore after this :)
keunyoungb85b2752013-03-08 12:28:03 -0800451 ctx->m_shared->deleteBufferData(buffers[i]);
bohub0f0cdf2014-11-06 18:08:07 -0800452 ctx->m_state->unBindBuffer(buffers[i]);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800453 ctx->m_state->removeBuffer(buffers[i]);
keunyoungb85b2752013-03-08 12:28:03 -0800454 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
455 }
456}
457
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700458static bool isValidVertexAttribIndex(void *self, GLuint indx)
459{
460 GL2Encoder *ctx = (GL2Encoder *) self;
461 GLint maxIndex;
462 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
463 return indx < maxIndex;
464}
465
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100466void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
keunyoungb85b2752013-03-08 12:28:03 -0800467{
468 GL2Encoder *ctx = (GL2Encoder *)self;
469 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700470 SET_ERROR_IF(!isValidVertexAttribIndex(self, indx), GL_INVALID_VALUE);
471 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800472 SET_ERROR_IF(!GLESv2Validation::vertexAttribType(ctx, type), GL_INVALID_ENUM);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700473 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800474 SET_ERROR_IF((type == GL_INT_2_10_10_10_REV ||
475 type == GL_UNSIGNED_INT_2_10_10_10_REV) &&
476 size != 4,
477 GL_INVALID_OPERATION);
478 ctx->m_state->setVertexAttribBinding(indx, indx);
479 ctx->m_state->setVertexAttribFormat(indx, size, type, normalized, 0, false);
480
481 GLsizei effectiveStride = stride;
482 if (stride == 0) {
483 effectiveStride = glSizeof(type) * size;
484 switch (type) {
485 case GL_INT_2_10_10_10_REV:
486 case GL_UNSIGNED_INT_2_10_10_10_REV:
487 effectiveStride /= 4;
488 break;
489 default:
490 break;
491 }
492 }
493
494 ctx->m_state->bindIndexedBuffer(0, indx, ctx->m_state->currentArrayVbo(), (uintptr_t)ptr, 0, stride, effectiveStride);
495
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800496 if (ctx->m_state->currentArrayVbo() != 0) {
497 ctx->glVertexAttribPointerOffset(ctx, indx, size, type, normalized, stride, (uintptr_t)ptr);
498 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800499 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && ptr, GL_INVALID_OPERATION);
500 // wait for client-array handler
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800501 }
keunyoungb85b2752013-03-08 12:28:03 -0800502}
503
504void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
505{
506 GL2Encoder *ctx = (GL2Encoder *) self;
507 assert(ctx->m_state != NULL);
508 GLClientState* state = ctx->m_state;
509
510 switch (param) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800511 case GL_MAJOR_VERSION:
512 *ptr = ctx->m_currMajorVersion;
513 break;
514 case GL_MINOR_VERSION:
515 *ptr = ctx->m_currMinorVersion;
516 break;
keunyoungb85b2752013-03-08 12:28:03 -0800517 case GL_NUM_SHADER_BINARY_FORMATS:
518 *ptr = 0;
519 break;
520 case GL_SHADER_BINARY_FORMATS:
521 // do nothing
522 break;
523
524 case GL_COMPRESSED_TEXTURE_FORMATS: {
525 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
526 if (ctx->m_num_compressedTextureFormats > 0 &&
527 compressedTextureFormats != NULL) {
528 memcpy(ptr, compressedTextureFormats,
529 ctx->m_num_compressedTextureFormats * sizeof(GLint));
530 }
531 break;
532 }
533
534 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
535 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
536 case GL_MAX_TEXTURE_IMAGE_UNITS:
537 ctx->m_glGetIntegerv_enc(self, param, ptr);
538 *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
539 break;
540
541 case GL_TEXTURE_BINDING_2D:
542 *ptr = state->getBoundTexture(GL_TEXTURE_2D);
543 break;
544 case GL_TEXTURE_BINDING_EXTERNAL_OES:
545 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
546 break;
547
Lingfeng Yangb0176982016-03-01 21:27:49 -0800548 case GL_MAX_VERTEX_ATTRIBS:
549 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
550 ctx->m_glGetIntegerv_enc(self, param, ptr);
551 ctx->m_state->setMaxVertexAttribs(*ptr);
Yahan Zhoua5c36842016-06-01 12:49:39 -0700552 }
553 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800554 case GL_MAX_VERTEX_ATTRIB_STRIDE:
555 if (ctx->m_max_vertexAttribStride != 0) {
556 *ptr = ctx->m_max_vertexAttribStride;
557 } else {
558 ctx->m_glGetIntegerv_enc(self, param, ptr);
559 ctx->m_max_vertexAttribStride = *ptr;
560 }
561 break;
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800562 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
563 if (ctx->m_max_cubeMapTextureSize != 0) {
564 *ptr = ctx->m_max_cubeMapTextureSize;
565 } else {
566 ctx->m_glGetIntegerv_enc(self, param, ptr);
567 ctx->m_max_cubeMapTextureSize = *ptr;
568 }
569 break;
570 case GL_MAX_RENDERBUFFER_SIZE:
571 if (ctx->m_max_renderBufferSize != 0) {
572 *ptr = ctx->m_max_renderBufferSize;
573 } else {
574 ctx->m_glGetIntegerv_enc(self, param, ptr);
575 ctx->m_max_renderBufferSize = *ptr;
576 }
577 break;
578 case GL_MAX_TEXTURE_SIZE:
579 if (ctx->m_max_textureSize != 0) {
580 *ptr = ctx->m_max_textureSize;
581 } else {
582 ctx->m_glGetIntegerv_enc(self, param, ptr);
583 ctx->m_max_textureSize = *ptr;
Lingfeng Yangb0176982016-03-01 21:27:49 -0800584 }
585 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800586 case GL_MAX_3D_TEXTURE_SIZE:
587 if (ctx->m_max_3d_textureSize != 0) {
588 *ptr = ctx->m_max_3d_textureSize;
589 } else {
590 ctx->m_glGetIntegerv_enc(self, param, ptr);
591 ctx->m_max_3d_textureSize = *ptr;
592 }
593 break;
594 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
595 if (ctx->m_ssbo_offset_align != 0) {
596 *ptr = ctx->m_ssbo_offset_align;
597 } else {
598 ctx->m_glGetIntegerv_enc(self, param, ptr);
599 ctx->m_ssbo_offset_align = *ptr;
600 }
601 break;
602 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
603 if (ctx->m_ubo_offset_align != 0) {
604 *ptr = ctx->m_ubo_offset_align;
605 } else {
606 ctx->m_glGetIntegerv_enc(self, param, ptr);
607 ctx->m_ubo_offset_align = *ptr;
608 }
609 break;
610 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
611 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
612 case GL_MAX_SAMPLES:
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800613 case GL_MAX_COLOR_TEXTURE_SAMPLES:
614 case GL_MAX_INTEGER_SAMPLES:
615 case GL_MAX_DEPTH_TEXTURE_SAMPLES:
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800616 *ptr = 4;
617 break;
keunyoungb85b2752013-03-08 12:28:03 -0800618 default:
619 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
620 ctx->m_glGetIntegerv_enc(self, param, ptr);
621 }
622 break;
623 }
624}
625
626
627void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
628{
629 GL2Encoder *ctx = (GL2Encoder *)self;
630 assert(ctx->m_state != NULL);
631 GLClientState* state = ctx->m_state;
632
633 switch (param) {
634 case GL_NUM_SHADER_BINARY_FORMATS:
635 *ptr = 0;
636 break;
637 case GL_SHADER_BINARY_FORMATS:
638 // do nothing
639 break;
640
641 case GL_COMPRESSED_TEXTURE_FORMATS: {
642 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
643 if (ctx->m_num_compressedTextureFormats > 0 &&
644 compressedTextureFormats != NULL) {
645 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
646 ptr[i] = (GLfloat) compressedTextureFormats[i];
647 }
648 }
649 break;
650 }
651
652 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
653 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
654 case GL_MAX_TEXTURE_IMAGE_UNITS:
655 ctx->m_glGetFloatv_enc(self, param, ptr);
656 *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
657 break;
658
659 case GL_TEXTURE_BINDING_2D:
660 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
661 break;
662 case GL_TEXTURE_BINDING_EXTERNAL_OES:
663 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
664 break;
665
666 default:
667 if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
668 ctx->m_glGetFloatv_enc(self, param, ptr);
669 }
670 break;
671 }
672}
673
674
675void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
676{
677 GL2Encoder *ctx = (GL2Encoder *)self;
678 assert(ctx->m_state != NULL);
679 GLClientState* state = ctx->m_state;
680
681 switch (param) {
682 case GL_NUM_SHADER_BINARY_FORMATS:
683 *ptr = GL_FALSE;
684 break;
685 case GL_SHADER_BINARY_FORMATS:
686 // do nothing
687 break;
688
689 case GL_COMPRESSED_TEXTURE_FORMATS: {
690 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
691 if (ctx->m_num_compressedTextureFormats > 0 &&
692 compressedTextureFormats != NULL) {
693 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
694 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
695 }
696 }
697 break;
698 }
699
700 case GL_TEXTURE_BINDING_2D:
701 *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
702 break;
703 case GL_TEXTURE_BINDING_EXTERNAL_OES:
704 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
705 ? GL_TRUE : GL_FALSE;
706 break;
707
708 default:
709 if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
710 ctx->m_glGetBooleanv_enc(self, param, ptr);
711 }
bohu05101d22014-11-17 16:28:42 -0800712 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
keunyoungb85b2752013-03-08 12:28:03 -0800713 break;
714 }
715}
716
717
718void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
719{
720 GL2Encoder *ctx = (GL2Encoder *)self;
721 assert(ctx->m_state);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700722 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800723 ctx->m_glEnableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800724 ctx->m_state->enable(index, 1);
725}
726
727void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
728{
729 GL2Encoder *ctx = (GL2Encoder *)self;
730 assert(ctx->m_state);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700731 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800732 ctx->m_glDisableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800733 ctx->m_state->enable(index, 0);
734}
735
736
737void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
738{
739 GL2Encoder *ctx = (GL2Encoder *)self;
740 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700741 GLint maxIndex;
742 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
743 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800744
745 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
746 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
747 }
748}
749
750void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
751{
752 GL2Encoder *ctx = (GL2Encoder *)self;
753 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700754 GLint maxIndex;
755 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
756 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800757
758 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
759 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
760 }
761}
762
763void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
764{
765 GL2Encoder *ctx = (GL2Encoder *)self;
766 if (ctx->m_state == NULL) return;
Lingfeng Yang5e100432016-04-08 12:46:42 -0700767 GLint maxIndex;
768 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
769 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
770 SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100771 (void)pname;
772
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800773 *pointer = (GLvoid*)(ctx->m_state->getCurrAttributeBindingInfo(index).offset);
keunyoungb85b2752013-03-08 12:28:03 -0800774}
775
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700776void GL2Encoder::calcIndexRange(const void* indices,
777 GLenum type,
778 GLsizei count,
779 int* minIndex_out,
780 int* maxIndex_out) {
781 switch(type) {
782 case GL_BYTE:
783 case GL_UNSIGNED_BYTE:
784 GLUtils::minmaxExcept(
785 (unsigned char *)indices, count,
786 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800787 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned char>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700788 break;
789 case GL_SHORT:
790 case GL_UNSIGNED_SHORT:
791 GLUtils::minmaxExcept(
792 (unsigned short *)indices, count,
793 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800794 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned short>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700795 break;
796 case GL_INT:
797 case GL_UNSIGNED_INT:
798 GLUtils::minmaxExcept(
799 (unsigned int *)indices, count,
800 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800801 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned int>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700802 break;
803 default:
804 ALOGE("unsupported index buffer type %d\n", type);
805 }
806}
807
808void* GL2Encoder::recenterIndices(const void* src,
809 GLenum type,
810 GLsizei count,
811 int minIndex) {
812
813 void* adjustedIndices = (void*)src;
814
815 if (minIndex != 0) {
816 adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count);
817 switch(type) {
818 case GL_BYTE:
819 case GL_UNSIGNED_BYTE:
820 GLUtils::shiftIndicesExcept(
821 (unsigned char *)src,
822 (unsigned char *)adjustedIndices,
823 count, -minIndex,
824 m_primitiveRestartEnabled,
825 (unsigned char)m_primitiveRestartIndex);
826 break;
827 case GL_SHORT:
828 case GL_UNSIGNED_SHORT:
829 GLUtils::shiftIndicesExcept(
830 (unsigned short *)src,
831 (unsigned short *)adjustedIndices,
832 count, -minIndex,
833 m_primitiveRestartEnabled,
834 (unsigned short)m_primitiveRestartIndex);
835 break;
836 case GL_INT:
837 case GL_UNSIGNED_INT:
838 GLUtils::shiftIndicesExcept(
839 (unsigned int *)src,
840 (unsigned int *)adjustedIndices,
841 count, -minIndex,
842 m_primitiveRestartEnabled,
843 (unsigned int)m_primitiveRestartIndex);
844 break;
845 default:
846 ALOGE("unsupported index buffer type %d\n", type);
847 }
848 }
849
850 return adjustedIndices;
851}
852
853void GL2Encoder::getBufferIndexRange(BufferData* buf,
854 const void* dataWithOffset,
855 GLenum type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -0800856 size_t count,
857 size_t offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700858 int* minIndex_out,
859 int* maxIndex_out) {
860
861 if (buf->m_indexRangeCache.findRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -0800862 type, offset, count,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700863 m_primitiveRestartEnabled,
864 minIndex_out,
865 maxIndex_out)) {
866 return;
867 }
868
869 calcIndexRange(dataWithOffset, type, count, minIndex_out, maxIndex_out);
870
871 buf->m_indexRangeCache.addRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -0800872 type, offset, count, m_primitiveRestartEnabled,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700873 *minIndex_out, *maxIndex_out);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800874
875 ALOGV("%s: got range [%u %u] pr? %d", __FUNCTION__, *minIndex_out, *maxIndex_out, m_primitiveRestartEnabled);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700876}
keunyoungb85b2752013-03-08 12:28:03 -0800877
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800878// For detecting legacy usage of glVertexAttribPointer
879void GL2Encoder::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) const {
880 if (hasClientArrays) *hasClientArrays = false;
881 if (hasVBOs) *hasVBOs = false;
882
883 for (int i = 0; i < m_state->nLocations(); i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800884 const GLClientState::VertexAttribState& state = m_state->getState(i);
885 if (state.enabled) {
886 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
887 GLuint bufferObject = curr_binding.buffer;
888 if (bufferObject == 0 && curr_binding.offset && hasClientArrays) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800889 *hasClientArrays = true;
890 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800891 if (bufferObject != 0 && hasVBOs) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800892 *hasVBOs = true;
893 }
894 }
895 }
896}
897
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800898void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count, bool hasClientArrays, GLsizei primcount)
keunyoungb85b2752013-03-08 12:28:03 -0800899{
900 assert(m_state);
901
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800902 GLuint currentVao = m_state->currentVertexArrayObject();
Lingfeng Yang398162b2016-05-26 14:18:33 -0700903 GLuint lastBoundVbo = m_state->currentArrayVbo();
keunyoungb85b2752013-03-08 12:28:03 -0800904 for (int i = 0; i < m_state->nLocations(); i++) {
905 bool enableDirty;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800906 const GLClientState::VertexAttribState& state = m_state->getStateAndEnableDirty(i, &enableDirty);
keunyoungb85b2752013-03-08 12:28:03 -0800907
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800908 if (!enableDirty && !state.enabled) {
keunyoungb85b2752013-03-08 12:28:03 -0800909 continue;
910 }
911
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800912 if (state.enabled) {
913 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
914 GLuint bufferObject = curr_binding.buffer;
915 if (hasClientArrays && lastBoundVbo != bufferObject) {
916 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, bufferObject);
917 lastBoundVbo = bufferObject;
Lingfeng Yang398162b2016-05-26 14:18:33 -0700918 }
keunyoungb85b2752013-03-08 12:28:03 -0800919
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800920 int divisor = curr_binding.divisor;
921 int stride = curr_binding.stride;
922 int effectiveStride = curr_binding.effectiveStride;
923 uintptr_t offset = curr_binding.offset;
924 int firstIndex = effectiveStride * first;
keunyoungb85b2752013-03-08 12:28:03 -0800925
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800926 if (bufferObject == 0) {
927 unsigned int datalen = state.elementSize * count;
928 if (divisor && primcount) {
929 ALOGV("%s: divisor for att %d: %d, w/ stride %d (effective stride %d) size %d type 0x%x) datalen %u",
930 __FUNCTION__, i, divisor, state.stride, effectiveStride, state.elementSize, state.type, datalen);
931 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
932 datalen = state.elementSize * actual_count;
933 ALOGV("%s: actual datalen %u", __FUNCTION__, datalen);
934 }
935 if (state.elementSize == 0) {
Yahan Zhou3f2f1b42016-12-01 13:49:44 -0800936 // The vertex attribute array is uninitialized. Abandon it.
937 ALOGE("a vertex attribute array is uninitialized. Skipping corresponding vertex attribute.");
938 this->m_glDisableVertexAttribArray_enc(this, i);
939 continue;
940 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700941 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang000cf4c2017-01-25 08:09:02 -0800942
943 if (datalen && (!offset || !((unsigned char*)offset + firstIndex))) {
944 ALOGD("%s: bad offset / len!!!!!", __FUNCTION__);
945 continue;
946 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800947 if (state.isInt) {
948 this->glVertexAttribIPointerDataAEMU(this, i, state.size, state.type, stride, (unsigned char *)offset + firstIndex, datalen);
949 } else {
950 this->glVertexAttribPointerData(this, i, state.size, state.type, state.normalized, stride, (unsigned char *)offset + firstIndex, datalen);
951 }
keunyoungb85b2752013-03-08 12:28:03 -0800952 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800953 const BufferData* buf = m_shared->getBufferData(bufferObject);
Yahan Zhou5507c042016-06-01 17:24:28 -0700954 // The following expression actually means bufLen = stride*count;
955 // But the last element doesn't have to fill up the whole stride.
956 // So it becomes the current form.
Lingfeng Yang5fe99012017-01-18 09:17:09 -0800957 unsigned int bufLen = effectiveStride * (count ? (count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800958 if (divisor && primcount) {
959 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
Lingfeng Yang5fe99012017-01-18 09:17:09 -0800960 bufLen = effectiveStride * (actual_count ? (actual_count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800961 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700962 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800963 if (hasClientArrays) {
964 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800965 if (state.isInt) {
966 this->glVertexAttribIPointerOffsetAEMU(this, i, state.size, state.type, stride, offset + firstIndex);
967 } else {
968 this->glVertexAttribPointerOffset(this, i, state.size, state.type, state.normalized, stride, offset + firstIndex);
969 }
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800970 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700971 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800972 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=%p", buf);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -0800973 if (buf) {
974 ALOGE("Out of bounds vertex attribute info: "
975 "clientArray? %d attribute %d vbo %u allocedBufferSize %u bufferDataSpecified? %d wantedStart %u wantedEnd %u",
976 hasClientArrays, i, bufferObject, buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen);
977 }
978 m_glDisableVertexAttribArray_enc(this, i);
Yahan Zhou5507c042016-06-01 17:24:28 -0700979 }
keunyoungb85b2752013-03-08 12:28:03 -0800980 }
981 } else {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800982 if (hasClientArrays) {
983 this->m_glDisableVertexAttribArray_enc(this, i);
984 }
keunyoungb85b2752013-03-08 12:28:03 -0800985 }
986 }
Lingfeng Yang398162b2016-05-26 14:18:33 -0700987
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800988 if (hasClientArrays && lastBoundVbo != m_state->currentArrayVbo()) {
Lingfeng Yang398162b2016-05-26 14:18:33 -0700989 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
990 }
keunyoungb85b2752013-03-08 12:28:03 -0800991}
992
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700993void GL2Encoder::flushDrawCall() {
Lingfeng Yang1ebb33c2017-01-19 08:04:48 -0800994 // This used to be every other draw call, but
995 // now that we are using real GPU buffers on host,
996 // set this to every 200 draw calls
997 // (tuned on z840 linux NVIDIA Quadro K2200)
998 if (m_drawCallFlushCount % 200 == 0) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700999 m_stream->flush();
1000 }
1001 m_drawCallFlushCount++;
1002}
1003
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001004static bool isValidDrawMode(GLenum mode)
1005{
1006 bool retval = false;
1007 switch (mode) {
1008 case GL_POINTS:
1009 case GL_LINE_STRIP:
1010 case GL_LINE_LOOP:
1011 case GL_LINES:
1012 case GL_TRIANGLE_STRIP:
1013 case GL_TRIANGLE_FAN:
1014 case GL_TRIANGLES:
1015 retval = true;
1016 }
1017 return retval;
1018}
1019
keunyoungb85b2752013-03-08 12:28:03 -08001020void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
1021{
1022 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001023 assert(ctx->m_state != NULL);
1024 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1025 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhoud6217a52016-02-10 16:10:46 -08001026
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001027 bool has_client_vertex_arrays = false;
1028 bool has_indirect_arrays = false;
1029 ctx->getVBOUsage(&has_client_vertex_arrays,
1030 &has_indirect_arrays);
1031
1032 if (has_client_vertex_arrays ||
1033 (!has_client_vertex_arrays &&
1034 !has_indirect_arrays)) {
1035 ctx->sendVertexAttributes(first, count, true);
1036 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
1037 } else {
1038 ctx->sendVertexAttributes(0, count, false);
1039 ctx->m_glDrawArrays_enc(ctx, mode, first, count);
1040 }
keunyoungb85b2752013-03-08 12:28:03 -08001041}
1042
1043
1044void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
1045{
1046
1047 GL2Encoder *ctx = (GL2Encoder *)self;
1048 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001049 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1050 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -07001051 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 -08001052 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001053
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001054 bool has_client_vertex_arrays = false;
keunyoungb85b2752013-03-08 12:28:03 -08001055 bool has_indirect_arrays = false;
1056 int nLocations = ctx->m_state->nLocations();
Yahan Zhou5507c042016-06-01 17:24:28 -07001057 GLintptr offset = 0;
keunyoungb85b2752013-03-08 12:28:03 -08001058
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001059 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
keunyoungb85b2752013-03-08 12:28:03 -08001060
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001061 if (!has_client_vertex_arrays && !has_indirect_arrays) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001062 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -07001063 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
1064 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001065 }
1066
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001067 BufferData* buf = NULL;
Yahan Zhou5507c042016-06-01 17:24:28 -07001068 int minIndex = 0, maxIndex = 0;
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001069
1070 // For validation/immediate index array purposes,
1071 // we need the min/max vertex index of the index array.
1072 // If the VBO != 0, this may not be the first time we have
1073 // used this particular index buffer. getBufferIndexRange
1074 // can more quickly get min/max vertex index by
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001075 // caching previous results.
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001076 if (ctx->m_state->currentIndexVbo() != 0) {
1077 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1078 offset = (GLintptr)indices;
1079 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
1080 ctx->getBufferIndexRange(buf,
1081 indices,
1082 type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001083 (size_t)count,
1084 (size_t)offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001085 &minIndex, &maxIndex);
1086 } else {
1087 // In this case, the |indices| field holds a real
1088 // array, so calculate the indices now. They will
1089 // also be needed to know how much data to
1090 // transfer to host.
1091 ctx->calcIndexRange(indices,
1092 type,
1093 count,
1094 &minIndex,
1095 &maxIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -07001096 }
1097
keunyoungb85b2752013-03-08 12:28:03 -08001098 bool adjustIndices = true;
1099 if (ctx->m_state->currentIndexVbo() != 0) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001100 if (!has_client_vertex_arrays) {
1101 ctx->sendVertexAttributes(0, maxIndex + 1, false);
keunyoungb85b2752013-03-08 12:28:03 -08001102 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -07001103 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001104 ctx->flushDrawCall();
keunyoungb85b2752013-03-08 12:28:03 -08001105 adjustIndices = false;
1106 } else {
1107 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1108 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001109 }
1110 }
1111 if (adjustIndices) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001112 void *adjustedIndices =
1113 ctx->recenterIndices(indices,
1114 type,
1115 count,
1116 minIndex);
keunyoungb85b2752013-03-08 12:28:03 -08001117
keunyoungb85b2752013-03-08 12:28:03 -08001118 if (has_indirect_arrays || 1) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001119 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
keunyoungb85b2752013-03-08 12:28:03 -08001120 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
1121 count * glSizeof(type));
1122 // XXX - OPTIMIZATION (see the other else branch) should be implemented
1123 if(!has_indirect_arrays) {
1124 //ALOGD("unoptimized drawelements !!!\n");
1125 }
1126 } else {
1127 // we are all direct arrays and immidate mode index array -
1128 // rebuild the arrays and the index array;
1129 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
1130 }
1131 }
1132}
1133
1134
1135GLint * GL2Encoder::getCompressedTextureFormats()
1136{
1137 if (m_compressedTextureFormats == NULL) {
1138 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
1139 &m_num_compressedTextureFormats);
1140 if (m_num_compressedTextureFormats > 0) {
1141 // get number of texture formats;
1142 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
1143 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
1144 }
1145 }
1146 return m_compressedTextureFormats;
1147}
1148
1149// Replace uses of samplerExternalOES with sampler2D, recording the names of
1150// modified shaders in data. Also remove
1151// #extension GL_OES_EGL_image_external : require
1152// statements.
1153//
1154// This implementation assumes the input has already been pre-processed. If not,
1155// a few cases will be mishandled:
1156//
1157// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
1158// the following code:
1159// #if 1
1160// uniform sampler2D mySampler;
1161// #else
1162// uniform samplerExternalOES mySampler;
1163// #endif
1164//
1165// 2. Comments that look like sampler declarations will be incorrectly modified
1166// and recorded:
1167// // samplerExternalOES hahaFooledYou
1168//
1169// 3. However, GLSL ES does not have a concatentation operator, so things like
1170// this (valid in C) are invalid and not a problem:
1171// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
1172// SAMPLER(ExternalOES, mySampler);
1173//
1174static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
1175{
1176 static const char STR_HASH_EXTENSION[] = "#extension";
1177 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
1178 static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
1179 static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
1180
1181 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
1182 char* c = str;
1183 while ((c = strstr(c, STR_HASH_EXTENSION))) {
1184 char* start = c;
1185 c += sizeof(STR_HASH_EXTENSION)-1;
1186 while (isspace(*c) && *c != '\0') {
1187 c++;
1188 }
1189 if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
1190 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
1191 {
1192 // #extension statements are terminated by end of line
1193 c = start;
1194 while (*c != '\0' && *c != '\r' && *c != '\n') {
1195 *c++ = ' ';
1196 }
1197 }
1198 }
1199
1200 // -- replace "samplerExternalOES" with "sampler2D" and record name
1201 c = str;
1202 while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
1203 // Make sure "samplerExternalOES" isn't a substring of a larger token
1204 if (c == str || !isspace(*(c-1))) {
1205 c++;
1206 continue;
1207 }
1208 char* sampler_start = c;
1209 c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
1210 if (!isspace(*c) && *c != '\0') {
1211 continue;
1212 }
1213
1214 // capture sampler name
1215 while (isspace(*c) && *c != '\0') {
1216 c++;
1217 }
1218 if (!isalpha(*c) && *c != '_') {
1219 // not an identifier
1220 return false;
1221 }
1222 char* name_start = c;
1223 do {
1224 c++;
1225 } while (isalnum(*c) || *c == '_');
1226 data->samplerExternalNames.push_back(
1227 android::String8(name_start, c - name_start));
1228
1229 // memcpy instead of strcpy since we don't want the NUL terminator
1230 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
1231 }
1232
1233 return true;
1234}
1235
Bo Hu73568cd2015-01-20 16:29:50 -08001236void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
1237{
1238 GL2Encoder* ctx = (GL2Encoder*)self;
1239 // Although it is not supported, need to set proper error code.
1240 SET_ERROR_IF(1, GL_INVALID_ENUM);
1241}
1242
David 'Digit' Turner02fdb692014-10-30 18:07:56 +01001243void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -08001244{
1245 GL2Encoder* ctx = (GL2Encoder*)self;
1246 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001247 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(shader), GL_INVALID_VALUE);
Tina Zhang7a84f652014-12-04 12:37:30 +08001248 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
1249 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001250
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001251 // Track original sources---they may be translated in the backend
1252 std::vector<std::string> orig_sources;
1253 for (int i = 0; i < count; i++) {
1254 orig_sources.push_back(std::string((const char*)(string[i])));
1255 }
1256 shaderData->sources = orig_sources;
1257
keunyoungb85b2752013-03-08 12:28:03 -08001258 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
1259 char *str = new char[len + 1];
1260 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
1261
1262 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
1263 // Perhaps we can borrow Mesa's pre-processor?
1264
1265 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001266 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001267 ctx->setError(GL_OUT_OF_MEMORY);
1268 return;
1269 }
keunyoungb85b2752013-03-08 12:28:03 -08001270 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001271 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001272}
1273
1274void GL2Encoder::s_glFinish(void *self)
1275{
1276 GL2Encoder *ctx = (GL2Encoder *)self;
1277 ctx->glFinishRoundTrip(self);
1278}
1279
1280void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1281{
1282 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -08001283 bool isProgram = ctx->m_shared->isProgram(program);
1284 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
1285 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
1286
keunyoungb85b2752013-03-08 12:28:03 -08001287 ctx->m_glLinkProgram_enc(self, program);
1288
1289 GLint linkStatus = 0;
1290 ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001291 if (!linkStatus) {
keunyoungb85b2752013-03-08 12:28:03 -08001292 return;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001293 }
keunyoungb85b2752013-03-08 12:28:03 -08001294
1295 //get number of active uniforms in the program
1296 GLint numUniforms=0;
1297 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
1298 ctx->m_shared->initProgramData(program,numUniforms);
1299
1300 //get the length of the longest uniform name
1301 GLint maxLength=0;
1302 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
1303
1304 GLint size;
1305 GLenum type;
1306 GLchar *name = new GLchar[maxLength+1];
1307 GLint location;
1308 //for each active uniform, get its size and starting location.
1309 for (GLint i=0 ; i<numUniforms ; ++i)
1310 {
1311 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1312 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1313 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1314 }
1315 ctx->m_shared->setupLocationShiftWAR(program);
1316
1317 delete[] name;
1318}
1319
1320void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1321{
1322 GL2Encoder *ctx = (GL2Encoder*)self;
1323 ctx->m_glDeleteProgram_enc(self, program);
1324
1325 ctx->m_shared->deleteProgramData(program);
1326}
1327
1328void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1329{
1330 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001331 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001332 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001333 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1334 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1335 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1336 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1337}
1338void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1339{
1340 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001341 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001342 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001343 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1344 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1345 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1346 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1347}
1348
1349GLuint GL2Encoder::s_glCreateProgram(void * self)
1350{
1351 GL2Encoder *ctx = (GL2Encoder*)self;
1352 GLuint program = ctx->m_glCreateProgram_enc(self);
1353 if (program!=0)
1354 ctx->m_shared->addProgramData(program);
1355 return program;
1356}
1357
1358GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1359{
1360 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001361 RET_AND_SET_ERROR_IF(!GLESv2Validation::shaderType(ctx, shaderType), GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001362 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1363 if (shader != 0) {
1364 if (!ctx->m_shared->addShaderData(shader)) {
1365 ctx->m_glDeleteShader_enc(self, shader);
1366 return 0;
1367 }
1368 }
1369 return shader;
1370}
1371
bohu56bf82f2014-10-17 15:35:48 -07001372void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1373 GLsizei* count, GLuint* shaders)
1374{
1375 GL2Encoder *ctx = (GL2Encoder*)self;
1376 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1377 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1378}
1379
1380void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1381 GLsizei* length, GLchar* source)
1382{
1383 GL2Encoder *ctx = (GL2Encoder*)self;
1384 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1385 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001386 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
1387 if (shaderData) {
1388 std::string returned;
1389 int curr_len = 0;
1390 for (int i = 0; i < shaderData->sources.size(); i++) {
1391 if (curr_len + shaderData->sources[i].size() < bufsize - 1) {
1392 returned += shaderData->sources[i];
1393 } else {
1394 returned += shaderData->sources[i].substr(0, bufsize - 1 - curr_len);
1395 break;
1396 }
1397 }
1398 memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize);
1399 }
bohu56bf82f2014-10-17 15:35:48 -07001400}
1401
1402void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1403 GLsizei* length, GLchar* infolog)
1404{
1405 GL2Encoder *ctx = (GL2Encoder*)self;
1406 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1407 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1408}
1409
1410void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1411 GLsizei* length, GLchar* infolog)
1412{
1413 GL2Encoder *ctx = (GL2Encoder*)self;
1414 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1415 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1416}
1417
keunyoungb85b2752013-03-08 12:28:03 -08001418void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1419{
1420 GL2Encoder *ctx = (GL2Encoder*)self;
1421 ctx->m_glDeleteShader_enc(self,shader);
1422 ctx->m_shared->unrefShaderData(shader);
1423}
1424
1425void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1426{
1427 GL2Encoder *ctx = (GL2Encoder*)self;
1428 ctx->m_glAttachShader_enc(self, program, shader);
1429 ctx->m_shared->attachShader(program, shader);
1430}
1431
1432void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1433{
1434 GL2Encoder *ctx = (GL2Encoder*)self;
1435 ctx->m_glDetachShader_enc(self, program, shader);
1436 ctx->m_shared->detachShader(program, shader);
1437}
1438
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001439int sArrIndexOfUniformExpr(const char* name, int* err) {
1440 *err = 0;
1441 int arrIndex = 0;
1442 int namelen = strlen(name);
1443 if (name[namelen-1] == ']') {
1444 const char *brace = strrchr(name,'[');
1445 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1446 *err = 1; return 0;
1447 }
1448 }
1449 return arrIndex;
1450}
1451
keunyoungb85b2752013-03-08 12:28:03 -08001452int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1453{
1454 if (!name) return -1;
1455
1456 GL2Encoder *ctx = (GL2Encoder*)self;
1457
1458 // if we need the uniform location WAR
1459 // parse array index from the end of the name string
1460 int arrIndex = 0;
1461 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1462 if (needLocationWAR) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001463 int err;
1464 arrIndex = sArrIndexOfUniformExpr(name, &err);
1465 if (err) return -1;
keunyoungb85b2752013-03-08 12:28:03 -08001466 }
1467
1468 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1469 if (hostLoc >= 0 && needLocationWAR) {
1470 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1471 }
1472 return hostLoc;
1473}
1474
1475bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1476{
1477 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1478 return false;
1479
1480 m_state->setActiveTextureUnit(texUnit);
1481
1482 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1483 if (newTarget != oldTarget) {
1484 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1485 m_state->disableTextureTarget(GL_TEXTURE_2D);
1486 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1487 } else {
1488 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1489 m_state->enableTextureTarget(GL_TEXTURE_2D);
1490 }
1491 m_glActiveTexture_enc(this, texUnit);
1492 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1493 m_state->getBoundTexture(newTarget));
1494 return true;
1495 }
1496
1497 return false;
1498}
1499
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001500void GL2Encoder::updateHostTexture2DBindingsFromProgramData(GLuint program) {
1501 GL2Encoder *ctx = this;
keunyoungb85b2752013-03-08 12:28:03 -08001502 GLClientState* state = ctx->m_state;
1503 GLSharedGroupPtr shared = ctx->m_shared;
1504
keunyoungb85b2752013-03-08 12:28:03 -08001505 GLenum origActiveTexture = state->getActiveTextureUnit();
1506 GLenum hostActiveTexture = origActiveTexture;
1507 GLint samplerIdx = -1;
1508 GLint samplerVal;
1509 GLenum samplerTarget;
1510 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1511 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1512 continue;
1513 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001514 samplerTarget))
keunyoungb85b2752013-03-08 12:28:03 -08001515 {
1516 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1517 }
1518 }
1519 state->setActiveTextureUnit(origActiveTexture);
1520 if (hostActiveTexture != origActiveTexture) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001521 ctx->m_glActiveTexture_enc(ctx, origActiveTexture);
keunyoungb85b2752013-03-08 12:28:03 -08001522 }
1523}
1524
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001525void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1526{
1527 GL2Encoder *ctx = (GL2Encoder*)self;
1528 GLSharedGroupPtr shared = ctx->m_shared;
1529
1530 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
1531 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1532
1533 ctx->m_glUseProgram_enc(self, program);
1534 ctx->m_state->setCurrentProgram(program);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001535 ctx->m_state->setCurrentShaderProgram(program);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001536
1537 ctx->updateHostTexture2DBindingsFromProgramData(program);
1538}
1539
keunyoungb85b2752013-03-08 12:28:03 -08001540void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1541{
1542 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001543 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001544 ctx->m_glUniform1f_enc(self, hostLoc, x);
1545}
1546
1547void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1548{
1549 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001550 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001551 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1552}
1553
1554void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1555{
1556 GL2Encoder *ctx = (GL2Encoder*)self;
1557 GLClientState* state = ctx->m_state;
1558 GLSharedGroupPtr shared = ctx->m_shared;
1559
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001560 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001561 ctx->m_glUniform1i_enc(self, hostLoc, x);
1562
1563 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001564 if (shared->setSamplerUniform(state->currentShaderProgram(), location, x, &target)) {
keunyoungb85b2752013-03-08 12:28:03 -08001565 GLenum origActiveTexture = state->getActiveTextureUnit();
1566 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1567 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1568 }
1569 state->setActiveTextureUnit(origActiveTexture);
1570 }
1571}
1572
1573void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* 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_glUniform1iv_enc(self, hostLoc, count, v);
1578}
1579
1580void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1581{
1582 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001583 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001584 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1585}
1586
1587void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1588{
1589 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001590 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001591 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1592}
1593
1594void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1595{
1596 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001597 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001598 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1599}
1600
1601void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1602{
1603 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001604 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001605 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1606}
1607
1608void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1609{
1610 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001611 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001612 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1613}
1614
1615void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1616{
1617 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001618 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001619 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1620}
1621
1622void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1623{
1624 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001625 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001626 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1627}
1628
1629void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1630{
1631 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001632 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001633 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1634}
1635
1636void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1637{
1638 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001639 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001640 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1641}
1642
1643void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1644{
1645 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001646 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001647 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1648}
1649
1650void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1651{
1652 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001653 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001654 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1655}
1656
1657void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1658{
1659 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001660 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001661 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1662}
1663
1664void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1665{
1666 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001667 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001668 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1669}
1670
1671void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1672{
1673 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001674 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001675 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1676}
1677
1678void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1679{
1680 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001681 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001682 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1683}
1684
1685void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1686{
1687 GL2Encoder* ctx = (GL2Encoder*)self;
1688 GLClientState* state = ctx->m_state;
1689 GLenum err;
1690
1691 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1692
1693 ctx->m_glActiveTexture_enc(ctx, texture);
1694}
1695
1696void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1697{
1698 GL2Encoder* ctx = (GL2Encoder*)self;
1699 GLClientState* state = ctx->m_state;
1700 GLenum err;
1701 GLboolean firstUse;
1702
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001703 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -08001704 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1705
1706 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1707 ctx->m_glBindTexture_enc(ctx, target, texture);
1708 return;
1709 }
1710
1711 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1712
1713 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1714 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1715 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1716 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1717 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1718 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1719 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1720 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1721
1722 if (target != priorityTarget) {
1723 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1724 state->getBoundTexture(GL_TEXTURE_2D));
1725 }
1726 }
1727
1728 if (target == priorityTarget) {
1729 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1730 }
1731}
1732
1733void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1734{
1735 GL2Encoder* ctx = (GL2Encoder*)self;
1736 GLClientState* state = ctx->m_state;
1737
1738 state->deleteTextures(n, textures);
1739 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1740}
1741
1742void GL2Encoder::s_glGetTexParameterfv(void* self,
1743 GLenum target, GLenum pname, GLfloat* params)
1744{
1745 GL2Encoder* ctx = (GL2Encoder*)self;
1746 const GLClientState* state = ctx->m_state;
1747
1748 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1749 ctx->override2DTextureTarget(target);
1750 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001751 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001752 } else {
1753 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1754 }
1755}
1756
1757void GL2Encoder::s_glGetTexParameteriv(void* self,
1758 GLenum target, GLenum pname, GLint* params)
1759{
1760 GL2Encoder* ctx = (GL2Encoder*)self;
1761 const GLClientState* state = ctx->m_state;
1762
1763 switch (pname) {
1764 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1765 *params = 1;
1766 break;
1767
1768 default:
1769 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1770 ctx->override2DTextureTarget(target);
1771 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001772 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001773 } else {
1774 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1775 }
1776 break;
1777 }
1778}
1779
1780static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1781{
1782 switch (pname) {
1783 case GL_TEXTURE_MIN_FILTER:
1784 case GL_TEXTURE_MAG_FILTER:
1785 return param == GL_NEAREST || param == GL_LINEAR;
1786
1787 case GL_TEXTURE_WRAP_S:
1788 case GL_TEXTURE_WRAP_T:
1789 return param == GL_CLAMP_TO_EDGE;
1790
1791 default:
1792 return true;
1793 }
1794}
1795
1796void GL2Encoder::s_glTexParameterf(void* self,
1797 GLenum target, GLenum pname, GLfloat param)
1798{
1799 GL2Encoder* ctx = (GL2Encoder*)self;
1800 const GLClientState* state = ctx->m_state;
1801
1802 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1803 !isValidTextureExternalParam(pname, (GLenum)param)),
1804 GL_INVALID_ENUM);
1805
1806 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1807 ctx->override2DTextureTarget(target);
1808 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001809 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001810 } else {
1811 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1812 }
1813}
1814
1815void GL2Encoder::s_glTexParameterfv(void* self,
1816 GLenum target, GLenum pname, const GLfloat* params)
1817{
1818 GL2Encoder* ctx = (GL2Encoder*)self;
1819 const GLClientState* state = ctx->m_state;
1820
1821 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1822 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1823 GL_INVALID_ENUM);
1824
1825 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1826 ctx->override2DTextureTarget(target);
1827 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001828 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001829 } else {
1830 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1831 }
1832}
1833
1834void GL2Encoder::s_glTexParameteri(void* self,
1835 GLenum target, GLenum pname, GLint param)
1836{
1837 GL2Encoder* ctx = (GL2Encoder*)self;
1838 const GLClientState* state = ctx->m_state;
1839
1840 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1841 !isValidTextureExternalParam(pname, (GLenum)param)),
1842 GL_INVALID_ENUM);
1843
1844 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1845 ctx->override2DTextureTarget(target);
1846 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001847 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001848 } else {
1849 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
1850 }
1851}
1852
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001853static int ilog2(uint32_t x) {
1854 int p = 0;
1855 while ((1 << p) < x)
1856 p++;
1857 return p;
1858}
1859
bohu26a92982014-11-25 16:50:37 -08001860void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
1861 GLint internalformat, GLsizei width, GLsizei height, GLint border,
1862 GLenum format, GLenum type, const GLvoid* pixels)
1863{
1864 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07001865 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001866
1867 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
1868 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
1869 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
1870 // If unpack buffer is nonzero, verify unmapped state.
1871 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
1872
1873 GLint max_texture_size;
1874 GLint max_cube_map_texture_size;
1875 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
1876 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
1877 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
1878 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
1879 SET_ERROR_IF((target == GL_TEXTURE_CUBE_MAP) &&
1880 (level > ilog2(max_cube_map_texture_size)), GL_INVALID_VALUE);
1881 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
1882 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
1883 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
1884 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && width > max_cube_map_texture_size, GL_INVALID_VALUE);
1885 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && height > max_cube_map_texture_size, GL_INVALID_VALUE);
1886 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
1887 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
1888 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1889 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1890 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 0) >
1891 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
1892 GL_INVALID_OPERATION);
1893 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1894 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1895 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
1896 glSizeof(type)),
1897 GL_INVALID_OPERATION);
1898 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1899 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1900 ((uintptr_t)pixels % glSizeof(type)),
1901 GL_INVALID_OPERATION);
1902 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
1903
1904 GLenum stateTarget = target;
1905 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1906 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1907 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
1908 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1909 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1910 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
1911 stateTarget = GL_TEXTURE_CUBE_MAP;
1912
1913 state->setBoundTextureInternalFormat(stateTarget, internalformat);
1914 state->setBoundTextureFormat(stateTarget, format);
1915 state->setBoundTextureType(stateTarget, type);
1916 state->setBoundTextureDims(stateTarget, level, width, height, 1);
1917
bohu26a92982014-11-25 16:50:37 -08001918 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1919 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001920 }
Lingfeng Yang69066602016-04-12 09:29:11 -07001921
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001922 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
1923 ctx->glTexImage2DOffsetAEMU(
1924 ctx, target, level, internalformat,
1925 width, height, border,
1926 format, type, (uintptr_t)pixels);
bohu26a92982014-11-25 16:50:37 -08001927 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001928 ctx->m_glTexImage2D_enc(
1929 ctx, target, level, internalformat,
1930 width, height, border,
1931 format, type, pixels);
1932 }
1933
1934 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1935 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08001936 }
1937}
1938
Yahan Zhou2a208292016-06-22 15:36:04 -07001939void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
1940 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
1941 GLenum type, const GLvoid* pixels)
1942{
1943 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001944 GLClientState* state = ctx->m_state;
1945
1946 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
1947 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
1948 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
1949 // If unpack buffer is nonzero, verify unmapped state.
1950 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
1951
1952 GLint max_texture_size;
1953 GLint max_cube_map_texture_size;
1954 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
1955 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
1956 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
1957 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
1958 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) &&
1959 level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
1960 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
1961 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
1962
1963 GLuint tex = state->getBoundTexture(target);
1964 GLsizei neededWidth = xoffset + width;
1965 GLsizei neededHeight = yoffset + height;
1966 GLsizei neededDepth = 1;
1967
1968 if (tex && !state->queryTexEGLImageBacked(tex)) {
1969 SET_ERROR_IF(
1970 (neededWidth > state->queryTexWidth(level, tex) ||
1971 neededHeight > state->queryTexHeight(level, tex) ||
1972 neededDepth > state->queryTexDepth(level, tex)),
1973 GL_INVALID_VALUE);
1974 }
1975
1976 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
1977 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1978 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1979 (state->pboNeededDataSize(width, height, 1, format, type, 0) >
1980 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
1981 GL_INVALID_OPERATION);
1982 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1983 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1984 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
1985 glSizeof(type)),
1986 GL_INVALID_OPERATION);
1987 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !pixels, GL_INVALID_OPERATION);
Yahan Zhou2a208292016-06-22 15:36:04 -07001988
1989 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1990 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001991 }
1992
1993 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
1994 ctx->glTexSubImage2DOffsetAEMU(
1995 ctx, target, level,
1996 xoffset, yoffset, width, height,
1997 format, type, (uintptr_t)pixels);
Yahan Zhou2a208292016-06-22 15:36:04 -07001998 } else {
1999 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
2000 height, format, type, pixels);
2001 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002002
2003 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2004 ctx->restore2DTextureTarget(target);
2005 }
Yahan Zhou2a208292016-06-22 15:36:04 -07002006}
bohu26a92982014-11-25 16:50:37 -08002007
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002008void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
2009 GLenum internalformat, GLint x, GLint y,
2010 GLsizei width, GLsizei height, GLint border)
2011{
2012 GL2Encoder* ctx = (GL2Encoder*)self;
2013 GLClientState* state = ctx->m_state;
2014
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002015 SET_ERROR_IF(ctx->glCheckFramebufferStatus(ctx, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
2016 GL_INVALID_FRAMEBUFFER_OPERATION);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002017 // This is needed to work around underlying OpenGL drivers
2018 // (such as those feeding some some AMD GPUs) that expect
2019 // positive components of cube maps to be defined _before_
2020 // the negative components (otherwise a segfault occurs).
2021 GLenum extraTarget =
2022 state->copyTexImageLuminanceCubeMapAMDWorkaround
2023 (target, level, internalformat);
2024
2025 if (extraTarget) {
2026 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
2027 x, y, width, height, border);
2028 }
2029
2030 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
2031 x, y, width, height, border);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002032
2033 state->setBoundTextureInternalFormat(target, internalformat);
2034 state->setBoundTextureDims(target, level, width, height, 1);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002035}
2036
keunyoungb85b2752013-03-08 12:28:03 -08002037void GL2Encoder::s_glTexParameteriv(void* self,
2038 GLenum target, GLenum pname, const GLint* params)
2039{
2040 GL2Encoder* ctx = (GL2Encoder*)self;
2041 const GLClientState* state = ctx->m_state;
2042
2043 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2044 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2045 GL_INVALID_ENUM);
2046
2047 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2048 ctx->override2DTextureTarget(target);
2049 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002050 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002051 } else {
2052 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
2053 }
2054}
2055
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002056bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
2057 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
2058 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2059}
2060
keunyoungb85b2752013-03-08 12:28:03 -08002061void GL2Encoder::override2DTextureTarget(GLenum target)
2062{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002063 if (texture2DNeedsOverride(target)) {
2064 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2065 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08002066 }
2067}
2068
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002069void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08002070{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002071 if (texture2DNeedsOverride(target)) {
2072 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2073 m_state->getBoundTexture(
2074 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)));
2075 }
keunyoungb85b2752013-03-08 12:28:03 -08002076}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002077
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002078void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2079 m_state->setBoundEGLImage(target, eglImage);
2080}
2081
2082
2083GLuint GL2Encoder::boundBuffer(GLenum target) const {
2084 return m_state->getBuffer(target);
2085}
2086
2087BufferData* GL2Encoder::getBufferData(GLenum target) const {
2088 GLuint bufferId = m_state->getBuffer(target);
2089 if (!bufferId) return NULL;
2090 return m_shared->getBufferData(bufferId);
2091}
2092
2093BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2094 if (!bufferId) return NULL;
2095 return m_shared->getBufferData(bufferId);
2096}
2097
2098bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2099 return m_shared->getBufferData(buffer)->m_mapped;
2100}
2101
2102bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2103 BufferData* buf = getBufferData(target);
2104 if (!buf) return false;
2105 return buf->m_mapped;
2106}
2107
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002108void GL2Encoder::s_glGenRenderbuffers(void* self,
2109 GLsizei n, GLuint* renderbuffers) {
2110 GL2Encoder* ctx = (GL2Encoder*)self;
2111 GLClientState* state = ctx->m_state;
2112
2113 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2114
2115 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2116 state->addRenderbuffers(n, renderbuffers);
2117}
2118
2119void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2120 GLsizei n, const GLuint* renderbuffers) {
2121 GL2Encoder* ctx = (GL2Encoder*)self;
2122 GLClientState* state = ctx->m_state;
2123
2124 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2125
2126 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002127
2128 // Nope, lets just leak those for now.
2129 // The spec has an *amazingly* convoluted set of conditions for when
2130 // render buffers are actually deleted:
2131 // 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.
2132 //
2133 // 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***
2134 //
2135 // So, just detach this one from the bound FBO, and ignore the rest.
2136 for (int i = 0; i < n; i++) {
2137 state->detachRbo(renderbuffers[i]);
2138 }
2139 // state->removeRenderbuffers(n, renderbuffers);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002140}
2141
2142void GL2Encoder::s_glBindRenderbuffer(void* self,
2143 GLenum target, GLuint renderbuffer) {
2144 GL2Encoder* ctx = (GL2Encoder*)self;
2145 GLClientState* state = ctx->m_state;
2146
2147 SET_ERROR_IF((target != GL_RENDERBUFFER),
2148 GL_INVALID_ENUM);
2149
2150 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2151 state->bindRenderbuffer(target, renderbuffer);
2152}
2153
Lingfeng Yang69066602016-04-12 09:29:11 -07002154void GL2Encoder::s_glRenderbufferStorage(void* self,
2155 GLenum target, GLenum internalformat,
2156 GLsizei width, GLsizei height) {
2157 GL2Encoder* ctx = (GL2Encoder*) self;
2158 GLClientState* state = ctx->m_state;
2159
2160 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002161 SET_ERROR_IF(
2162 !GLESv2Validation::rboFormat(ctx, internalformat),
2163 GL_INVALID_ENUM);
Lingfeng Yang69066602016-04-12 09:29:11 -07002164
2165 state->setBoundRenderbufferFormat(internalformat);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002166 state->setBoundRenderbufferSamples(0);
2167
Lingfeng Yang69066602016-04-12 09:29:11 -07002168 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
2169 width, height);
2170}
2171
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002172void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
2173 GLenum target, GLenum attachment,
2174 GLenum renderbuffertarget, GLuint renderbuffer) {
2175 GL2Encoder* ctx = (GL2Encoder*)self;
2176 GLClientState* state = ctx->m_state;
2177
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002178 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2179 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2180 state->attachRbo(target, attachment, renderbuffer);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002181
2182 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
2183}
2184
2185void GL2Encoder::s_glGenFramebuffers(void* self,
2186 GLsizei n, GLuint* framebuffers) {
2187 GL2Encoder* ctx = (GL2Encoder*)self;
2188 GLClientState* state = ctx->m_state;
2189
2190 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2191
2192 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2193 state->addFramebuffers(n, framebuffers);
2194}
2195
2196void GL2Encoder::s_glDeleteFramebuffers(void* self,
2197 GLsizei n, const GLuint* framebuffers) {
2198 GL2Encoder* ctx = (GL2Encoder*)self;
2199 GLClientState* state = ctx->m_state;
2200
2201 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2202
2203 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2204 state->removeFramebuffers(n, framebuffers);
2205}
2206
2207void GL2Encoder::s_glBindFramebuffer(void* self,
2208 GLenum target, GLuint framebuffer) {
2209 GL2Encoder* ctx = (GL2Encoder*)self;
2210 GLClientState* state = ctx->m_state;
2211
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002212 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002213
2214 state->bindFramebuffer(target, framebuffer);
2215
2216 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
2217}
2218
2219void GL2Encoder::s_glFramebufferTexture2D(void* self,
2220 GLenum target, GLenum attachment,
2221 GLenum textarget, GLuint texture, GLint level) {
2222 GL2Encoder* ctx = (GL2Encoder*)self;
2223 GLClientState* state = ctx->m_state;
2224
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002225 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2226 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2227 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002228
2229 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
2230}
2231
2232void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2233 GLenum target, GLenum attachment,
2234 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2235 GL2Encoder* ctx = (GL2Encoder*)self;
2236 GLClientState* state = ctx->m_state;
2237
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002238 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002239
2240 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2241}
2242
2243void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2244 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2245 GL2Encoder* ctx = (GL2Encoder*)self;
2246 const GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002247 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2248 SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2249 pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE &&
2250 !state->attachmentHasObject(target, attachment),
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002251 GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002252 SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL ||
2253 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE ||
2254 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) &&
2255 (!state->attachmentHasObject(target, attachment) ||
2256 state->getBoundFramebufferAttachmentType(target, attachment) !=
2257 FBO_ATTACHMENT_TEXTURE),
2258 !state->attachmentHasObject(target, attachment) ?
2259 GL_INVALID_OPERATION : GL_INVALID_ENUM);
2260 SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2261 pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2262 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
2263 state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
2264 GL_INVALID_OPERATION);
2265 SET_ERROR_IF(state->boundFramebuffer(target) &&
2266 (attachment == GL_BACK ||
2267 attachment == GL_FRONT),
2268 GL_INVALID_OPERATION);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002269 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
2270}
Lingfeng Yang69066602016-04-12 09:29:11 -07002271
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002272bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state,
Lingfeng Yang69066602016-04-12 09:29:11 -07002273 GLenum attachment) const {
2274 FboFormatInfo fbo_format_info;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002275 state->getBoundFramebufferFormat(target, attachment, &fbo_format_info);
Lingfeng Yang69066602016-04-12 09:29:11 -07002276
2277 bool res;
2278 switch (fbo_format_info.type) {
2279 case FBO_ATTACHMENT_RENDERBUFFER:
2280 switch (fbo_format_info.rb_format) {
2281 case GL_R16F:
2282 case GL_RG16F:
2283 case GL_RGB16F:
2284 case GL_RGBA16F:
2285 res = false;
2286 break;
2287 case GL_STENCIL_INDEX8:
2288 if (attachment == GL_STENCIL_ATTACHMENT) {
2289 res = true;
2290 } else {
2291 res = false;
2292 }
2293 break;
2294 default:
2295 res = true;
2296 }
2297 break;
2298 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002299 switch (fbo_format_info.tex_internalformat) {
2300 case GL_RED:
2301 case GL_RG:
2302 case GL_R16F:
2303 case GL_RG16F:
2304 case GL_RGBA16F:
2305 case GL_RGB16F:
2306 case GL_R11F_G11F_B10F:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002307 case GL_R32F:
2308 case GL_RG32F:
2309 case GL_RGBA32F:
2310 case GL_SRGB8:
2311 case GL_RGB32UI:
2312 case GL_RGB16UI:
2313 case GL_RGB8UI:
2314 case GL_RGB32I:
2315 case GL_RGB16I:
2316 case GL_RGB8I:
2317 case GL_R8_SNORM:
2318 case GL_RG8_SNORM:
2319 case GL_RGB8_SNORM:
2320 case GL_RGBA8_SNORM:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002321 res = false;
2322 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07002323 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002324 case GL_RGB:
2325 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07002326 switch (fbo_format_info.tex_type) {
2327 case GL_FLOAT:
2328 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002329 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002330 case GL_UNSIGNED_INT_2_10_10_10_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07002331 res = false;
2332 break;
2333 default:
2334 res = true;
2335 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002336 break;
2337 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07002338 res = true;
2339 }
2340 break;
2341 case FBO_ATTACHMENT_NONE:
2342 res = true;
2343 break;
2344 default:
2345 res = true;
2346 }
2347 return res;
2348}
2349
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002350bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const {
2351 bool res = true;
2352
2353 for (int i = 0; i < state->getMaxColorAttachments(); i++) {
2354 res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i));
2355 }
2356
2357 res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT);
2358 res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT);
2359
2360 return res;
2361}
2362
Lingfeng Yang69066602016-04-12 09:29:11 -07002363GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
2364 GL2Encoder* ctx = (GL2Encoder*)self;
2365 GLClientState* state = ctx->m_state;
2366
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002367 bool fboCompleteByCodec =
2368 ctx->checkFramebufferCompleteness(target, state);
2369
2370 if (!fboCompleteByCodec) {
2371 state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
Lingfeng Yang69066602016-04-12 09:29:11 -07002372 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2373 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002374 // double check with underlying opengl to avoid craziness.
Lingfeng Yang69066602016-04-12 09:29:11 -07002375 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002376 state->setCheckFramebufferStatus(target, host_checkstatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002377 if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE;
Lingfeng Yang69066602016-04-12 09:29:11 -07002378 return host_checkstatus;
2379 }
2380}
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002381
2382void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2383 GL2Encoder* ctx = (GL2Encoder*)self;
2384 GLClientState* state = ctx->m_state;
2385 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2386
2387 ctx->m_glGenVertexArrays_enc(self, n, arrays);
2388 for (int i = 0; i < n; i++) {
2389 ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2390 }
2391 state->addVertexArrayObjects(n, arrays);
2392}
2393
2394void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2395 GL2Encoder* ctx = (GL2Encoder*)self;
2396 GLClientState* state = ctx->m_state;
2397 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2398
2399 ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2400 for (int i = 0; i < n; i++) {
2401 ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2402 }
2403 state->removeVertexArrayObjects(n, arrays);
2404}
2405
2406void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2407 ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2408 GL2Encoder* ctx = (GL2Encoder*)self;
2409 GLClientState* state = ctx->m_state;
2410 SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2411 ctx->m_glBindVertexArray_enc(self, array);
2412 state->setVertexArrayObject(array);
2413}
2414
2415void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2416 GL2Encoder* ctx = (GL2Encoder*)self;
2417 GLClientState* state = ctx->m_state;
2418
2419 // begin validation (lots)
2420
2421 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2422
2423 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2424
2425 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2426
2427 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2428 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2429
2430 GLsizeiptr bufferDataSize = buf->m_size;
2431
2432 RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2433 RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2434 RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2435 RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2436
2437 RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2438 RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2439 RET_AND_SET_ERROR_IF(
2440 (access & GL_MAP_READ_BIT) &&
2441 ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2442 (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2443 (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2444 (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2445
2446 // end validation; actually do stuff now
2447
2448 buf->m_mapped = true;
2449 buf->m_mappedAccess = access;
2450 buf->m_mappedOffset = offset;
2451 buf->m_mappedLength = length;
2452
2453 char* todo = (char*)buf->m_fixedBuffer.ptr() + offset;
2454 ctx->glMapBufferRangeAEMU(
2455 ctx, target,
2456 offset, length,
2457 access,
2458 todo);
2459
2460 return todo;
2461}
2462
2463GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
2464 GL2Encoder* ctx = (GL2Encoder*)self;
2465 GLClientState* state = ctx->m_state;
2466
2467 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
2468
2469 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2470
2471 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
2472
2473 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2474 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
2475 RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
2476
Lingfeng Yang423129e2017-01-18 09:23:12 -08002477 if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
2478 // invalide index range cache here
2479 if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) {
2480 buf->m_indexRangeCache.invalidateRange(0, buf->m_size);
2481 } else {
2482 buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength);
2483 }
2484 }
2485
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002486 GLboolean host_res = GL_TRUE;
2487
2488 ctx->glUnmapBufferAEMU(
2489 ctx, target,
2490 buf->m_mappedOffset,
2491 buf->m_mappedLength,
2492 buf->m_mappedAccess,
2493 (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
2494 &host_res);
2495
2496 buf->m_mapped = false;
2497 buf->m_mappedAccess = 0;
2498 buf->m_mappedOffset = 0;
2499 buf->m_mappedLength = 0;
2500
2501 return host_res;
2502}
2503
2504void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
2505 GL2Encoder* ctx = (GL2Encoder*)self;
2506 GLClientState* state = ctx->m_state;
2507
2508 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2509
2510 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2511 SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
2512
2513 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2514 SET_ERROR_IF(!buf, GL_INVALID_VALUE);
2515 SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
2516 SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
2517
2518 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
2519 SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
2520 SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
2521
2522 GLintptr totalOffset = buf->m_mappedOffset + offset;
Lingfeng Yang423129e2017-01-18 09:23:12 -08002523
2524 buf->m_indexRangeCache.invalidateRange(totalOffset, length);
2525
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002526 ctx->glFlushMappedBufferRangeAEMU(
2527 ctx, target,
2528 totalOffset,
2529 length,
2530 buf->m_mappedAccess,
2531 (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
2532}
2533
2534void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
2535 GL2Encoder* ctx = (GL2Encoder*)self;
2536 GLClientState* state = ctx->m_state;
2537
2538 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2539 // Filter compressed formats support.
2540 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
2541 // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
2542 GLint max_texture_size;
2543 GLint max_cube_map_texture_size;
2544 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2545 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2546 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2547 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2548 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2549 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2550 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2551 SET_ERROR_IF(border, GL_INVALID_VALUE);
2552 // If unpack buffer is nonzero, verify unmapped state.
2553 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2554 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2555 // If unpack buffer is nonzero, verify buffer data fits.
2556 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2557 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2558 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2559 GL_INVALID_OPERATION);
2560 // TODO: Fix:
2561 // If |imageSize| is inconsistent with compressed dimensions.
2562 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
2563
2564 GLenum stateTarget = target;
2565 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2566 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2567 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2568 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2569 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2570 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2571 stateTarget = GL_TEXTURE_CUBE_MAP;
2572 state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
2573 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2574
2575 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2576 ctx->glCompressedTexImage2DOffsetAEMU(
2577 ctx, target, level, internalformat,
2578 width, height, border,
2579 imageSize, (uintptr_t)data);
2580 } else {
2581 ctx->m_glCompressedTexImage2D_enc(
2582 ctx, target, level, internalformat,
2583 width, height, border,
2584 imageSize, data);
2585 }
2586}
2587
2588void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
2589 GL2Encoder* ctx = (GL2Encoder*)self;
2590 GLClientState* state = ctx->m_state;
2591
2592 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2593 // If unpack buffer is nonzero, verify unmapped state.
2594 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2595 GLint max_texture_size;
2596 GLint max_cube_map_texture_size;
2597 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2598 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2599 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2600 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2601 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2602 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2603 // If unpack buffer is nonzero, verify buffer data fits.
2604 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2605 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2606 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2607 GL_INVALID_OPERATION);
2608 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2609
2610 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2611 ctx->glCompressedTexSubImage2DOffsetAEMU(
2612 ctx, target, level,
2613 xoffset, yoffset,
2614 width, height, format,
2615 imageSize, (uintptr_t)data);
2616 } else {
2617 ctx->m_glCompressedTexSubImage2D_enc(
2618 ctx, target, level,
2619 xoffset, yoffset,
2620 width, height, format,
2621 imageSize, data);
2622 }
2623}
2624
2625void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
2626 GL2Encoder* ctx = (GL2Encoder*)self;
2627 GLClientState* state = ctx->m_state;
2628
2629 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2630
2631 // Only works with certain targets
2632 SET_ERROR_IF(
2633 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2634 target == GL_SHADER_STORAGE_BUFFER ||
2635 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2636 target == GL_UNIFORM_BUFFER),
2637 GL_INVALID_ENUM);
2638
2639 // Can't exceed range
2640 SET_ERROR_IF(index < 0 ||
2641 index >= state->getMaxIndexedBufferBindings(target),
2642 GL_INVALID_VALUE);
2643 SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
2644 SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
2645 target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
2646 (size % 4 || offset % 4),
2647 GL_INVALID_VALUE);
2648
2649 GLint ssbo_offset_align, ubo_offset_align;
2650 ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
2651 ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
2652 SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
2653 offset % ssbo_offset_align,
2654 GL_INVALID_VALUE);
2655 SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
2656 offset % ubo_offset_align,
2657 GL_INVALID_VALUE);
2658
2659 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002660 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002661 state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0);
2662 ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size);
2663}
2664
2665void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
2666 GL2Encoder* ctx = (GL2Encoder*)self;
2667 GLClientState* state = ctx->m_state;
2668
2669 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2670
2671 // Only works with certain targets
2672 SET_ERROR_IF(
2673 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2674 target == GL_SHADER_STORAGE_BUFFER ||
2675 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2676 target == GL_UNIFORM_BUFFER),
2677 GL_INVALID_ENUM);
2678 // Can't exceed range
2679 SET_ERROR_IF(index < 0 ||
2680 index >= state->getMaxIndexedBufferBindings(target),
2681 GL_INVALID_VALUE);
2682
2683 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002684 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002685 BufferData* buf = ctx->getBufferDataById(buffer);
2686 state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0);
2687 ctx->m_glBindBufferBase_enc(self, target, index, buffer);
2688}
2689
2690void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
2691 GL2Encoder* ctx = (GL2Encoder*)self;
2692 GLClientState* state = ctx->m_state;
2693
2694 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
2695 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
2696 SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
2697 readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
2698 readtarget == GL_DRAW_INDIRECT_BUFFER ||
2699 readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2700 SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
2701 writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
2702 writetarget == GL_DRAW_INDIRECT_BUFFER ||
2703 writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2704 SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
2705 SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
2706 SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
2707 SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
2708 SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
2709 SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
2710 SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
2711 SET_ERROR_IF(
2712 ctx->getBufferData(readtarget) &&
2713 (readoffset + size > ctx->getBufferData(readtarget)->m_size),
2714 GL_INVALID_VALUE);
2715 SET_ERROR_IF(
2716 ctx->getBufferData(writetarget) &&
2717 (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
2718 GL_INVALID_VALUE);
2719 SET_ERROR_IF(readtarget == writetarget &&
2720 !((writeoffset >= readoffset + size) ||
2721 (readoffset >= writeoffset + size)),
2722 GL_INVALID_VALUE);
2723
2724 ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
2725}
2726
2727void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
2728 GL2Encoder* ctx = (GL2Encoder*)self;
2729
2730 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2731 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002732 target != GL_ARRAY_BUFFER &&
2733 target != GL_ELEMENT_ARRAY_BUFFER &&
2734 target != GL_COPY_READ_BUFFER &&
2735 target != GL_COPY_WRITE_BUFFER &&
2736 target != GL_PIXEL_PACK_BUFFER &&
2737 target != GL_PIXEL_UNPACK_BUFFER &&
2738 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
2739 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002740 GL_INVALID_ENUM);
2741 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
2742 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002743 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
2744 pname != GL_BUFFER_MAPPED &&
2745 pname != GL_BUFFER_SIZE &&
2746 pname != GL_BUFFER_USAGE &&
2747 pname != GL_BUFFER_MAP_LENGTH &&
2748 pname != GL_BUFFER_MAP_OFFSET,
2749 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002750
2751 if (!params) return;
2752
2753 BufferData* buf = ctx->getBufferData(target);
2754
2755 switch (pname) {
2756 case GL_BUFFER_ACCESS_FLAGS:
2757 *params = buf ? buf->m_mappedAccess : 0;
2758 break;
2759 case GL_BUFFER_MAPPED:
2760 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
2761 break;
2762 case GL_BUFFER_SIZE:
2763 *params = buf ? buf->m_size : 0;
2764 break;
2765 case GL_BUFFER_USAGE:
2766 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
2767 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002768 case GL_BUFFER_MAP_LENGTH:
2769 *params = buf ? buf->m_mappedLength : 0;
2770 break;
2771 case GL_BUFFER_MAP_OFFSET:
2772 *params = buf ? buf->m_mappedOffset : 0;
2773 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002774 default:
2775 break;
2776 }
2777}
2778
2779void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
2780 GL2Encoder* ctx = (GL2Encoder*)self;
2781
2782 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2783 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002784 target != GL_ARRAY_BUFFER &&
2785 target != GL_ELEMENT_ARRAY_BUFFER &&
2786 target != GL_COPY_READ_BUFFER &&
2787 target != GL_COPY_WRITE_BUFFER &&
2788 target != GL_PIXEL_PACK_BUFFER &&
2789 target != GL_PIXEL_UNPACK_BUFFER &&
2790 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
2791 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002792 GL_INVALID_ENUM);
2793 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
2794 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002795 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
2796 pname != GL_BUFFER_MAPPED &&
2797 pname != GL_BUFFER_SIZE &&
2798 pname != GL_BUFFER_USAGE &&
2799 pname != GL_BUFFER_MAP_LENGTH &&
2800 pname != GL_BUFFER_MAP_OFFSET,
2801 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002802
2803 if (!params) return;
2804
2805 BufferData* buf = ctx->getBufferData(target);
2806
2807 switch (pname) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002808 case GL_BUFFER_ACCESS_FLAGS:
2809 *params = buf ? buf->m_mappedAccess : 0;
2810 break;
2811 case GL_BUFFER_MAPPED:
2812 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
2813 break;
2814 case GL_BUFFER_SIZE:
2815 *params = buf ? buf->m_size : 0;
2816 break;
2817 case GL_BUFFER_USAGE:
2818 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
2819 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002820 case GL_BUFFER_MAP_LENGTH:
2821 *params = buf ? buf->m_mappedLength : 0;
2822 break;
2823 case GL_BUFFER_MAP_OFFSET:
2824 *params = buf ? buf->m_mappedOffset : 0;
2825 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002826 default:
2827 break;
2828 }
2829}
2830
2831void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
2832 GL2Encoder* ctx = (GL2Encoder*)self;
2833 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2834 SET_ERROR_IF(
2835 target == GL_ATOMIC_COUNTER_BUFFER ||
2836 target == GL_DISPATCH_INDIRECT_BUFFER ||
2837 target == GL_DRAW_INDIRECT_BUFFER ||
2838 target == GL_SHADER_STORAGE_BUFFER,
2839 GL_INVALID_ENUM);
2840 SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
2841 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
2842 if (!params) return;
2843
2844 BufferData* buf = ctx->getBufferData(target);
2845
2846 if (!buf || !buf->m_mapped) { *params = NULL; return; }
2847
2848 *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
2849}
2850
2851static const char* const kNameDelimiter = ";";
2852
2853static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
2854
2855#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
2856
2857 std::string packed;
2858 // validate the array of char[]'s
2859 const char* currName;
2860 for (GLsizei i = 0; i < count; i++) {
2861 currName = names[i];
2862 VALIDATE(!currName, GL_INVALID_OPERATION);
2863 // check if has reasonable size
2864 size_t len = strlen(currName);
2865 VALIDATE(!len, GL_INVALID_OPERATION);
2866 // check for our delimiter, which if present
2867 // in the name, means an invalid name anyway.
2868 VALIDATE(strstr(currName, kNameDelimiter),
2869 GL_INVALID_OPERATION);
2870 packed += currName;
2871 packed += ";";
2872 }
2873
2874 *err_out = GL_NO_ERROR;
2875 return packed;
2876}
2877
2878void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
2879 GL2Encoder* ctx = (GL2Encoder*)self;
2880
2881 if (!uniformCount) return;
2882
2883 GLint err = GL_NO_ERROR;
2884 std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
2885 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
2886
2887 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
2888 std::vector<int> arrIndices;
2889 for (size_t i = 0; i < uniformCount; i++) {
2890 int err;
2891 arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
2892 if (err) {
2893 ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
2894 return;
2895 }
2896 }
2897
2898 ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
2899
2900 for (int i = 0; i < uniformCount; i++) {
2901 if (uniformIndices[i] >= 0 && needLocationWAR) {
2902 uniformIndices[i] =
2903 ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
2904 }
2905 }
2906}
2907
2908void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
2909 GL2Encoder *ctx = (GL2Encoder*)self;
2910 GLClientState* state = ctx->m_state;
2911 GLSharedGroupPtr shared = ctx->m_shared;
2912
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002913 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002914 ctx->m_glUniform1ui_enc(self, hostLoc, v0);
2915
2916 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002917 if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002918 GLenum origActiveTexture = state->getActiveTextureUnit();
2919 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
2920 ctx->m_glActiveTexture_enc(self, origActiveTexture);
2921 }
2922 state->setActiveTextureUnit(origActiveTexture);
2923 }
2924}
2925
2926void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) {
2927 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002928 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002929 ctx->m_glUniform2ui_enc(self, hostLoc, v0, v1);
2930}
2931
2932void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) {
2933 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002934 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002935 ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2);
2936}
2937
2938void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) {
2939 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002940 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002941 ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3);
2942}
2943
2944void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2945 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002946 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002947 ctx->m_glUniform1uiv_enc(self, hostLoc, count, value);
2948}
2949
2950void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2951 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002952 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002953 ctx->m_glUniform2uiv_enc(self, hostLoc, count, value);
2954}
2955
2956void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2957 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002958 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002959 ctx->m_glUniform3uiv_enc(self, hostLoc, count, value);
2960}
2961
2962void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
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_glUniform4uiv_enc(self, hostLoc, count, value);
2966}
2967
2968void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
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_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value);
2972}
2973
2974void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
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_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value);
2978}
2979
2980void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *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_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value);
2984}
2985
2986void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *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_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value);
2990}
2991
2992void GL2Encoder::s_glUniformMatrix3x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *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_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value);
2996}
2997
2998void GL2Encoder::s_glUniformMatrix4x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *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_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value);
3002}
3003
3004void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3005 GL2Encoder *ctx = (GL2Encoder*)self;
3006 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3007 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3008 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3009 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3010 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3011 ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3012}
3013
3014void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3015 GL2Encoder* ctx = (GL2Encoder*)self;
3016 GLClientState* state = ctx->m_state;
3017
3018 // refresh client state's # active uniforms in this block
3019 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3020 // TODO if worth it: cache uniform count and other params,
3021 // invalidate on program relinking.
3022 GLint numActiveUniforms;
3023 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3024 program, uniformBlockIndex,
3025 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3026 &numActiveUniforms);
3027 ctx->m_state->setNumActiveUniformsInUniformBlock(
3028 program, uniformBlockIndex, numActiveUniforms);
3029 }
3030
3031 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3032 program, uniformBlockIndex,
3033 pname, params);
3034}
3035
3036void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3037 GL2Encoder *ctx = (GL2Encoder *)self;
3038 assert(ctx->m_state);
3039 GLint maxIndex;
3040 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3041 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3042
3043 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3044 ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3045 }
3046}
3047
3048void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3049 GL2Encoder *ctx = (GL2Encoder *)self;
3050 assert(ctx->m_state);
3051 GLint maxIndex;
3052 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3053 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3054
3055 if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3056 ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3057 }
3058}
3059
3060void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3061 GL2Encoder *ctx = (GL2Encoder *)self;
3062 assert(ctx->m_state != NULL);
3063 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
3064 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
3065 SET_ERROR_IF(
3066 !(type == GL_BYTE ||
3067 type == GL_UNSIGNED_BYTE ||
3068 type == GL_SHORT ||
3069 type == GL_UNSIGNED_SHORT ||
3070 type == GL_INT ||
3071 type == GL_UNSIGNED_INT),
3072 GL_INVALID_ENUM);
3073 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
3074
3075 ctx->m_state->setVertexAttribBinding(index, index);
3076 ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true);
3077 GLsizei effectiveStride = stride;
3078 if (stride == 0) {
3079 effectiveStride = glSizeof(type) * size;
3080 }
3081 ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride);
3082
3083 if (ctx->m_state->currentArrayVbo() != 0) {
3084 ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer);
3085 } else {
3086 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION);
3087 // wait for client-array handler
3088 }
3089}
3090
3091void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) {
3092 GL2Encoder *ctx = (GL2Encoder *)self;
3093 assert(ctx->m_state != NULL);
3094 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
3095 ctx->m_state->setVertexAttribBinding(index, index);
3096 ctx->m_state->setVertexBindingDivisor(index, divisor);
3097 ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor);
3098}
3099
3100void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3101 GLenum target, GLsizei samples, GLenum internalformat,
3102 GLsizei width, GLsizei height) {
3103 GL2Encoder *ctx = (GL2Encoder *)self;
3104 GLClientState* state = ctx->m_state;
3105
3106 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3107 SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3108
3109 GLint max_samples;
3110 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3111 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3112
3113 state->setBoundRenderbufferFormat(internalformat);
3114 state->setBoundRenderbufferSamples(samples);
3115 ctx->m_glRenderbufferStorageMultisample_enc(
3116 self, target, samples, internalformat, width, height);
3117}
3118
3119void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3120 GL2Encoder* ctx = (GL2Encoder*)self;
3121 SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3122 SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3123 for (int i = 0; i < n; i++) {
3124 SET_ERROR_IF(
3125 bufs[i] != GL_NONE &&
3126 bufs[i] != GL_BACK &&
3127 glUtilsColorAttachmentIndex(bufs[i]) == -1,
3128 GL_INVALID_ENUM);
3129 SET_ERROR_IF(
3130 !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3131 glUtilsColorAttachmentIndex(bufs[i]) != -1,
3132 GL_INVALID_OPERATION);
3133 SET_ERROR_IF(
3134 ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3135 ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3136 glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3137 (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3138 bufs[i] != GL_NONE)),
3139 GL_INVALID_OPERATION);
3140 }
3141
3142 ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3143}
3144
3145void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3146 GL2Encoder* ctx = (GL2Encoder*)self;
3147
3148 SET_ERROR_IF(
3149 glUtilsColorAttachmentIndex(src) != -1 &&
3150 (glUtilsColorAttachmentIndex(src) >=
3151 ctx->m_state->getMaxColorAttachments()),
3152 GL_INVALID_OPERATION);
3153 SET_ERROR_IF(
3154 src != GL_NONE &&
3155 src != GL_BACK &&
3156 src > GL_COLOR_ATTACHMENT0 &&
3157 src < GL_DEPTH_ATTACHMENT &&
3158 (src - GL_COLOR_ATTACHMENT0) >
3159 ctx->m_state->getMaxColorAttachments(),
3160 GL_INVALID_OPERATION);
3161 SET_ERROR_IF(
3162 src != GL_NONE &&
3163 src != GL_BACK &&
3164 glUtilsColorAttachmentIndex(src) == -1,
3165 GL_INVALID_ENUM);
3166 SET_ERROR_IF(
3167 !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3168 src != GL_NONE &&
3169 src != GL_BACK,
3170 GL_INVALID_OPERATION);
3171 SET_ERROR_IF(
3172 ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3173 src != GL_NONE &&
3174 glUtilsColorAttachmentIndex(src) == -1,
3175 GL_INVALID_OPERATION);
3176
3177 ctx->m_glReadBuffer_enc(ctx, src);
3178}
3179
3180void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3181 GL2Encoder* ctx = (GL2Encoder*)self;
3182 GLClientState* state = ctx->m_state;
3183
3184 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3185 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3186 GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3187 SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3188 lastBoundTarget != GL_TEXTURE_3D,
3189 GL_INVALID_OPERATION);
3190 state->attachTextureObject(target, attachment, texture);
3191
3192 GLint max3DTextureSize;
3193 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3194 SET_ERROR_IF(
3195 layer >= max3DTextureSize,
3196 GL_INVALID_VALUE);
3197
3198 ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3199}
3200
3201void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3202 GL2Encoder* ctx = (GL2Encoder*)self;
3203 GLClientState* state = ctx->m_state;
3204
3205 SET_ERROR_IF(
3206 target != GL_TEXTURE_2D &&
3207 target != GL_TEXTURE_CUBE_MAP,
3208 GL_INVALID_ENUM);
3209 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3210 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3211 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3212 SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3213 GL_INVALID_OPERATION);
3214 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3215
3216 state->setBoundTextureInternalFormat(target, internalformat);
3217 state->setBoundTextureDims(target, -1, width, height, 1);
3218 state->setBoundTextureImmutableFormat(target);
3219 ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
3220}
3221
3222void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3223 GL2Encoder* ctx = (GL2Encoder*)self;
3224
3225 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3226
3227 GLint maxCount = 0;
3228 ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3229
3230 SET_ERROR_IF(
3231 bufferMode == GL_SEPARATE_ATTRIBS &&
3232 maxCount < count,
3233 GL_INVALID_VALUE);
3234 SET_ERROR_IF(
3235 bufferMode != GL_INTERLEAVED_ATTRIBS &&
3236 bufferMode != GL_SEPARATE_ATTRIBS,
3237 GL_INVALID_ENUM);
3238
3239 if (!count) return;
3240
3241 GLint err = GL_NO_ERROR;
3242 std::string packed = packVarNames(count, varyings, &err);
3243 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3244
3245 ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3246}
3247
3248void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3249 GL2Encoder* ctx = (GL2Encoder*)self;
3250 GLClientState* state = ctx->m_state;
3251 ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3252 state->setTransformFeedbackActiveUnpaused(true);
3253}
3254
3255void GL2Encoder::s_glEndTransformFeedback(void* self) {
3256 GL2Encoder* ctx = (GL2Encoder*)self;
3257 GLClientState* state = ctx->m_state;
3258 ctx->m_glEndTransformFeedback_enc(ctx);
3259 state->setTransformFeedbackActiveUnpaused(false);
3260}
3261
3262void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3263 GL2Encoder* ctx = (GL2Encoder*)self;
3264 GLClientState* state = ctx->m_state;
3265 ctx->m_glPauseTransformFeedback_enc(ctx);
3266 state->setTransformFeedbackActiveUnpaused(false);
3267}
3268
3269void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3270 GL2Encoder* ctx = (GL2Encoder*)self;
3271 GLClientState* state = ctx->m_state;
3272 ctx->m_glResumeTransformFeedback_enc(ctx);
3273 state->setTransformFeedbackActiveUnpaused(true);
3274}
3275
3276void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3277 GLsizei width, GLsizei height, GLsizei depth,
3278 GLint border, GLenum format, GLenum type, const GLvoid* data) {
3279 GL2Encoder* ctx = (GL2Encoder*)self;
3280 GLClientState* state = ctx->m_state;
3281
3282 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3283 target != GL_TEXTURE_2D_ARRAY,
3284 GL_INVALID_ENUM);
3285 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3286 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3287
3288 // If unpack buffer is nonzero, verify unmapped state.
3289 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3290
3291 GLint max_texture_size;
3292 GLint max_3d_texture_size;
3293 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3294 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3295 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3296 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3297 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3298
3299 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3300 SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3301 SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3302 SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3303 SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3304 SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3305 SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3306 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3307 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3308 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3309 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3310 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3311 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3312 GL_INVALID_OPERATION);
3313 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3314 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3315 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3316 glSizeof(type)),
3317 GL_INVALID_OPERATION);
3318 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3319
3320 state->setBoundTextureInternalFormat(target, internalFormat);
3321 state->setBoundTextureFormat(target, format);
3322 state->setBoundTextureType(target, type);
3323 state->setBoundTextureDims(target, level, width, height, depth);
3324
3325 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3326 ctx->glTexImage3DOffsetAEMU(
3327 ctx, target, level, internalFormat,
3328 width, height, depth,
3329 border, format, type, (uintptr_t)data);
3330 } else {
3331 ctx->m_glTexImage3D_enc(ctx,
3332 target, level, internalFormat,
3333 width, height, depth,
3334 border, format, type, data);
3335 }
3336}
3337
3338void 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) {
3339 GL2Encoder* ctx = (GL2Encoder*)self;
3340 GLClientState* state = ctx->m_state;
3341
3342 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3343 target != GL_TEXTURE_2D_ARRAY,
3344 GL_INVALID_ENUM);
3345 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3346 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3347 // If unpack buffer is nonzero, verify unmapped state.
3348 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3349 GLint max_texture_size;
3350 GLint max_3d_texture_size;
3351 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3352 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3353 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3354 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3355 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3356 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3357 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3358 GLuint tex = state->getBoundTexture(target);
3359 GLsizei neededWidth = xoffset + width;
3360 GLsizei neededHeight = yoffset + height;
3361 GLsizei neededDepth = zoffset + depth;
3362
3363 SET_ERROR_IF(tex &&
3364 (neededWidth > state->queryTexWidth(level, tex) ||
3365 neededHeight > state->queryTexHeight(level, tex) ||
3366 neededDepth > state->queryTexDepth(level, tex)),
3367 GL_INVALID_VALUE);
3368 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3369 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3370 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3371 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3372 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3373 GL_INVALID_OPERATION);
3374 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3375 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3376 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3377 glSizeof(type)),
3378 GL_INVALID_OPERATION);
3379 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
3380 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3381
3382 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3383 ctx->glTexSubImage3DOffsetAEMU(ctx,
3384 target, level,
3385 xoffset, yoffset, zoffset,
3386 width, height, depth,
3387 format, type, (uintptr_t)data);
3388 } else {
3389 ctx->m_glTexSubImage3D_enc(ctx,
3390 target, level,
3391 xoffset, yoffset, zoffset,
3392 width, height, depth,
3393 format, type, data);
3394 }
3395}
3396
3397void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
3398 GL2Encoder* ctx = (GL2Encoder*)self;
3399 GLClientState* state = ctx->m_state;
3400
3401 // Filter compressed formats support.
3402 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3403 // If unpack buffer is nonzero, verify unmapped state.
3404 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3405 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3406 SET_ERROR_IF(border, GL_INVALID_VALUE);
3407 // If unpack buffer is nonzero, verify buffer data fits.
3408 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3409 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3410 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3411 GL_INVALID_OPERATION);
3412 // TODO: Fix:
3413 // If |imageSize| is too small for compressed dimensions.
3414 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
3415 state->setBoundTextureInternalFormat(target, (GLint)internalformat);
3416 state->setBoundTextureDims(target, level, width, height, depth);
3417
3418 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3419 ctx->glCompressedTexImage3DOffsetAEMU(
3420 ctx, target, level, internalformat,
3421 width, height, depth, border,
3422 imageSize, (uintptr_t)data);
3423 } else {
3424 ctx->m_glCompressedTexImage3D_enc(
3425 ctx, target, level, internalformat,
3426 width, height, depth, border,
3427 imageSize, data);
3428 }
3429}
3430
3431void 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) {
3432 GL2Encoder* ctx = (GL2Encoder*)self;
3433 GLClientState* state = ctx->m_state;
3434
3435 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3436 // If unpack buffer is nonzero, verify unmapped state.
3437 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3438 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3439 // If unpack buffer is nonzero, verify buffer data fits.
3440 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3441 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3442 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3443 GL_INVALID_OPERATION);
3444 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3445
3446 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3447 ctx->glCompressedTexSubImage3DOffsetAEMU(
3448 ctx, target, level,
3449 xoffset, yoffset, zoffset,
3450 width, height, depth,
3451 format, imageSize, (uintptr_t)data);
3452 } else {
3453 ctx->m_glCompressedTexSubImage3D_enc(
3454 ctx, target, level,
3455 xoffset, yoffset, zoffset,
3456 width, height, depth,
3457 format, imageSize, data);
3458
3459 }
3460}
3461
3462void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
3463 GL2Encoder* ctx = (GL2Encoder*)self;
3464 GLClientState* state = ctx->m_state;
3465 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3466 target != GL_TEXTURE_2D_ARRAY,
3467 GL_INVALID_ENUM);
3468 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3469 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3470 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3471 SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
3472 GL_INVALID_OPERATION);
3473 SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
3474 GL_INVALID_OPERATION);
3475 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3476
3477 state->setBoundTextureInternalFormat(target, internalformat);
3478 state->setBoundTextureDims(target, -1, width, height, depth);
3479 state->setBoundTextureImmutableFormat(target);
3480 ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
3481 state->setBoundTextureImmutableFormat(target);
3482}
3483
3484void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
3485 GL2Encoder *ctx = (GL2Encoder *)self;
3486 assert(ctx->m_state != NULL);
3487 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3488 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3489
3490 bool has_client_vertex_arrays = false;
3491 bool has_indirect_arrays = false;
3492 ctx->getVBOUsage(&has_client_vertex_arrays,
3493 &has_indirect_arrays);
3494
3495 if (has_client_vertex_arrays ||
3496 (!has_client_vertex_arrays &&
3497 !has_indirect_arrays)) {
3498 ctx->sendVertexAttributes(first, count, true, primcount);
3499 ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
3500 } else {
3501 ctx->sendVertexAttributes(0, count, false, primcount);
3502 ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
3503 }
3504 ctx->m_stream->flush();
3505}
3506
3507void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
3508{
3509
3510 GL2Encoder *ctx = (GL2Encoder *)self;
3511 assert(ctx->m_state != NULL);
3512 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3513 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3514 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3515 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3516
3517 bool has_client_vertex_arrays = false;
3518 bool has_indirect_arrays = false;
3519 int nLocations = ctx->m_state->nLocations();
3520 GLintptr offset = 0;
3521
3522 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3523
3524 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3525 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3526 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3527 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3528 }
3529
3530 BufferData* buf = NULL;
3531 int minIndex = 0, maxIndex = 0;
3532
3533 // For validation/immediate index array purposes,
3534 // we need the min/max vertex index of the index array.
3535 // If the VBO != 0, this may not be the first time we have
3536 // used this particular index buffer. getBufferIndexRange
3537 // can more quickly get min/max vertex index by
3538 // caching previous results.
3539 if (ctx->m_state->currentIndexVbo() != 0) {
3540 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3541 offset = (GLintptr)indices;
3542 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3543 ctx->getBufferIndexRange(buf,
3544 indices,
3545 type,
3546 (size_t)count,
3547 (size_t)offset,
3548 &minIndex, &maxIndex);
3549 } else {
3550 // In this case, the |indices| field holds a real
3551 // array, so calculate the indices now. They will
3552 // also be needed to know how much data to
3553 // transfer to host.
3554 ctx->calcIndexRange(indices,
3555 type,
3556 count,
3557 &minIndex,
3558 &maxIndex);
3559 }
3560
3561 bool adjustIndices = true;
3562 if (ctx->m_state->currentIndexVbo() != 0) {
3563 if (!has_client_vertex_arrays) {
3564 ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
3565 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3566 ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
3567 ctx->flushDrawCall();
3568 adjustIndices = false;
3569 } else {
3570 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3571 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3572 }
3573 }
3574 if (adjustIndices) {
3575 void *adjustedIndices =
3576 ctx->recenterIndices(indices,
3577 type,
3578 count,
3579 minIndex);
3580
3581 if (has_indirect_arrays || 1) {
3582 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
3583 ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
3584 ctx->m_stream->flush();
3585 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3586 if(!has_indirect_arrays) {
3587 //ALOGD("unoptimized drawelements !!!\n");
3588 }
3589 } else {
3590 // we are all direct arrays and immidate mode index array -
3591 // rebuild the arrays and the index array;
3592 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3593 }
3594 }
3595}
3596
3597void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
3598{
3599
3600 GL2Encoder *ctx = (GL2Encoder *)self;
3601 assert(ctx->m_state != NULL);
3602 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3603 SET_ERROR_IF(end < start, GL_INVALID_VALUE);
3604 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3605 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3606 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3607
3608 bool has_client_vertex_arrays = false;
3609 bool has_indirect_arrays = false;
3610 int nLocations = ctx->m_state->nLocations();
3611 GLintptr offset = 0;
3612
3613 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3614
3615 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3616 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3617 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3618 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3619 }
3620
3621 BufferData* buf = NULL;
3622 int minIndex = 0, maxIndex = 0;
3623
3624 // For validation/immediate index array purposes,
3625 // we need the min/max vertex index of the index array.
3626 // If the VBO != 0, this may not be the first time we have
3627 // used this particular index buffer. getBufferIndexRange
3628 // can more quickly get min/max vertex index by
3629 // caching previous results.
3630 if (ctx->m_state->currentIndexVbo() != 0) {
3631 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3632 offset = (GLintptr)indices;
3633 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3634 ctx->getBufferIndexRange(buf,
3635 indices,
3636 type,
3637 (size_t)count,
3638 (size_t)offset,
3639 &minIndex, &maxIndex);
3640 } else {
3641 // In this case, the |indices| field holds a real
3642 // array, so calculate the indices now. They will
3643 // also be needed to know how much data to
3644 // transfer to host.
3645 ctx->calcIndexRange(indices,
3646 type,
3647 count,
3648 &minIndex,
3649 &maxIndex);
3650 }
3651
3652 bool adjustIndices = true;
3653 if (ctx->m_state->currentIndexVbo() != 0) {
3654 if (!has_client_vertex_arrays) {
3655 ctx->sendVertexAttributes(0, maxIndex + 1, false);
3656 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3657 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
3658 ctx->flushDrawCall();
3659 adjustIndices = false;
3660 } else {
3661 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3662 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3663 }
3664 }
3665 if (adjustIndices) {
3666 void *adjustedIndices =
3667 ctx->recenterIndices(indices,
3668 type,
3669 count,
3670 minIndex);
3671
3672 if (has_indirect_arrays || 1) {
3673 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
3674 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
3675 ctx->m_stream->flush();
3676 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3677 if(!has_indirect_arrays) {
3678 //ALOGD("unoptimized drawelements !!!\n");
3679 }
3680 } else {
3681 // we are all direct arrays and immidate mode index array -
3682 // rebuild the arrays and the index array;
3683 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3684 }
3685 }
3686}
3687
3688// struct GLStringKey {
3689// GLenum name;
3690// GLuint index;
3691// };
3692//
3693// struct GLStringKeyCompare {
3694// bool operator() (const GLStringKey& a,
3695// const GLStringKey& b) const {
3696// if (a.name != b.name) return a.name < b.name;
3697// if (a.index != b.index) return a.index < b.index;
3698// return false;
3699// }
3700// };
3701//
3702// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
3703//
3704// static GLStringStore sGLStringStore;
3705// bool sGLStringStoreInitialized = false;
3706
3707const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
3708 GL2Encoder *ctx = (GL2Encoder *)self;
3709 GLubyte *retval = (GLubyte *) "";
3710
3711 RET_AND_SET_ERROR_IF(
3712 name != GL_VENDOR &&
3713 name != GL_RENDERER &&
3714 name != GL_VERSION &&
3715 name != GL_EXTENSIONS,
3716 GL_INVALID_ENUM,
3717 retval);
3718
3719 RET_AND_SET_ERROR_IF(
3720 name == GL_VENDOR ||
3721 name == GL_RENDERER ||
3722 name == GL_VERSION ||
3723 name == GL_EXTENSIONS &&
3724 index != 0,
3725 GL_INVALID_VALUE,
3726 retval);
3727
3728 switch (name) {
3729 case GL_VENDOR:
3730 retval = gVendorString;
3731 break;
3732 case GL_RENDERER:
3733 retval = gRendererString;
3734 break;
3735 case GL_VERSION:
3736 retval = gVersionString;
3737 break;
3738 case GL_EXTENSIONS:
3739 retval = gExtensionsString;
3740 break;
3741 }
3742
3743 return retval;
3744}
3745
3746void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
3747 GL2Encoder *ctx = (GL2Encoder *)self;
3748
3749 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3750
3751 GLint linkStatus = 0;
3752 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
3753 GLint properLength = 0;
3754 ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
3755
3756 SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
3757 SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
3758
3759 ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
3760}
3761
3762void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
3763 GL2Encoder *ctx = (GL2Encoder *)self;
3764
3765 SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
3766 SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
3767 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
3768 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
3769 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
3770 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
3771 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
3772 ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
3773 GL_INVALID_OPERATION);
3774 /*
3775GL_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.
3776
3777GL_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.
3778
3779GL_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.
3780
3781GL_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.
3782*/
3783
3784 FboFormatInfo fbo_format_info;
3785 ctx->m_state->getBoundFramebufferFormat(
3786 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
3787 SET_ERROR_IF(
3788 fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3789 !GLESv2Validation::readPixelsFboFormatMatch(
3790 format, type, fbo_format_info.tex_type),
3791 GL_INVALID_OPERATION);
3792
3793 if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
3794 ctx->glReadPixelsOffsetAEMU(
3795 ctx, x, y, width, height,
3796 format, type, (uintptr_t)pixels);
3797 } else {
3798 ctx->m_glReadPixels_enc(
3799 ctx, x, y, width, height,
3800 format, type, pixels);
3801 }
3802}
3803
3804// Track enabled state for some things like:
3805// - Primitive restart
3806void GL2Encoder::s_glEnable(void* self, GLenum what) {
3807 GL2Encoder *ctx = (GL2Encoder *)self;
3808
3809 switch (what) {
3810 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
3811 ctx->m_primitiveRestartEnabled = true;
3812 break;
3813 }
3814
3815 ctx->m_glEnable_enc(ctx, what);
3816}
3817
3818void GL2Encoder::s_glDisable(void* self, GLenum what) {
3819 GL2Encoder *ctx = (GL2Encoder *)self;
3820
3821 switch (what) {
3822 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
3823 ctx->m_primitiveRestartEnabled = false;
3824 break;
3825 }
3826
3827 ctx->m_glDisable_enc(ctx, what);
3828}
3829
3830void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
3831 GL2Encoder *ctx = (GL2Encoder *)self;
3832
3833 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3834
3835 ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
3836}
3837
3838void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
3839 GL2Encoder *ctx = (GL2Encoder *)self;
3840
3841 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3842
3843 ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
3844}
3845
3846void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
3847 GL2Encoder *ctx = (GL2Encoder *)self;
3848
3849 SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3850
3851 ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
3852}
3853
3854void 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) {
3855 GL2Encoder *ctx = (GL2Encoder *)self;
3856 GLClientState* state = ctx->m_state;
3857
3858 bool validateColor = mask | GL_COLOR_BUFFER_BIT;
3859 bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
3860 bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
3861
3862 FboFormatInfo read_fbo_format_info;
3863 FboFormatInfo draw_fbo_format_info;
3864 if (validateColor) {
3865 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
3866 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
3867
3868 if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3869 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
3870 SET_ERROR_IF(
3871 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3872 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3873 !GLESv2Validation::blitFramebufferFormat(
3874 read_fbo_format_info.tex_type,
3875 draw_fbo_format_info.tex_type),
3876 GL_INVALID_OPERATION);
3877 }
3878 }
3879
3880 if (validateDepth) {
3881 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
3882 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
3883
3884 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3885 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
3886 SET_ERROR_IF(
3887 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3888 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3889 !GLESv2Validation::blitFramebufferFormat(
3890 read_fbo_format_info.rb_format,
3891 draw_fbo_format_info.rb_format),
3892 GL_INVALID_OPERATION);
3893 }
3894 }
3895
3896 if (validateStencil) {
3897 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
3898 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
3899
3900 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3901 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
3902 SET_ERROR_IF(
3903 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3904 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3905 !GLESv2Validation::blitFramebufferFormat(
3906 read_fbo_format_info.rb_format,
3907 draw_fbo_format_info.rb_format),
3908 GL_INVALID_OPERATION);
3909 }
3910 }
3911
3912 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
3913 SET_ERROR_IF(
3914 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3915 draw_fbo_format_info.rb_multisamples > 0,
3916 GL_INVALID_OPERATION);
3917 SET_ERROR_IF(
3918 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3919 draw_fbo_format_info.tex_multisamples > 0,
3920 GL_INVALID_OPERATION);
3921
3922 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
3923 SET_ERROR_IF(
3924 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3925 read_fbo_format_info.rb_multisamples > 0 &&
3926 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3927 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3928 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3929 (read_fbo_format_info.rb_format !=
3930 draw_fbo_format_info.rb_format),
3931 GL_INVALID_OPERATION);
3932 SET_ERROR_IF(
3933 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3934 read_fbo_format_info.rb_multisamples > 0 &&
3935 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3936 (srcX0 != dstX0 || srcY0 != dstY0 ||
3937 srcX1 != dstX1 || srcY1 != dstY1),
3938 GL_INVALID_OPERATION);
3939
3940 ctx->m_glBlitFramebuffer_enc(ctx,
3941 srcX0, srcY0, srcX1, srcY1,
3942 dstX0, dstY0, dstX1, dstY1,
3943 mask, filter);
3944}
3945
3946void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
3947 GL2Encoder *ctx = (GL2Encoder *)self;
3948
3949 SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
3950 pname != GL_SAMPLES,
3951 GL_INVALID_ENUM);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003952 SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003953 SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
3954 !GLESv2Validation::colorRenderableFormat(internalformat) &&
3955 !GLESv2Validation::depthRenderableFormat(internalformat) &&
3956 !GLESv2Validation::stencilRenderableFormat(internalformat),
3957 GL_INVALID_ENUM);
3958 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
3959
3960 if (bufSize < 1) return;
3961
3962 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
3963 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
3964 switch (pname) {
3965 case GL_NUM_SAMPLE_COUNTS:
3966 *params = 3;
3967 break;
3968 case GL_SAMPLES:
3969 params[0] = 4;
3970 if (bufSize > 1) params[1] = 2;
3971 if (bufSize > 2) params[2] = 1;
3972 break;
3973 default:
3974 break;
3975 }
3976}
3977
3978void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
3979 GL2Encoder *ctx = (GL2Encoder *)self;
3980 GLClientState* state = ctx->m_state;
3981
3982 SET_ERROR_IF(target != GL_TEXTURE_2D &&
3983 target != GL_TEXTURE_3D &&
3984 target != GL_TEXTURE_CUBE_MAP,
3985 GL_INVALID_ENUM);
3986
3987 GLuint tex = state->getBoundTexture(target);
3988 GLenum internalformat = state->queryTexInternalFormat(tex);
3989 GLenum format = state->queryTexFormat(tex);
3990
3991 SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
3992 GL_INVALID_OPERATION);
3993 SET_ERROR_IF(tex &&
3994 !GLESv2Validation::unsizedFormat(internalformat) &&
3995 (!GLESv2Validation::colorRenderableFormat(internalformat) ||
3996 !GLESv2Validation::filterableTexFormat(internalformat)),
3997 GL_INVALID_OPERATION);
3998
3999 ctx->m_glGenerateMipmap_enc(ctx, target);
4000}
4001
4002void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4003 GL2Encoder *ctx = (GL2Encoder *)self;
4004 GLint maxCombinedUnits;
4005 ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4006 SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4007
4008 ctx->m_glBindSampler_enc(ctx, unit, sampler);
4009}
4010
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004011GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4012 GL2Encoder *ctx = (GL2Encoder *)self;
4013 uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4014 return (GLsync)(uintptr_t)syncHandle;
4015}
4016
4017GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4018 GL2Encoder *ctx = (GL2Encoder *)self;
4019 return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4020}
4021
4022void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4023 GL2Encoder *ctx = (GL2Encoder *)self;
4024 ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4025}
4026
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004027void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) {
4028 GL2Encoder *ctx = (GL2Encoder *)self;
4029
4030 if (!sync) return;
4031
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004032 ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4033}
4034
4035GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4036 GL2Encoder *ctx = (GL2Encoder *)self;
4037 return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4038}
4039
4040void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4041 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004042
4043 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4044
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004045 return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004046}
4047
4048#define LIMIT_CASE(target, lim) \
4049 case target: \
4050 ctx->glGetIntegerv(ctx, lim, &limit); \
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004051 SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004052 break; \
4053
4054void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) {
4055 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004056 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004057
4058 GLint limit;
4059
4060 switch (target) {
4061 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4062 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4063 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4064 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4065 default:
4066 break;
4067 }
4068
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004069 const GLClientState::VertexAttribBindingVector& currBindings =
4070 state->currentVertexBufferBindings();
4071
4072 switch (target) {
4073 case GL_VERTEX_BINDING_DIVISOR:
4074 case GL_VERTEX_BINDING_OFFSET:
4075 case GL_VERTEX_BINDING_STRIDE:
4076 case GL_VERTEX_BINDING_BUFFER:
4077 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4078 break;
4079 default:
4080 break;
4081 }
4082
4083 switch (target) {
4084 case GL_VERTEX_BINDING_DIVISOR:
4085 *params = currBindings[index].divisor;
4086 return;
4087 case GL_VERTEX_BINDING_OFFSET:
4088 *params = currBindings[index].offset;
4089 return;
4090 case GL_VERTEX_BINDING_STRIDE:
4091 *params = currBindings[index].effectiveStride;
4092 return;
4093 case GL_VERTEX_BINDING_BUFFER:
4094 *params = currBindings[index].buffer;
4095 return;
4096 default:
4097 break;
4098 }
4099
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004100 ctx->m_glGetIntegeri_v_enc(self, target, index, params);
4101}
4102
4103void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
4104 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004105 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004106
4107 GLint limit;
4108
4109 switch (target) {
4110 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4111 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4112 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4113 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4114 default:
4115 break;
4116 }
4117
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004118 const GLClientState::VertexAttribBindingVector& currBindings =
4119 state->currentVertexBufferBindings();
4120
4121 switch (target) {
4122 case GL_VERTEX_BINDING_DIVISOR:
4123 case GL_VERTEX_BINDING_OFFSET:
4124 case GL_VERTEX_BINDING_STRIDE:
4125 case GL_VERTEX_BINDING_BUFFER:
4126 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4127 break;
4128 default:
4129 break;
4130 }
4131
4132 switch (target) {
4133 case GL_VERTEX_BINDING_DIVISOR:
4134 *params = currBindings[index].divisor;
4135 return;
4136 case GL_VERTEX_BINDING_OFFSET:
4137 *params = currBindings[index].offset;
4138 return;
4139 case GL_VERTEX_BINDING_STRIDE:
4140 *params = currBindings[index].effectiveStride;
4141 return;
4142 case GL_VERTEX_BINDING_BUFFER:
4143 *params = currBindings[index].buffer;
4144 return;
4145 default:
4146 break;
4147 }
4148
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004149 ctx->m_glGetInteger64i_v_enc(self, target, index, params);
4150}
4151
4152void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4153 GL2Encoder *ctx = (GL2Encoder *)self;
4154 ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4155 if (pname == GL_SHADER_SOURCE_LENGTH) {
4156 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4157 if (shaderData) {
4158 int totalLen = 0;
4159 for (int i = 0; i < shaderData->sources.size(); i++) {
4160 totalLen += shaderData->sources[i].size();
4161 }
4162 if (totalLen != 0) {
4163 *params = totalLen + 1; // account for null terminator
4164 }
4165 }
4166 }
4167}
4168
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004169void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) {
4170 GL2Encoder *ctx = (GL2Encoder*)self;
4171 GLClientState* state = ctx->m_state;
4172 GLSharedGroupPtr shared = ctx->m_shared;
4173
4174 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4175 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4176 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4177
4178 ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program);
4179 if (!state->currentProgram()) {
4180 state->setCurrentShaderProgram(program);
4181 }
4182}
4183
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004184GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4185
4186 GLint* length = NULL;
4187 GL2Encoder* ctx = (GL2Encoder*)self;
4188
4189 int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
4190 char *str = new char[len + 1];
4191 glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
4192
4193 // Do GLSharedGroup and location WorkARound-specific initialization
4194 // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4195 uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4196 ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
4197 ShaderData* sData = spData->shaderData;
4198
4199 if (!replaceSamplerExternalWith2D(str, sData)) {
4200 delete [] str;
4201 ctx->setError(GL_OUT_OF_MEMORY);
4202 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4203 return -1;
4204 }
4205
4206 GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
4207 delete [] str;
4208
4209 // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4210 GLint linkStatus = 0;
4211 ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4212 if (!linkStatus) {
4213 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4214 return -1;
4215 }
4216
4217 ctx->m_shared->associateGLShaderProgram(res, spDataId);
4218
4219 GLint numUniforms = 0;
4220 ctx->glGetProgramiv(ctx, res, GL_ACTIVE_UNIFORMS, &numUniforms);
4221 ctx->m_shared->initShaderProgramData(res, numUniforms);
4222
4223 GLint maxLength=0;
4224 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4225
4226 GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4227
4228 for (GLint i = 0; i < numUniforms; ++i) {
4229 ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4230 GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4231 ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4232 }
4233
4234 ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4235
4236 delete [] name;
4237
4238 return res;
4239}
4240
4241void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4242{
4243 GL2Encoder *ctx = (GL2Encoder*)self;
4244 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4245 ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4246}
4247
4248void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4249{
4250 GL2Encoder *ctx = (GL2Encoder*)self;
4251 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4252 ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4253}
4254
4255void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4256{
4257 GL2Encoder *ctx = (GL2Encoder*)self;
4258 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004259 ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004260
4261 GLClientState* state = ctx->m_state;
4262 GLSharedGroupPtr shared = ctx->m_shared;
4263 GLenum target;
4264
4265 if (shared->setSamplerUniform(program, location, v0, &target)) {
4266 GLenum origActiveTexture = state->getActiveTextureUnit();
4267 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4268 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4269 }
4270 state->setActiveTextureUnit(origActiveTexture);
4271 }
4272}
4273
4274void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4275{
4276 GL2Encoder *ctx = (GL2Encoder*)self;
4277 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4278 ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4279}
4280
4281void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4282{
4283 GL2Encoder *ctx = (GL2Encoder*)self;
4284 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4285 ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4286
4287 GLClientState* state = ctx->m_state;
4288 GLSharedGroupPtr shared = ctx->m_shared;
4289 GLenum target;
4290
4291 if (shared->setSamplerUniform(program, location, v0, &target)) {
4292 GLenum origActiveTexture = state->getActiveTextureUnit();
4293 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4294 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4295 }
4296 state->setActiveTextureUnit(origActiveTexture);
4297 }
4298}
4299
4300void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4301{
4302 GL2Encoder *ctx = (GL2Encoder*)self;
4303 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4304 ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
4305}
4306
4307void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
4308{
4309 GL2Encoder *ctx = (GL2Encoder*)self;
4310 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4311 ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
4312}
4313
4314void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4315{
4316 GL2Encoder *ctx = (GL2Encoder*)self;
4317 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4318 ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
4319}
4320
4321void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
4322{
4323 GL2Encoder *ctx = (GL2Encoder*)self;
4324 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4325 ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
4326}
4327
4328void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4329{
4330 GL2Encoder *ctx = (GL2Encoder*)self;
4331 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4332 ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
4333}
4334
4335void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
4336{
4337 GL2Encoder *ctx = (GL2Encoder*)self;
4338 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4339 ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
4340}
4341
4342void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4343{
4344 GL2Encoder *ctx = (GL2Encoder*)self;
4345 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4346 ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
4347}
4348
4349void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
4350{
4351 GL2Encoder *ctx = (GL2Encoder*)self;
4352 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4353 ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
4354}
4355
4356void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4357{
4358 GL2Encoder *ctx = (GL2Encoder*)self;
4359 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4360 ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
4361}
4362
4363void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
4364{
4365 GL2Encoder *ctx = (GL2Encoder*)self;
4366 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4367 ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
4368}
4369
4370void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4371{
4372 GL2Encoder *ctx = (GL2Encoder*)self;
4373 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4374 ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
4375}
4376
4377void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
4378{
4379 GL2Encoder *ctx = (GL2Encoder*)self;
4380 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4381 ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
4382}
4383
4384void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4385{
4386 GL2Encoder *ctx = (GL2Encoder*)self;
4387 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4388 ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
4389}
4390
4391void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
4392{
4393 GL2Encoder *ctx = (GL2Encoder*)self;
4394 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4395 ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
4396}
4397
4398void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4399{
4400 GL2Encoder *ctx = (GL2Encoder*)self;
4401 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4402 ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
4403}
4404
4405void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
4406{
4407 GL2Encoder *ctx = (GL2Encoder*)self;
4408 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4409 ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
4410}
4411
4412void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4413{
4414 GL2Encoder *ctx = (GL2Encoder*)self;
4415 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4416 ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
4417}
4418
4419void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
4420{
4421 GL2Encoder *ctx = (GL2Encoder*)self;
4422 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4423 ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
4424}
4425
4426void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4427{
4428 GL2Encoder *ctx = (GL2Encoder*)self;
4429 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4430 ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
4431}
4432
4433void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4434{
4435 GL2Encoder *ctx = (GL2Encoder*)self;
4436 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4437 ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
4438}
4439
4440void GL2Encoder::s_glProgramUniformMatrix2x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4441{
4442 GL2Encoder *ctx = (GL2Encoder*)self;
4443 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4444 ctx->m_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
4445}
4446
4447void GL2Encoder::s_glProgramUniformMatrix2x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4448{
4449 GL2Encoder *ctx = (GL2Encoder*)self;
4450 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4451 ctx->m_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
4452}
4453
4454void GL2Encoder::s_glProgramUniformMatrix3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4455{
4456 GL2Encoder *ctx = (GL2Encoder*)self;
4457 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4458 ctx->m_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
4459}
4460
4461void GL2Encoder::s_glProgramUniformMatrix3x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4462{
4463 GL2Encoder *ctx = (GL2Encoder*)self;
4464 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4465 ctx->m_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
4466}
4467
4468void GL2Encoder::s_glProgramUniformMatrix3x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4469{
4470 GL2Encoder *ctx = (GL2Encoder*)self;
4471 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4472 ctx->m_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
4473}
4474
4475void GL2Encoder::s_glProgramUniformMatrix4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4476{
4477 GL2Encoder *ctx = (GL2Encoder*)self;
4478 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4479 ctx->m_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
4480}
4481
4482void GL2Encoder::s_glProgramUniformMatrix4x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4483{
4484 GL2Encoder *ctx = (GL2Encoder*)self;
4485 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4486 ctx->m_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
4487}
4488
4489void GL2Encoder::s_glProgramUniformMatrix4x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4490{
4491 GL2Encoder *ctx = (GL2Encoder*)self;
4492 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4493 ctx->m_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
4494}
4495
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004496void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) {
4497 GL2Encoder* ctx = (GL2Encoder*)self;
4498 ctx->m_glProgramParameteri_enc(self, program, pname, value);
4499}
4500
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004501void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
4502{
4503 GL2Encoder *ctx = (GL2Encoder*)self;
4504 GLClientState* state = ctx->m_state;
4505 GLSharedGroupPtr shared = ctx->m_shared;
4506
4507 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4508 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4509 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4510
4511 ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
4512 state->associateProgramWithPipeline(program, pipeline);
4513
4514 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4515 if (state->currentProgram()) {
4516 return;
4517 }
4518
4519 // Otherwise, update host texture 2D bindings.
4520 ctx->updateHostTexture2DBindingsFromProgramData(program);
4521}
4522
4523void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
4524{
4525 GL2Encoder *ctx = (GL2Encoder*)self;
4526 GLClientState* state = ctx->m_state;
4527
4528 ctx->m_glBindProgramPipeline_enc(self, pipeline);
4529
4530 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4531 if (!pipeline || state->currentProgram()) {
4532 return;
4533 }
4534
4535 GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
4536 for (; it != state->programPipelineEnd(); ++it) {
4537 if (it->second == pipeline) {
4538 ctx->updateHostTexture2DBindingsFromProgramData(it->first);
4539 }
4540 }
4541}
4542
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004543void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
4544 GL2Encoder *ctx = (GL2Encoder*)self;
4545 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4546 if (bufSize == 0) {
4547 if (length) *length = 0;
4548 return;
4549 }
4550
4551 // Avoid modifying |name| if |*length| < bufSize.
4552 GLint* intermediate = new GLint[bufSize];
4553 GLsizei* myLength = length ? length : new GLsizei;
4554 bool needFreeLength = length == NULL;
4555
4556 ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
4557 GLsizei writtenInts = *myLength;
4558 memcpy(params, intermediate, writtenInts * sizeof(GLint));
4559
4560 delete [] intermediate;
4561 if (needFreeLength)
4562 delete myLength;
4563}
4564
4565GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
4566 GL2Encoder *ctx = (GL2Encoder*)self;
4567 return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
4568}
4569
4570GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
4571 GL2Encoder *ctx = (GL2Encoder*)self;
4572 return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
4573}
4574
4575void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
4576 GL2Encoder *ctx = (GL2Encoder*)self;
4577 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4578 if (bufSize == 0) {
4579 if (length) *length = 0;
4580 return;
4581 }
4582
4583 // Avoid modifying |name| if |*length| < bufSize.
4584 char* intermediate = new char[bufSize];
4585 GLsizei* myLength = length ? length : new GLsizei;
4586 bool needFreeLength = length == NULL;
4587
4588 ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
4589 GLsizei writtenStrLen = *myLength;
4590 memcpy(name, intermediate, writtenStrLen + 1);
4591
4592 delete [] intermediate;
4593 if (needFreeLength)
4594 delete myLength;
4595}
4596
4597void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
4598 GL2Encoder *ctx = (GL2Encoder*)self;
4599 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4600 if (bufSize == 0) {
4601 if (length) *length = 0;
4602 return;
4603 }
4604
4605 // Avoid modifying |infoLog| if |*length| < bufSize.
4606 GLchar* intermediate = new GLchar[bufSize];
4607 GLsizei* myLength = length ? length : new GLsizei;
4608 bool needFreeLength = length == NULL;
4609
4610 ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
4611 GLsizei writtenStrLen = *myLength;
4612 memcpy(infoLog, intermediate, writtenStrLen + 1);
4613
4614 delete [] intermediate;
4615 if (needFreeLength)
4616 delete myLength;
4617}
4618
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004619void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
4620 GL2Encoder *ctx = (GL2Encoder*)self;
4621 GLClientState* state = ctx->m_state;
4622
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004623 SET_ERROR_IF(!isValidVertexAttribIndex(self, attribindex), GL_INVALID_VALUE);
4624 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4625
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004626 state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false);
4627 ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset);
4628}
4629
4630void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
4631 GL2Encoder *ctx = (GL2Encoder*)self;
4632 GLClientState* state = ctx->m_state;
4633
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004634 SET_ERROR_IF(!isValidVertexAttribIndex(self, attribindex), GL_INVALID_VALUE);
4635 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4636
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004637 state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true);
4638 ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset);
4639}
4640
4641void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004642 GL2Encoder *ctx = (GL2Encoder*)self;
4643 GLClientState* state = ctx->m_state;
4644
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004645 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4646
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004647 state->setVertexBindingDivisor(bindingindex, divisor);
4648 ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor);
4649}
4650
4651void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) {
4652 GL2Encoder *ctx = (GL2Encoder*)self;
4653 GLClientState* state = ctx->m_state;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004654 SET_ERROR_IF(!isValidVertexAttribIndex(self, attribindex), GL_INVALID_VALUE);
4655 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004656
4657 state->setVertexAttribBinding(attribindex, bindingindex);
4658 ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex);
4659}
4660
4661void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
4662 GL2Encoder *ctx = (GL2Encoder*)self;
4663 GLClientState* state = ctx->m_state;
4664
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004665 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
4666
4667 GLint maxStride;
4668 ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
4669 SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE);
4670
4671 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4672
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004673 state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride);
4674 ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride);
4675}
4676
4677void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) {
4678 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004679 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004680
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004681 bool hasClientArrays = false;
4682 ctx->getVBOUsage(&hasClientArrays, NULL);
4683
4684 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
4685 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4686 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
4687
4688 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004689 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004690 // BufferData* buf = ctx->getBufferData(target);
4691 // if (buf) {
4692 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
4693 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004694 ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect);
4695 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004696 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
4697 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004698 ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize);
4699 }
4700}
4701
4702void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) {
4703 GL2Encoder *ctx = (GL2Encoder*)self;
4704
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004705 GLClientState* state = ctx->m_state;
4706
4707 bool hasClientArrays = false;
4708 ctx->getVBOUsage(&hasClientArrays, NULL);
4709
4710 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
4711 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4712 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
4713
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004714 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004715
4716 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004717 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004718 // BufferData* buf = ctx->getBufferData(target);
4719 // if (buf) {
4720 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
4721 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004722 ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect);
4723 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004724 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
4725 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004726 ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize);
4727 }
4728
4729}
4730
4731void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
4732 GL2Encoder *ctx = (GL2Encoder*)self;
4733 GLClientState* state = ctx->m_state;
4734
4735 SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
4736 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
4737 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
4738 SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
4739 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004740 GLint max_samples;
4741 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
4742 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004743
4744 state->setBoundTextureInternalFormat(target, internalformat);
4745 state->setBoundTextureDims(target, 0, width, height, 1);
4746 state->setBoundTextureImmutableFormat(target);
4747 state->setBoundTextureSamples(target, samples);
4748
4749 ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
4750}
4751