blob: 6dec27ba2d6a258e4298c9213816c763c44dd25d [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 Yang46153ab2017-01-09 13:37:22 -0800942 if (state.isInt) {
943 this->glVertexAttribIPointerDataAEMU(this, i, state.size, state.type, stride, (unsigned char *)offset + firstIndex, datalen);
944 } else {
945 this->glVertexAttribPointerData(this, i, state.size, state.type, state.normalized, stride, (unsigned char *)offset + firstIndex, datalen);
946 }
keunyoungb85b2752013-03-08 12:28:03 -0800947 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800948 const BufferData* buf = m_shared->getBufferData(bufferObject);
Yahan Zhou5507c042016-06-01 17:24:28 -0700949 // The following expression actually means bufLen = stride*count;
950 // But the last element doesn't have to fill up the whole stride.
951 // So it becomes the current form.
Lingfeng Yang5fe99012017-01-18 09:17:09 -0800952 unsigned int bufLen = effectiveStride * (count ? (count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800953 if (divisor && primcount) {
954 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
Lingfeng Yang5fe99012017-01-18 09:17:09 -0800955 bufLen = effectiveStride * (actual_count ? (actual_count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800956 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700957 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800958 if (hasClientArrays) {
959 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800960 if (state.isInt) {
961 this->glVertexAttribIPointerOffsetAEMU(this, i, state.size, state.type, stride, offset + firstIndex);
962 } else {
963 this->glVertexAttribPointerOffset(this, i, state.size, state.type, state.normalized, stride, offset + firstIndex);
964 }
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800965 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700966 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800967 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=%p", buf);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -0800968 if (buf) {
969 ALOGE("Out of bounds vertex attribute info: "
970 "clientArray? %d attribute %d vbo %u allocedBufferSize %u bufferDataSpecified? %d wantedStart %u wantedEnd %u",
971 hasClientArrays, i, bufferObject, buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen);
972 }
973 m_glDisableVertexAttribArray_enc(this, i);
Yahan Zhou5507c042016-06-01 17:24:28 -0700974 }
keunyoungb85b2752013-03-08 12:28:03 -0800975 }
976 } else {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800977 if (hasClientArrays) {
978 this->m_glDisableVertexAttribArray_enc(this, i);
979 }
keunyoungb85b2752013-03-08 12:28:03 -0800980 }
981 }
Lingfeng Yang398162b2016-05-26 14:18:33 -0700982
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800983 if (hasClientArrays && lastBoundVbo != m_state->currentArrayVbo()) {
Lingfeng Yang398162b2016-05-26 14:18:33 -0700984 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
985 }
keunyoungb85b2752013-03-08 12:28:03 -0800986}
987
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700988void GL2Encoder::flushDrawCall() {
989 // The idea is that
990 // commitBuffer / write() to qemu pipe will
991 // take at least ~20-60us, and for cases like
992 // sendVertexAttributes / glDrawElementsOffset,
993 // which sends only around few hundred bytes,
994 // we can get away with sending
995 // two at a time in the same ~20-60us,
996 // reducing average latency and gaining ~1 fps
997 // in Antutu on Linux + Quadro K2200.
998 if (m_drawCallFlushCount % 2 == 0) {
999 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 }
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001041 // ctx->m_stream->flush();
keunyoungb85b2752013-03-08 12:28:03 -08001042}
1043
1044
1045void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
1046{
1047
1048 GL2Encoder *ctx = (GL2Encoder *)self;
1049 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001050 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1051 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -07001052 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 -08001053 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001054
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001055 bool has_client_vertex_arrays = false;
keunyoungb85b2752013-03-08 12:28:03 -08001056 bool has_indirect_arrays = false;
1057 int nLocations = ctx->m_state->nLocations();
Yahan Zhou5507c042016-06-01 17:24:28 -07001058 GLintptr offset = 0;
keunyoungb85b2752013-03-08 12:28:03 -08001059
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001060 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
keunyoungb85b2752013-03-08 12:28:03 -08001061
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001062 if (!has_client_vertex_arrays && !has_indirect_arrays) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001063 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -07001064 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
1065 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001066 }
1067
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001068 BufferData* buf = NULL;
Yahan Zhou5507c042016-06-01 17:24:28 -07001069 int minIndex = 0, maxIndex = 0;
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001070
1071 // For validation/immediate index array purposes,
1072 // we need the min/max vertex index of the index array.
1073 // If the VBO != 0, this may not be the first time we have
1074 // used this particular index buffer. getBufferIndexRange
1075 // can more quickly get min/max vertex index by
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001076 // caching previous results.
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001077 if (ctx->m_state->currentIndexVbo() != 0) {
1078 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1079 offset = (GLintptr)indices;
1080 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
1081 ctx->getBufferIndexRange(buf,
1082 indices,
1083 type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001084 (size_t)count,
1085 (size_t)offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001086 &minIndex, &maxIndex);
1087 } else {
1088 // In this case, the |indices| field holds a real
1089 // array, so calculate the indices now. They will
1090 // also be needed to know how much data to
1091 // transfer to host.
1092 ctx->calcIndexRange(indices,
1093 type,
1094 count,
1095 &minIndex,
1096 &maxIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -07001097 }
1098
keunyoungb85b2752013-03-08 12:28:03 -08001099 bool adjustIndices = true;
1100 if (ctx->m_state->currentIndexVbo() != 0) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001101 if (!has_client_vertex_arrays) {
1102 ctx->sendVertexAttributes(0, maxIndex + 1, false);
keunyoungb85b2752013-03-08 12:28:03 -08001103 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -07001104 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001105 ctx->flushDrawCall();
keunyoungb85b2752013-03-08 12:28:03 -08001106 adjustIndices = false;
1107 } else {
1108 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1109 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001110 }
1111 }
1112 if (adjustIndices) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001113 void *adjustedIndices =
1114 ctx->recenterIndices(indices,
1115 type,
1116 count,
1117 minIndex);
keunyoungb85b2752013-03-08 12:28:03 -08001118
keunyoungb85b2752013-03-08 12:28:03 -08001119 if (has_indirect_arrays || 1) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001120 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
keunyoungb85b2752013-03-08 12:28:03 -08001121 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
1122 count * glSizeof(type));
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001123 // ctx->m_stream->flush();
keunyoungb85b2752013-03-08 12:28:03 -08001124 // XXX - OPTIMIZATION (see the other else branch) should be implemented
1125 if(!has_indirect_arrays) {
1126 //ALOGD("unoptimized drawelements !!!\n");
1127 }
1128 } else {
1129 // we are all direct arrays and immidate mode index array -
1130 // rebuild the arrays and the index array;
1131 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
1132 }
1133 }
1134}
1135
1136
1137GLint * GL2Encoder::getCompressedTextureFormats()
1138{
1139 if (m_compressedTextureFormats == NULL) {
1140 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
1141 &m_num_compressedTextureFormats);
1142 if (m_num_compressedTextureFormats > 0) {
1143 // get number of texture formats;
1144 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
1145 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
1146 }
1147 }
1148 return m_compressedTextureFormats;
1149}
1150
1151// Replace uses of samplerExternalOES with sampler2D, recording the names of
1152// modified shaders in data. Also remove
1153// #extension GL_OES_EGL_image_external : require
1154// statements.
1155//
1156// This implementation assumes the input has already been pre-processed. If not,
1157// a few cases will be mishandled:
1158//
1159// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
1160// the following code:
1161// #if 1
1162// uniform sampler2D mySampler;
1163// #else
1164// uniform samplerExternalOES mySampler;
1165// #endif
1166//
1167// 2. Comments that look like sampler declarations will be incorrectly modified
1168// and recorded:
1169// // samplerExternalOES hahaFooledYou
1170//
1171// 3. However, GLSL ES does not have a concatentation operator, so things like
1172// this (valid in C) are invalid and not a problem:
1173// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
1174// SAMPLER(ExternalOES, mySampler);
1175//
1176static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
1177{
1178 static const char STR_HASH_EXTENSION[] = "#extension";
1179 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
1180 static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
1181 static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
1182
1183 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
1184 char* c = str;
1185 while ((c = strstr(c, STR_HASH_EXTENSION))) {
1186 char* start = c;
1187 c += sizeof(STR_HASH_EXTENSION)-1;
1188 while (isspace(*c) && *c != '\0') {
1189 c++;
1190 }
1191 if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
1192 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
1193 {
1194 // #extension statements are terminated by end of line
1195 c = start;
1196 while (*c != '\0' && *c != '\r' && *c != '\n') {
1197 *c++ = ' ';
1198 }
1199 }
1200 }
1201
1202 // -- replace "samplerExternalOES" with "sampler2D" and record name
1203 c = str;
1204 while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
1205 // Make sure "samplerExternalOES" isn't a substring of a larger token
1206 if (c == str || !isspace(*(c-1))) {
1207 c++;
1208 continue;
1209 }
1210 char* sampler_start = c;
1211 c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
1212 if (!isspace(*c) && *c != '\0') {
1213 continue;
1214 }
1215
1216 // capture sampler name
1217 while (isspace(*c) && *c != '\0') {
1218 c++;
1219 }
1220 if (!isalpha(*c) && *c != '_') {
1221 // not an identifier
1222 return false;
1223 }
1224 char* name_start = c;
1225 do {
1226 c++;
1227 } while (isalnum(*c) || *c == '_');
1228 data->samplerExternalNames.push_back(
1229 android::String8(name_start, c - name_start));
1230
1231 // memcpy instead of strcpy since we don't want the NUL terminator
1232 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
1233 }
1234
1235 return true;
1236}
1237
Bo Hu73568cd2015-01-20 16:29:50 -08001238void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
1239{
1240 GL2Encoder* ctx = (GL2Encoder*)self;
1241 // Although it is not supported, need to set proper error code.
1242 SET_ERROR_IF(1, GL_INVALID_ENUM);
1243}
1244
David 'Digit' Turner02fdb692014-10-30 18:07:56 +01001245void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -08001246{
1247 GL2Encoder* ctx = (GL2Encoder*)self;
1248 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001249 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(shader), GL_INVALID_VALUE);
Tina Zhang7a84f652014-12-04 12:37:30 +08001250 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
1251 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001252
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001253 // Track original sources---they may be translated in the backend
1254 std::vector<std::string> orig_sources;
1255 for (int i = 0; i < count; i++) {
1256 orig_sources.push_back(std::string((const char*)(string[i])));
1257 }
1258 shaderData->sources = orig_sources;
1259
keunyoungb85b2752013-03-08 12:28:03 -08001260 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
1261 char *str = new char[len + 1];
1262 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
1263
1264 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
1265 // Perhaps we can borrow Mesa's pre-processor?
1266
1267 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001268 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001269 ctx->setError(GL_OUT_OF_MEMORY);
1270 return;
1271 }
keunyoungb85b2752013-03-08 12:28:03 -08001272 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001273 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001274}
1275
1276void GL2Encoder::s_glFinish(void *self)
1277{
1278 GL2Encoder *ctx = (GL2Encoder *)self;
1279 ctx->glFinishRoundTrip(self);
1280}
1281
1282void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1283{
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001284 ALOGD("%s: link %u\n", __FUNCTION__, program);
keunyoungb85b2752013-03-08 12:28:03 -08001285 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -08001286 bool isProgram = ctx->m_shared->isProgram(program);
1287 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
1288 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
1289
keunyoungb85b2752013-03-08 12:28:03 -08001290 ctx->m_glLinkProgram_enc(self, program);
1291
1292 GLint linkStatus = 0;
1293 ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001294 if (!linkStatus) {
keunyoungb85b2752013-03-08 12:28:03 -08001295 return;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001296 }
keunyoungb85b2752013-03-08 12:28:03 -08001297
1298 //get number of active uniforms in the program
1299 GLint numUniforms=0;
1300 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
1301 ctx->m_shared->initProgramData(program,numUniforms);
1302
1303 //get the length of the longest uniform name
1304 GLint maxLength=0;
1305 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
1306
1307 GLint size;
1308 GLenum type;
1309 GLchar *name = new GLchar[maxLength+1];
1310 GLint location;
1311 //for each active uniform, get its size and starting location.
1312 for (GLint i=0 ; i<numUniforms ; ++i)
1313 {
1314 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1315 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1316 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1317 }
1318 ctx->m_shared->setupLocationShiftWAR(program);
1319
1320 delete[] name;
1321}
1322
1323void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1324{
1325 GL2Encoder *ctx = (GL2Encoder*)self;
1326 ctx->m_glDeleteProgram_enc(self, program);
1327
1328 ctx->m_shared->deleteProgramData(program);
1329}
1330
1331void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1332{
1333 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001334 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001335 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001336 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1337 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1338 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1339 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1340}
1341void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1342{
1343 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001344 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001345 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001346 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1347 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1348 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1349 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1350}
1351
1352GLuint GL2Encoder::s_glCreateProgram(void * self)
1353{
1354 GL2Encoder *ctx = (GL2Encoder*)self;
1355 GLuint program = ctx->m_glCreateProgram_enc(self);
1356 if (program!=0)
1357 ctx->m_shared->addProgramData(program);
1358 return program;
1359}
1360
1361GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1362{
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001363 ALOGD("%s: create shader of type 0x%x\n", __FUNCTION__, shaderType);
keunyoungb85b2752013-03-08 12:28:03 -08001364 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001365 RET_AND_SET_ERROR_IF(!GLESv2Validation::shaderType(ctx, shaderType), GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001366 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1367 if (shader != 0) {
1368 if (!ctx->m_shared->addShaderData(shader)) {
1369 ctx->m_glDeleteShader_enc(self, shader);
1370 return 0;
1371 }
1372 }
1373 return shader;
1374}
1375
bohu56bf82f2014-10-17 15:35:48 -07001376void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1377 GLsizei* count, GLuint* shaders)
1378{
1379 GL2Encoder *ctx = (GL2Encoder*)self;
1380 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1381 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1382}
1383
1384void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1385 GLsizei* length, GLchar* source)
1386{
1387 GL2Encoder *ctx = (GL2Encoder*)self;
1388 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1389 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001390 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
1391 if (shaderData) {
1392 std::string returned;
1393 int curr_len = 0;
1394 for (int i = 0; i < shaderData->sources.size(); i++) {
1395 if (curr_len + shaderData->sources[i].size() < bufsize - 1) {
1396 returned += shaderData->sources[i];
1397 } else {
1398 returned += shaderData->sources[i].substr(0, bufsize - 1 - curr_len);
1399 break;
1400 }
1401 }
1402 memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize);
1403 }
bohu56bf82f2014-10-17 15:35:48 -07001404}
1405
1406void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1407 GLsizei* length, GLchar* infolog)
1408{
1409 GL2Encoder *ctx = (GL2Encoder*)self;
1410 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1411 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1412}
1413
1414void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1415 GLsizei* length, GLchar* infolog)
1416{
1417 GL2Encoder *ctx = (GL2Encoder*)self;
1418 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1419 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1420}
1421
keunyoungb85b2752013-03-08 12:28:03 -08001422void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1423{
1424 GL2Encoder *ctx = (GL2Encoder*)self;
1425 ctx->m_glDeleteShader_enc(self,shader);
1426 ctx->m_shared->unrefShaderData(shader);
1427}
1428
1429void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1430{
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001431 ALOGD("%s: attach shader %u to %u\n", __FUNCTION__, shader, program);
keunyoungb85b2752013-03-08 12:28:03 -08001432 GL2Encoder *ctx = (GL2Encoder*)self;
1433 ctx->m_glAttachShader_enc(self, program, shader);
1434 ctx->m_shared->attachShader(program, shader);
1435}
1436
1437void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1438{
1439 GL2Encoder *ctx = (GL2Encoder*)self;
1440 ctx->m_glDetachShader_enc(self, program, shader);
1441 ctx->m_shared->detachShader(program, shader);
1442}
1443
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001444int sArrIndexOfUniformExpr(const char* name, int* err) {
1445 *err = 0;
1446 int arrIndex = 0;
1447 int namelen = strlen(name);
1448 if (name[namelen-1] == ']') {
1449 const char *brace = strrchr(name,'[');
1450 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1451 *err = 1; return 0;
1452 }
1453 }
1454 return arrIndex;
1455}
1456
keunyoungb85b2752013-03-08 12:28:03 -08001457int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1458{
1459 if (!name) return -1;
1460
1461 GL2Encoder *ctx = (GL2Encoder*)self;
1462
1463 // if we need the uniform location WAR
1464 // parse array index from the end of the name string
1465 int arrIndex = 0;
1466 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1467 if (needLocationWAR) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001468 int err;
1469 arrIndex = sArrIndexOfUniformExpr(name, &err);
1470 if (err) return -1;
keunyoungb85b2752013-03-08 12:28:03 -08001471 }
1472
1473 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1474 if (hostLoc >= 0 && needLocationWAR) {
1475 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1476 }
1477 return hostLoc;
1478}
1479
1480bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1481{
1482 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1483 return false;
1484
1485 m_state->setActiveTextureUnit(texUnit);
1486
1487 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1488 if (newTarget != oldTarget) {
1489 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1490 m_state->disableTextureTarget(GL_TEXTURE_2D);
1491 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1492 } else {
1493 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1494 m_state->enableTextureTarget(GL_TEXTURE_2D);
1495 }
1496 m_glActiveTexture_enc(this, texUnit);
1497 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1498 m_state->getBoundTexture(newTarget));
1499 return true;
1500 }
1501
1502 return false;
1503}
1504
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001505void GL2Encoder::updateHostTexture2DBindingsFromProgramData(GLuint program) {
1506 GL2Encoder *ctx = this;
keunyoungb85b2752013-03-08 12:28:03 -08001507 GLClientState* state = ctx->m_state;
1508 GLSharedGroupPtr shared = ctx->m_shared;
1509
keunyoungb85b2752013-03-08 12:28:03 -08001510 GLenum origActiveTexture = state->getActiveTextureUnit();
1511 GLenum hostActiveTexture = origActiveTexture;
1512 GLint samplerIdx = -1;
1513 GLint samplerVal;
1514 GLenum samplerTarget;
1515 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1516 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1517 continue;
1518 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001519 samplerTarget))
keunyoungb85b2752013-03-08 12:28:03 -08001520 {
1521 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1522 }
1523 }
1524 state->setActiveTextureUnit(origActiveTexture);
1525 if (hostActiveTexture != origActiveTexture) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001526 ctx->m_glActiveTexture_enc(ctx, origActiveTexture);
keunyoungb85b2752013-03-08 12:28:03 -08001527 }
1528}
1529
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001530void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1531{
1532 GL2Encoder *ctx = (GL2Encoder*)self;
1533 GLSharedGroupPtr shared = ctx->m_shared;
1534
1535 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
1536 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1537
1538 ctx->m_glUseProgram_enc(self, program);
1539 ctx->m_state->setCurrentProgram(program);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001540 ctx->m_state->setCurrentShaderProgram(program);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001541
1542 ctx->updateHostTexture2DBindingsFromProgramData(program);
1543}
1544
keunyoungb85b2752013-03-08 12:28:03 -08001545void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1546{
1547 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001548 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001549 ctx->m_glUniform1f_enc(self, hostLoc, x);
1550}
1551
1552void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1553{
1554 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001555 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001556 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1557}
1558
1559void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1560{
1561 GL2Encoder *ctx = (GL2Encoder*)self;
1562 GLClientState* state = ctx->m_state;
1563 GLSharedGroupPtr shared = ctx->m_shared;
1564
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001565 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001566 ctx->m_glUniform1i_enc(self, hostLoc, x);
1567
1568 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001569 if (shared->setSamplerUniform(state->currentShaderProgram(), location, x, &target)) {
keunyoungb85b2752013-03-08 12:28:03 -08001570 GLenum origActiveTexture = state->getActiveTextureUnit();
1571 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1572 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1573 }
1574 state->setActiveTextureUnit(origActiveTexture);
1575 }
1576}
1577
1578void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1579{
1580 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001581 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001582 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1583}
1584
1585void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1586{
1587 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001588 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001589 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1590}
1591
1592void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1593{
1594 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001595 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001596 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1597}
1598
1599void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1600{
1601 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001602 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001603 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1604}
1605
1606void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1607{
1608 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001609 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001610 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1611}
1612
1613void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1614{
1615 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001616 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001617 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1618}
1619
1620void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1621{
1622 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001623 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001624 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1625}
1626
1627void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1628{
1629 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001630 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001631 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1632}
1633
1634void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1635{
1636 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001637 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001638 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1639}
1640
1641void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1642{
1643 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001644 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001645 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1646}
1647
1648void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1649{
1650 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001651 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001652 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1653}
1654
1655void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1656{
1657 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001658 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001659 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1660}
1661
1662void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1663{
1664 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001665 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001666 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1667}
1668
1669void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1670{
1671 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001672 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001673 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1674}
1675
1676void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1677{
1678 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001679 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001680 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1681}
1682
1683void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1684{
1685 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001686 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001687 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1688}
1689
1690void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1691{
1692 GL2Encoder* ctx = (GL2Encoder*)self;
1693 GLClientState* state = ctx->m_state;
1694 GLenum err;
1695
1696 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1697
1698 ctx->m_glActiveTexture_enc(ctx, texture);
1699}
1700
1701void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1702{
1703 GL2Encoder* ctx = (GL2Encoder*)self;
1704 GLClientState* state = ctx->m_state;
1705 GLenum err;
1706 GLboolean firstUse;
1707
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001708 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -08001709 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1710
1711 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1712 ctx->m_glBindTexture_enc(ctx, target, texture);
1713 return;
1714 }
1715
1716 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1717
1718 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1719 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1720 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1721 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1722 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1723 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1724 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1725 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1726
1727 if (target != priorityTarget) {
1728 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1729 state->getBoundTexture(GL_TEXTURE_2D));
1730 }
1731 }
1732
1733 if (target == priorityTarget) {
1734 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1735 }
1736}
1737
1738void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1739{
1740 GL2Encoder* ctx = (GL2Encoder*)self;
1741 GLClientState* state = ctx->m_state;
1742
1743 state->deleteTextures(n, textures);
1744 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1745}
1746
1747void GL2Encoder::s_glGetTexParameterfv(void* self,
1748 GLenum target, GLenum pname, GLfloat* params)
1749{
1750 GL2Encoder* ctx = (GL2Encoder*)self;
1751 const GLClientState* state = ctx->m_state;
1752
1753 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1754 ctx->override2DTextureTarget(target);
1755 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001756 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001757 } else {
1758 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1759 }
1760}
1761
1762void GL2Encoder::s_glGetTexParameteriv(void* self,
1763 GLenum target, GLenum pname, GLint* params)
1764{
1765 GL2Encoder* ctx = (GL2Encoder*)self;
1766 const GLClientState* state = ctx->m_state;
1767
1768 switch (pname) {
1769 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1770 *params = 1;
1771 break;
1772
1773 default:
1774 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1775 ctx->override2DTextureTarget(target);
1776 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001777 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001778 } else {
1779 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1780 }
1781 break;
1782 }
1783}
1784
1785static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1786{
1787 switch (pname) {
1788 case GL_TEXTURE_MIN_FILTER:
1789 case GL_TEXTURE_MAG_FILTER:
1790 return param == GL_NEAREST || param == GL_LINEAR;
1791
1792 case GL_TEXTURE_WRAP_S:
1793 case GL_TEXTURE_WRAP_T:
1794 return param == GL_CLAMP_TO_EDGE;
1795
1796 default:
1797 return true;
1798 }
1799}
1800
1801void GL2Encoder::s_glTexParameterf(void* self,
1802 GLenum target, GLenum pname, GLfloat param)
1803{
1804 GL2Encoder* ctx = (GL2Encoder*)self;
1805 const GLClientState* state = ctx->m_state;
1806
1807 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1808 !isValidTextureExternalParam(pname, (GLenum)param)),
1809 GL_INVALID_ENUM);
1810
1811 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1812 ctx->override2DTextureTarget(target);
1813 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001814 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001815 } else {
1816 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1817 }
1818}
1819
1820void GL2Encoder::s_glTexParameterfv(void* self,
1821 GLenum target, GLenum pname, const GLfloat* params)
1822{
1823 GL2Encoder* ctx = (GL2Encoder*)self;
1824 const GLClientState* state = ctx->m_state;
1825
1826 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1827 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1828 GL_INVALID_ENUM);
1829
1830 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1831 ctx->override2DTextureTarget(target);
1832 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001833 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001834 } else {
1835 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1836 }
1837}
1838
1839void GL2Encoder::s_glTexParameteri(void* self,
1840 GLenum target, GLenum pname, GLint param)
1841{
1842 GL2Encoder* ctx = (GL2Encoder*)self;
1843 const GLClientState* state = ctx->m_state;
1844
1845 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1846 !isValidTextureExternalParam(pname, (GLenum)param)),
1847 GL_INVALID_ENUM);
1848
1849 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1850 ctx->override2DTextureTarget(target);
1851 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001852 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001853 } else {
1854 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
1855 }
1856}
1857
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001858static int ilog2(uint32_t x) {
1859 int p = 0;
1860 while ((1 << p) < x)
1861 p++;
1862 return p;
1863}
1864
bohu26a92982014-11-25 16:50:37 -08001865void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
1866 GLint internalformat, GLsizei width, GLsizei height, GLint border,
1867 GLenum format, GLenum type, const GLvoid* pixels)
1868{
1869 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07001870 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001871
1872 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
1873 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
1874 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
1875 // If unpack buffer is nonzero, verify unmapped state.
1876 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
1877
1878 GLint max_texture_size;
1879 GLint max_cube_map_texture_size;
1880 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
1881 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
1882 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
1883 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
1884 SET_ERROR_IF((target == GL_TEXTURE_CUBE_MAP) &&
1885 (level > ilog2(max_cube_map_texture_size)), GL_INVALID_VALUE);
1886 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
1887 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
1888 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
1889 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && width > max_cube_map_texture_size, GL_INVALID_VALUE);
1890 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && height > max_cube_map_texture_size, GL_INVALID_VALUE);
1891 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
1892 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
1893 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1894 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1895 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 0) >
1896 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
1897 GL_INVALID_OPERATION);
1898 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1899 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1900 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
1901 glSizeof(type)),
1902 GL_INVALID_OPERATION);
1903 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1904 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1905 ((uintptr_t)pixels % glSizeof(type)),
1906 GL_INVALID_OPERATION);
1907 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
1908
1909 GLenum stateTarget = target;
1910 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1911 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1912 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
1913 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1914 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1915 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
1916 stateTarget = GL_TEXTURE_CUBE_MAP;
1917
1918 state->setBoundTextureInternalFormat(stateTarget, internalformat);
1919 state->setBoundTextureFormat(stateTarget, format);
1920 state->setBoundTextureType(stateTarget, type);
1921 state->setBoundTextureDims(stateTarget, level, width, height, 1);
1922
bohu26a92982014-11-25 16:50:37 -08001923 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1924 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001925 }
Lingfeng Yang69066602016-04-12 09:29:11 -07001926
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001927 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
1928 ctx->glTexImage2DOffsetAEMU(
1929 ctx, target, level, internalformat,
1930 width, height, border,
1931 format, type, (uintptr_t)pixels);
bohu26a92982014-11-25 16:50:37 -08001932 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001933 ctx->m_glTexImage2D_enc(
1934 ctx, target, level, internalformat,
1935 width, height, border,
1936 format, type, pixels);
1937 }
1938
1939 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1940 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08001941 }
1942}
1943
Yahan Zhou2a208292016-06-22 15:36:04 -07001944void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
1945 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
1946 GLenum type, const GLvoid* pixels)
1947{
1948 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001949 GLClientState* state = ctx->m_state;
1950
1951 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
1952 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
1953 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
1954 // If unpack buffer is nonzero, verify unmapped state.
1955 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
1956
1957 GLint max_texture_size;
1958 GLint max_cube_map_texture_size;
1959 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
1960 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
1961 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
1962 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
1963 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) &&
1964 level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
1965 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
1966 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
1967
1968 GLuint tex = state->getBoundTexture(target);
1969 GLsizei neededWidth = xoffset + width;
1970 GLsizei neededHeight = yoffset + height;
1971 GLsizei neededDepth = 1;
1972
1973 if (tex && !state->queryTexEGLImageBacked(tex)) {
1974 SET_ERROR_IF(
1975 (neededWidth > state->queryTexWidth(level, tex) ||
1976 neededHeight > state->queryTexHeight(level, tex) ||
1977 neededDepth > state->queryTexDepth(level, tex)),
1978 GL_INVALID_VALUE);
1979 }
1980
1981 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
1982 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1983 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1984 (state->pboNeededDataSize(width, height, 1, format, type, 0) >
1985 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
1986 GL_INVALID_OPERATION);
1987 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
1988 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
1989 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
1990 glSizeof(type)),
1991 GL_INVALID_OPERATION);
1992 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !pixels, GL_INVALID_OPERATION);
Yahan Zhou2a208292016-06-22 15:36:04 -07001993
1994 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1995 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001996 }
1997
1998 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
1999 ctx->glTexSubImage2DOffsetAEMU(
2000 ctx, target, level,
2001 xoffset, yoffset, width, height,
2002 format, type, (uintptr_t)pixels);
Yahan Zhou2a208292016-06-22 15:36:04 -07002003 } else {
2004 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
2005 height, format, type, pixels);
2006 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002007
2008 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2009 ctx->restore2DTextureTarget(target);
2010 }
Yahan Zhou2a208292016-06-22 15:36:04 -07002011}
bohu26a92982014-11-25 16:50:37 -08002012
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002013void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
2014 GLenum internalformat, GLint x, GLint y,
2015 GLsizei width, GLsizei height, GLint border)
2016{
2017 GL2Encoder* ctx = (GL2Encoder*)self;
2018 GLClientState* state = ctx->m_state;
2019
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002020 SET_ERROR_IF(ctx->glCheckFramebufferStatus(ctx, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
2021 GL_INVALID_FRAMEBUFFER_OPERATION);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002022 // This is needed to work around underlying OpenGL drivers
2023 // (such as those feeding some some AMD GPUs) that expect
2024 // positive components of cube maps to be defined _before_
2025 // the negative components (otherwise a segfault occurs).
2026 GLenum extraTarget =
2027 state->copyTexImageLuminanceCubeMapAMDWorkaround
2028 (target, level, internalformat);
2029
2030 if (extraTarget) {
2031 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
2032 x, y, width, height, border);
2033 }
2034
2035 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
2036 x, y, width, height, border);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002037
2038 state->setBoundTextureInternalFormat(target, internalformat);
2039 state->setBoundTextureDims(target, level, width, height, 1);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002040}
2041
keunyoungb85b2752013-03-08 12:28:03 -08002042void GL2Encoder::s_glTexParameteriv(void* self,
2043 GLenum target, GLenum pname, const GLint* params)
2044{
2045 GL2Encoder* ctx = (GL2Encoder*)self;
2046 const GLClientState* state = ctx->m_state;
2047
2048 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2049 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2050 GL_INVALID_ENUM);
2051
2052 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2053 ctx->override2DTextureTarget(target);
2054 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002055 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002056 } else {
2057 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
2058 }
2059}
2060
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002061bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
2062 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
2063 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2064}
2065
keunyoungb85b2752013-03-08 12:28:03 -08002066void GL2Encoder::override2DTextureTarget(GLenum target)
2067{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002068 if (texture2DNeedsOverride(target)) {
2069 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2070 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08002071 }
2072}
2073
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002074void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08002075{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002076 if (texture2DNeedsOverride(target)) {
2077 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2078 m_state->getBoundTexture(
2079 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)));
2080 }
keunyoungb85b2752013-03-08 12:28:03 -08002081}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002082
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002083void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2084 m_state->setBoundEGLImage(target, eglImage);
2085}
2086
2087
2088GLuint GL2Encoder::boundBuffer(GLenum target) const {
2089 return m_state->getBuffer(target);
2090}
2091
2092BufferData* GL2Encoder::getBufferData(GLenum target) const {
2093 GLuint bufferId = m_state->getBuffer(target);
2094 if (!bufferId) return NULL;
2095 return m_shared->getBufferData(bufferId);
2096}
2097
2098BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2099 if (!bufferId) return NULL;
2100 return m_shared->getBufferData(bufferId);
2101}
2102
2103bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2104 return m_shared->getBufferData(buffer)->m_mapped;
2105}
2106
2107bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2108 BufferData* buf = getBufferData(target);
2109 if (!buf) return false;
2110 return buf->m_mapped;
2111}
2112
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002113void GL2Encoder::s_glGenRenderbuffers(void* self,
2114 GLsizei n, GLuint* renderbuffers) {
2115 GL2Encoder* ctx = (GL2Encoder*)self;
2116 GLClientState* state = ctx->m_state;
2117
2118 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2119
2120 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2121 state->addRenderbuffers(n, renderbuffers);
2122}
2123
2124void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2125 GLsizei n, const GLuint* renderbuffers) {
2126 GL2Encoder* ctx = (GL2Encoder*)self;
2127 GLClientState* state = ctx->m_state;
2128
2129 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2130
2131 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002132
2133 // Nope, lets just leak those for now.
2134 // The spec has an *amazingly* convoluted set of conditions for when
2135 // render buffers are actually deleted:
2136 // 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.
2137 //
2138 // 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***
2139 //
2140 // So, just detach this one from the bound FBO, and ignore the rest.
2141 for (int i = 0; i < n; i++) {
2142 state->detachRbo(renderbuffers[i]);
2143 }
2144 // state->removeRenderbuffers(n, renderbuffers);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002145}
2146
2147void GL2Encoder::s_glBindRenderbuffer(void* self,
2148 GLenum target, GLuint renderbuffer) {
2149 GL2Encoder* ctx = (GL2Encoder*)self;
2150 GLClientState* state = ctx->m_state;
2151
2152 SET_ERROR_IF((target != GL_RENDERBUFFER),
2153 GL_INVALID_ENUM);
2154
2155 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2156 state->bindRenderbuffer(target, renderbuffer);
2157}
2158
Lingfeng Yang69066602016-04-12 09:29:11 -07002159void GL2Encoder::s_glRenderbufferStorage(void* self,
2160 GLenum target, GLenum internalformat,
2161 GLsizei width, GLsizei height) {
2162 GL2Encoder* ctx = (GL2Encoder*) self;
2163 GLClientState* state = ctx->m_state;
2164
2165 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002166 SET_ERROR_IF(
2167 !GLESv2Validation::rboFormat(ctx, internalformat),
2168 GL_INVALID_ENUM);
Lingfeng Yang69066602016-04-12 09:29:11 -07002169
2170 state->setBoundRenderbufferFormat(internalformat);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002171 state->setBoundRenderbufferSamples(0);
2172
Lingfeng Yang69066602016-04-12 09:29:11 -07002173 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
2174 width, height);
2175}
2176
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002177void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
2178 GLenum target, GLenum attachment,
2179 GLenum renderbuffertarget, GLuint renderbuffer) {
2180 GL2Encoder* ctx = (GL2Encoder*)self;
2181 GLClientState* state = ctx->m_state;
2182
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002183 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2184 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2185 state->attachRbo(target, attachment, renderbuffer);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002186
2187 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
2188}
2189
2190void GL2Encoder::s_glGenFramebuffers(void* self,
2191 GLsizei n, GLuint* framebuffers) {
2192 GL2Encoder* ctx = (GL2Encoder*)self;
2193 GLClientState* state = ctx->m_state;
2194
2195 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2196
2197 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2198 state->addFramebuffers(n, framebuffers);
2199}
2200
2201void GL2Encoder::s_glDeleteFramebuffers(void* self,
2202 GLsizei n, const GLuint* framebuffers) {
2203 GL2Encoder* ctx = (GL2Encoder*)self;
2204 GLClientState* state = ctx->m_state;
2205
2206 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2207
2208 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2209 state->removeFramebuffers(n, framebuffers);
2210}
2211
2212void GL2Encoder::s_glBindFramebuffer(void* self,
2213 GLenum target, GLuint framebuffer) {
2214 GL2Encoder* ctx = (GL2Encoder*)self;
2215 GLClientState* state = ctx->m_state;
2216
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002217 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002218
2219 state->bindFramebuffer(target, framebuffer);
2220
2221 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
2222}
2223
2224void GL2Encoder::s_glFramebufferTexture2D(void* self,
2225 GLenum target, GLenum attachment,
2226 GLenum textarget, GLuint texture, GLint level) {
2227 GL2Encoder* ctx = (GL2Encoder*)self;
2228 GLClientState* state = ctx->m_state;
2229
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002230 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2231 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2232 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002233
2234 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
2235}
2236
2237void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2238 GLenum target, GLenum attachment,
2239 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2240 GL2Encoder* ctx = (GL2Encoder*)self;
2241 GLClientState* state = ctx->m_state;
2242
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002243 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002244
2245 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2246}
2247
2248void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2249 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2250 GL2Encoder* ctx = (GL2Encoder*)self;
2251 const GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002252 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2253 SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2254 pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE &&
2255 !state->attachmentHasObject(target, attachment),
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002256 GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002257 SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL ||
2258 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE ||
2259 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) &&
2260 (!state->attachmentHasObject(target, attachment) ||
2261 state->getBoundFramebufferAttachmentType(target, attachment) !=
2262 FBO_ATTACHMENT_TEXTURE),
2263 !state->attachmentHasObject(target, attachment) ?
2264 GL_INVALID_OPERATION : GL_INVALID_ENUM);
2265 SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2266 pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2267 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
2268 state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
2269 GL_INVALID_OPERATION);
2270 SET_ERROR_IF(state->boundFramebuffer(target) &&
2271 (attachment == GL_BACK ||
2272 attachment == GL_FRONT),
2273 GL_INVALID_OPERATION);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002274 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
2275}
Lingfeng Yang69066602016-04-12 09:29:11 -07002276
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002277bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state,
Lingfeng Yang69066602016-04-12 09:29:11 -07002278 GLenum attachment) const {
2279 FboFormatInfo fbo_format_info;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002280 state->getBoundFramebufferFormat(target, attachment, &fbo_format_info);
Lingfeng Yang69066602016-04-12 09:29:11 -07002281
2282 bool res;
2283 switch (fbo_format_info.type) {
2284 case FBO_ATTACHMENT_RENDERBUFFER:
2285 switch (fbo_format_info.rb_format) {
2286 case GL_R16F:
2287 case GL_RG16F:
2288 case GL_RGB16F:
2289 case GL_RGBA16F:
2290 res = false;
2291 break;
2292 case GL_STENCIL_INDEX8:
2293 if (attachment == GL_STENCIL_ATTACHMENT) {
2294 res = true;
2295 } else {
2296 res = false;
2297 }
2298 break;
2299 default:
2300 res = true;
2301 }
2302 break;
2303 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002304 switch (fbo_format_info.tex_internalformat) {
2305 case GL_RED:
2306 case GL_RG:
2307 case GL_R16F:
2308 case GL_RG16F:
2309 case GL_RGBA16F:
2310 case GL_RGB16F:
2311 case GL_R11F_G11F_B10F:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002312 case GL_R32F:
2313 case GL_RG32F:
2314 case GL_RGBA32F:
2315 case GL_SRGB8:
2316 case GL_RGB32UI:
2317 case GL_RGB16UI:
2318 case GL_RGB8UI:
2319 case GL_RGB32I:
2320 case GL_RGB16I:
2321 case GL_RGB8I:
2322 case GL_R8_SNORM:
2323 case GL_RG8_SNORM:
2324 case GL_RGB8_SNORM:
2325 case GL_RGBA8_SNORM:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002326 res = false;
2327 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07002328 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002329 case GL_RGB:
2330 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07002331 switch (fbo_format_info.tex_type) {
2332 case GL_FLOAT:
2333 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002334 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002335 case GL_UNSIGNED_INT_2_10_10_10_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07002336 res = false;
2337 break;
2338 default:
2339 res = true;
2340 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002341 break;
2342 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07002343 res = true;
2344 }
2345 break;
2346 case FBO_ATTACHMENT_NONE:
2347 res = true;
2348 break;
2349 default:
2350 res = true;
2351 }
2352 return res;
2353}
2354
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002355bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const {
2356 bool res = true;
2357
2358 for (int i = 0; i < state->getMaxColorAttachments(); i++) {
2359 res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i));
2360 }
2361
2362 res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT);
2363 res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT);
2364
2365 return res;
2366}
2367
Lingfeng Yang69066602016-04-12 09:29:11 -07002368GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
2369 GL2Encoder* ctx = (GL2Encoder*)self;
2370 GLClientState* state = ctx->m_state;
2371
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002372 bool fboCompleteByCodec =
2373 ctx->checkFramebufferCompleteness(target, state);
2374
2375 if (!fboCompleteByCodec) {
2376 state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
Lingfeng Yang69066602016-04-12 09:29:11 -07002377 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2378 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002379 // double check with underlying opengl to avoid craziness.
Lingfeng Yang69066602016-04-12 09:29:11 -07002380 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002381 state->setCheckFramebufferStatus(target, host_checkstatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002382 if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE;
Lingfeng Yang69066602016-04-12 09:29:11 -07002383 return host_checkstatus;
2384 }
2385}
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002386
2387void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2388 GL2Encoder* ctx = (GL2Encoder*)self;
2389 GLClientState* state = ctx->m_state;
2390 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2391
2392 ctx->m_glGenVertexArrays_enc(self, n, arrays);
2393 for (int i = 0; i < n; i++) {
2394 ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2395 }
2396 state->addVertexArrayObjects(n, arrays);
2397}
2398
2399void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2400 GL2Encoder* ctx = (GL2Encoder*)self;
2401 GLClientState* state = ctx->m_state;
2402 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2403
2404 ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2405 for (int i = 0; i < n; i++) {
2406 ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2407 }
2408 state->removeVertexArrayObjects(n, arrays);
2409}
2410
2411void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2412 ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2413 GL2Encoder* ctx = (GL2Encoder*)self;
2414 GLClientState* state = ctx->m_state;
2415 SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2416 ctx->m_glBindVertexArray_enc(self, array);
2417 state->setVertexArrayObject(array);
2418}
2419
2420void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2421 GL2Encoder* ctx = (GL2Encoder*)self;
2422 GLClientState* state = ctx->m_state;
2423
2424 // begin validation (lots)
2425
2426 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2427
2428 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2429
2430 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2431
2432 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2433 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2434
2435 GLsizeiptr bufferDataSize = buf->m_size;
2436
2437 RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2438 RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2439 RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2440 RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2441
2442 RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2443 RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2444 RET_AND_SET_ERROR_IF(
2445 (access & GL_MAP_READ_BIT) &&
2446 ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2447 (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2448 (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2449 (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2450
2451 // end validation; actually do stuff now
2452
2453 buf->m_mapped = true;
2454 buf->m_mappedAccess = access;
2455 buf->m_mappedOffset = offset;
2456 buf->m_mappedLength = length;
2457
2458 char* todo = (char*)buf->m_fixedBuffer.ptr() + offset;
2459 ctx->glMapBufferRangeAEMU(
2460 ctx, target,
2461 offset, length,
2462 access,
2463 todo);
2464
2465 return todo;
2466}
2467
2468GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
2469 GL2Encoder* ctx = (GL2Encoder*)self;
2470 GLClientState* state = ctx->m_state;
2471
2472 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
2473
2474 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2475
2476 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
2477
2478 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2479 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
2480 RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
2481
Lingfeng Yang423129e2017-01-18 09:23:12 -08002482 if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
2483 // invalide index range cache here
2484 if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) {
2485 buf->m_indexRangeCache.invalidateRange(0, buf->m_size);
2486 } else {
2487 buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength);
2488 }
2489 }
2490
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002491 GLboolean host_res = GL_TRUE;
2492
2493 ctx->glUnmapBufferAEMU(
2494 ctx, target,
2495 buf->m_mappedOffset,
2496 buf->m_mappedLength,
2497 buf->m_mappedAccess,
2498 (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
2499 &host_res);
2500
2501 buf->m_mapped = false;
2502 buf->m_mappedAccess = 0;
2503 buf->m_mappedOffset = 0;
2504 buf->m_mappedLength = 0;
2505
2506 return host_res;
2507}
2508
2509void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
2510 GL2Encoder* ctx = (GL2Encoder*)self;
2511 GLClientState* state = ctx->m_state;
2512
2513 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2514
2515 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2516 SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
2517
2518 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2519 SET_ERROR_IF(!buf, GL_INVALID_VALUE);
2520 SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
2521 SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
2522
2523 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
2524 SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
2525 SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
2526
2527 GLintptr totalOffset = buf->m_mappedOffset + offset;
Lingfeng Yang423129e2017-01-18 09:23:12 -08002528
2529 buf->m_indexRangeCache.invalidateRange(totalOffset, length);
2530
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002531 ctx->glFlushMappedBufferRangeAEMU(
2532 ctx, target,
2533 totalOffset,
2534 length,
2535 buf->m_mappedAccess,
2536 (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
2537}
2538
2539void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
2540 GL2Encoder* ctx = (GL2Encoder*)self;
2541 GLClientState* state = ctx->m_state;
2542
2543 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2544 // Filter compressed formats support.
2545 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
2546 // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
2547 GLint max_texture_size;
2548 GLint max_cube_map_texture_size;
2549 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2550 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2551 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2552 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2553 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2554 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2555 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2556 SET_ERROR_IF(border, GL_INVALID_VALUE);
2557 // If unpack buffer is nonzero, verify unmapped state.
2558 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2559 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2560 // If unpack buffer is nonzero, verify buffer data fits.
2561 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2562 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2563 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2564 GL_INVALID_OPERATION);
2565 // TODO: Fix:
2566 // If |imageSize| is inconsistent with compressed dimensions.
2567 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
2568
2569 GLenum stateTarget = target;
2570 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2571 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2572 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2573 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2574 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2575 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2576 stateTarget = GL_TEXTURE_CUBE_MAP;
2577 state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
2578 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2579
2580 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2581 ctx->glCompressedTexImage2DOffsetAEMU(
2582 ctx, target, level, internalformat,
2583 width, height, border,
2584 imageSize, (uintptr_t)data);
2585 } else {
2586 ctx->m_glCompressedTexImage2D_enc(
2587 ctx, target, level, internalformat,
2588 width, height, border,
2589 imageSize, data);
2590 }
2591}
2592
2593void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
2594 GL2Encoder* ctx = (GL2Encoder*)self;
2595 GLClientState* state = ctx->m_state;
2596
2597 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2598 // If unpack buffer is nonzero, verify unmapped state.
2599 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2600 GLint max_texture_size;
2601 GLint max_cube_map_texture_size;
2602 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2603 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2604 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2605 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2606 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2607 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2608 // If unpack buffer is nonzero, verify buffer data fits.
2609 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2610 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2611 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2612 GL_INVALID_OPERATION);
2613 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2614
2615 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2616 ctx->glCompressedTexSubImage2DOffsetAEMU(
2617 ctx, target, level,
2618 xoffset, yoffset,
2619 width, height, format,
2620 imageSize, (uintptr_t)data);
2621 } else {
2622 ctx->m_glCompressedTexSubImage2D_enc(
2623 ctx, target, level,
2624 xoffset, yoffset,
2625 width, height, format,
2626 imageSize, data);
2627 }
2628}
2629
2630void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
2631 GL2Encoder* ctx = (GL2Encoder*)self;
2632 GLClientState* state = ctx->m_state;
2633
2634 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2635
2636 // Only works with certain targets
2637 SET_ERROR_IF(
2638 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2639 target == GL_SHADER_STORAGE_BUFFER ||
2640 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2641 target == GL_UNIFORM_BUFFER),
2642 GL_INVALID_ENUM);
2643
2644 // Can't exceed range
2645 SET_ERROR_IF(index < 0 ||
2646 index >= state->getMaxIndexedBufferBindings(target),
2647 GL_INVALID_VALUE);
2648 SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
2649 SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
2650 target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
2651 (size % 4 || offset % 4),
2652 GL_INVALID_VALUE);
2653
2654 GLint ssbo_offset_align, ubo_offset_align;
2655 ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
2656 ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
2657 SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
2658 offset % ssbo_offset_align,
2659 GL_INVALID_VALUE);
2660 SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
2661 offset % ubo_offset_align,
2662 GL_INVALID_VALUE);
2663
2664 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002665 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002666 state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0);
2667 ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size);
2668}
2669
2670void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
2671 GL2Encoder* ctx = (GL2Encoder*)self;
2672 GLClientState* state = ctx->m_state;
2673
2674 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2675
2676 // Only works with certain targets
2677 SET_ERROR_IF(
2678 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2679 target == GL_SHADER_STORAGE_BUFFER ||
2680 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2681 target == GL_UNIFORM_BUFFER),
2682 GL_INVALID_ENUM);
2683 // Can't exceed range
2684 SET_ERROR_IF(index < 0 ||
2685 index >= state->getMaxIndexedBufferBindings(target),
2686 GL_INVALID_VALUE);
2687
2688 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002689 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002690 BufferData* buf = ctx->getBufferDataById(buffer);
2691 state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0);
2692 ctx->m_glBindBufferBase_enc(self, target, index, buffer);
2693}
2694
2695void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
2696 GL2Encoder* ctx = (GL2Encoder*)self;
2697 GLClientState* state = ctx->m_state;
2698
2699 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
2700 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
2701 SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
2702 readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
2703 readtarget == GL_DRAW_INDIRECT_BUFFER ||
2704 readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2705 SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
2706 writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
2707 writetarget == GL_DRAW_INDIRECT_BUFFER ||
2708 writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2709 SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
2710 SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
2711 SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
2712 SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
2713 SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
2714 SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
2715 SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
2716 SET_ERROR_IF(
2717 ctx->getBufferData(readtarget) &&
2718 (readoffset + size > ctx->getBufferData(readtarget)->m_size),
2719 GL_INVALID_VALUE);
2720 SET_ERROR_IF(
2721 ctx->getBufferData(writetarget) &&
2722 (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
2723 GL_INVALID_VALUE);
2724 SET_ERROR_IF(readtarget == writetarget &&
2725 !((writeoffset >= readoffset + size) ||
2726 (readoffset >= writeoffset + size)),
2727 GL_INVALID_VALUE);
2728
2729 ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
2730}
2731
2732void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
2733 GL2Encoder* ctx = (GL2Encoder*)self;
2734
2735 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2736 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002737 target != GL_ARRAY_BUFFER &&
2738 target != GL_ELEMENT_ARRAY_BUFFER &&
2739 target != GL_COPY_READ_BUFFER &&
2740 target != GL_COPY_WRITE_BUFFER &&
2741 target != GL_PIXEL_PACK_BUFFER &&
2742 target != GL_PIXEL_UNPACK_BUFFER &&
2743 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
2744 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002745 GL_INVALID_ENUM);
2746 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
2747 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002748 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
2749 pname != GL_BUFFER_MAPPED &&
2750 pname != GL_BUFFER_SIZE &&
2751 pname != GL_BUFFER_USAGE &&
2752 pname != GL_BUFFER_MAP_LENGTH &&
2753 pname != GL_BUFFER_MAP_OFFSET,
2754 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002755
2756 if (!params) return;
2757
2758 BufferData* buf = ctx->getBufferData(target);
2759
2760 switch (pname) {
2761 case GL_BUFFER_ACCESS_FLAGS:
2762 *params = buf ? buf->m_mappedAccess : 0;
2763 break;
2764 case GL_BUFFER_MAPPED:
2765 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
2766 break;
2767 case GL_BUFFER_SIZE:
2768 *params = buf ? buf->m_size : 0;
2769 break;
2770 case GL_BUFFER_USAGE:
2771 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
2772 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002773 case GL_BUFFER_MAP_LENGTH:
2774 *params = buf ? buf->m_mappedLength : 0;
2775 break;
2776 case GL_BUFFER_MAP_OFFSET:
2777 *params = buf ? buf->m_mappedOffset : 0;
2778 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002779 default:
2780 break;
2781 }
2782}
2783
2784void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
2785 GL2Encoder* ctx = (GL2Encoder*)self;
2786
2787 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2788 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002789 target != GL_ARRAY_BUFFER &&
2790 target != GL_ELEMENT_ARRAY_BUFFER &&
2791 target != GL_COPY_READ_BUFFER &&
2792 target != GL_COPY_WRITE_BUFFER &&
2793 target != GL_PIXEL_PACK_BUFFER &&
2794 target != GL_PIXEL_UNPACK_BUFFER &&
2795 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
2796 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002797 GL_INVALID_ENUM);
2798 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
2799 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002800 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
2801 pname != GL_BUFFER_MAPPED &&
2802 pname != GL_BUFFER_SIZE &&
2803 pname != GL_BUFFER_USAGE &&
2804 pname != GL_BUFFER_MAP_LENGTH &&
2805 pname != GL_BUFFER_MAP_OFFSET,
2806 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002807
2808 if (!params) return;
2809
2810 BufferData* buf = ctx->getBufferData(target);
2811
2812 switch (pname) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002813 case GL_BUFFER_ACCESS_FLAGS:
2814 *params = buf ? buf->m_mappedAccess : 0;
2815 break;
2816 case GL_BUFFER_MAPPED:
2817 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
2818 break;
2819 case GL_BUFFER_SIZE:
2820 *params = buf ? buf->m_size : 0;
2821 break;
2822 case GL_BUFFER_USAGE:
2823 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
2824 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002825 case GL_BUFFER_MAP_LENGTH:
2826 *params = buf ? buf->m_mappedLength : 0;
2827 break;
2828 case GL_BUFFER_MAP_OFFSET:
2829 *params = buf ? buf->m_mappedOffset : 0;
2830 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002831 default:
2832 break;
2833 }
2834}
2835
2836void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
2837 GL2Encoder* ctx = (GL2Encoder*)self;
2838 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2839 SET_ERROR_IF(
2840 target == GL_ATOMIC_COUNTER_BUFFER ||
2841 target == GL_DISPATCH_INDIRECT_BUFFER ||
2842 target == GL_DRAW_INDIRECT_BUFFER ||
2843 target == GL_SHADER_STORAGE_BUFFER,
2844 GL_INVALID_ENUM);
2845 SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
2846 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
2847 if (!params) return;
2848
2849 BufferData* buf = ctx->getBufferData(target);
2850
2851 if (!buf || !buf->m_mapped) { *params = NULL; return; }
2852
2853 *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
2854}
2855
2856static const char* const kNameDelimiter = ";";
2857
2858static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
2859
2860#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
2861
2862 std::string packed;
2863 // validate the array of char[]'s
2864 const char* currName;
2865 for (GLsizei i = 0; i < count; i++) {
2866 currName = names[i];
2867 VALIDATE(!currName, GL_INVALID_OPERATION);
2868 // check if has reasonable size
2869 size_t len = strlen(currName);
2870 VALIDATE(!len, GL_INVALID_OPERATION);
2871 // check for our delimiter, which if present
2872 // in the name, means an invalid name anyway.
2873 VALIDATE(strstr(currName, kNameDelimiter),
2874 GL_INVALID_OPERATION);
2875 packed += currName;
2876 packed += ";";
2877 }
2878
2879 *err_out = GL_NO_ERROR;
2880 return packed;
2881}
2882
2883void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
2884 GL2Encoder* ctx = (GL2Encoder*)self;
2885
2886 if (!uniformCount) return;
2887
2888 GLint err = GL_NO_ERROR;
2889 std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
2890 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
2891
2892 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
2893 std::vector<int> arrIndices;
2894 for (size_t i = 0; i < uniformCount; i++) {
2895 int err;
2896 arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
2897 if (err) {
2898 ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
2899 return;
2900 }
2901 }
2902
2903 ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
2904
2905 for (int i = 0; i < uniformCount; i++) {
2906 if (uniformIndices[i] >= 0 && needLocationWAR) {
2907 uniformIndices[i] =
2908 ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
2909 }
2910 }
2911}
2912
2913void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
2914 GL2Encoder *ctx = (GL2Encoder*)self;
2915 GLClientState* state = ctx->m_state;
2916 GLSharedGroupPtr shared = ctx->m_shared;
2917
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002918 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002919 ctx->m_glUniform1ui_enc(self, hostLoc, v0);
2920
2921 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002922 if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002923 GLenum origActiveTexture = state->getActiveTextureUnit();
2924 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
2925 ctx->m_glActiveTexture_enc(self, origActiveTexture);
2926 }
2927 state->setActiveTextureUnit(origActiveTexture);
2928 }
2929}
2930
2931void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) {
2932 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002933 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002934 ctx->m_glUniform2ui_enc(self, hostLoc, v0, v1);
2935}
2936
2937void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) {
2938 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002939 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002940 ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2);
2941}
2942
2943void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) {
2944 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002945 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002946 ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3);
2947}
2948
2949void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2950 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002951 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002952 ctx->m_glUniform1uiv_enc(self, hostLoc, count, value);
2953}
2954
2955void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2956 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002957 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002958 ctx->m_glUniform2uiv_enc(self, hostLoc, count, value);
2959}
2960
2961void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2962 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002963 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002964 ctx->m_glUniform3uiv_enc(self, hostLoc, count, value);
2965}
2966
2967void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
2968 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002969 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002970 ctx->m_glUniform4uiv_enc(self, hostLoc, count, value);
2971}
2972
2973void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
2974 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002975 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002976 ctx->m_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value);
2977}
2978
2979void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
2980 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002981 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002982 ctx->m_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value);
2983}
2984
2985void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
2986 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002987 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002988 ctx->m_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value);
2989}
2990
2991void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
2992 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002993 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002994 ctx->m_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value);
2995}
2996
2997void GL2Encoder::s_glUniformMatrix3x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
2998 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002999 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003000 ctx->m_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value);
3001}
3002
3003void GL2Encoder::s_glUniformMatrix4x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3004 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003005 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003006 ctx->m_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value);
3007}
3008
3009void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3010 GL2Encoder *ctx = (GL2Encoder*)self;
3011 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3012 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3013 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3014 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3015 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3016 ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3017}
3018
3019void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3020 GL2Encoder* ctx = (GL2Encoder*)self;
3021 GLClientState* state = ctx->m_state;
3022
3023 // refresh client state's # active uniforms in this block
3024 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3025 // TODO if worth it: cache uniform count and other params,
3026 // invalidate on program relinking.
3027 GLint numActiveUniforms;
3028 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3029 program, uniformBlockIndex,
3030 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3031 &numActiveUniforms);
3032 ctx->m_state->setNumActiveUniformsInUniformBlock(
3033 program, uniformBlockIndex, numActiveUniforms);
3034 }
3035
3036 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3037 program, uniformBlockIndex,
3038 pname, params);
3039}
3040
3041void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3042 GL2Encoder *ctx = (GL2Encoder *)self;
3043 assert(ctx->m_state);
3044 GLint maxIndex;
3045 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3046 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3047
3048 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3049 ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3050 }
3051}
3052
3053void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3054 GL2Encoder *ctx = (GL2Encoder *)self;
3055 assert(ctx->m_state);
3056 GLint maxIndex;
3057 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3058 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3059
3060 if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3061 ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3062 }
3063}
3064
3065void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3066 GL2Encoder *ctx = (GL2Encoder *)self;
3067 assert(ctx->m_state != NULL);
3068 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
3069 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
3070 SET_ERROR_IF(
3071 !(type == GL_BYTE ||
3072 type == GL_UNSIGNED_BYTE ||
3073 type == GL_SHORT ||
3074 type == GL_UNSIGNED_SHORT ||
3075 type == GL_INT ||
3076 type == GL_UNSIGNED_INT),
3077 GL_INVALID_ENUM);
3078 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
3079
3080 ctx->m_state->setVertexAttribBinding(index, index);
3081 ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true);
3082 GLsizei effectiveStride = stride;
3083 if (stride == 0) {
3084 effectiveStride = glSizeof(type) * size;
3085 }
3086 ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride);
3087
3088 if (ctx->m_state->currentArrayVbo() != 0) {
3089 ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer);
3090 } else {
3091 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION);
3092 // wait for client-array handler
3093 }
3094}
3095
3096void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) {
3097 GL2Encoder *ctx = (GL2Encoder *)self;
3098 assert(ctx->m_state != NULL);
3099 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
3100 ctx->m_state->setVertexAttribBinding(index, index);
3101 ctx->m_state->setVertexBindingDivisor(index, divisor);
3102 ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor);
3103}
3104
3105void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3106 GLenum target, GLsizei samples, GLenum internalformat,
3107 GLsizei width, GLsizei height) {
3108 GL2Encoder *ctx = (GL2Encoder *)self;
3109 GLClientState* state = ctx->m_state;
3110
3111 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3112 SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3113
3114 GLint max_samples;
3115 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3116 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3117
3118 state->setBoundRenderbufferFormat(internalformat);
3119 state->setBoundRenderbufferSamples(samples);
3120 ctx->m_glRenderbufferStorageMultisample_enc(
3121 self, target, samples, internalformat, width, height);
3122}
3123
3124void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3125 GL2Encoder* ctx = (GL2Encoder*)self;
3126 SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3127 SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3128 for (int i = 0; i < n; i++) {
3129 SET_ERROR_IF(
3130 bufs[i] != GL_NONE &&
3131 bufs[i] != GL_BACK &&
3132 glUtilsColorAttachmentIndex(bufs[i]) == -1,
3133 GL_INVALID_ENUM);
3134 SET_ERROR_IF(
3135 !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3136 glUtilsColorAttachmentIndex(bufs[i]) != -1,
3137 GL_INVALID_OPERATION);
3138 SET_ERROR_IF(
3139 ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3140 ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3141 glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3142 (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3143 bufs[i] != GL_NONE)),
3144 GL_INVALID_OPERATION);
3145 }
3146
3147 ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3148}
3149
3150void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3151 GL2Encoder* ctx = (GL2Encoder*)self;
3152
3153 SET_ERROR_IF(
3154 glUtilsColorAttachmentIndex(src) != -1 &&
3155 (glUtilsColorAttachmentIndex(src) >=
3156 ctx->m_state->getMaxColorAttachments()),
3157 GL_INVALID_OPERATION);
3158 SET_ERROR_IF(
3159 src != GL_NONE &&
3160 src != GL_BACK &&
3161 src > GL_COLOR_ATTACHMENT0 &&
3162 src < GL_DEPTH_ATTACHMENT &&
3163 (src - GL_COLOR_ATTACHMENT0) >
3164 ctx->m_state->getMaxColorAttachments(),
3165 GL_INVALID_OPERATION);
3166 SET_ERROR_IF(
3167 src != GL_NONE &&
3168 src != GL_BACK &&
3169 glUtilsColorAttachmentIndex(src) == -1,
3170 GL_INVALID_ENUM);
3171 SET_ERROR_IF(
3172 !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3173 src != GL_NONE &&
3174 src != GL_BACK,
3175 GL_INVALID_OPERATION);
3176 SET_ERROR_IF(
3177 ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3178 src != GL_NONE &&
3179 glUtilsColorAttachmentIndex(src) == -1,
3180 GL_INVALID_OPERATION);
3181
3182 ctx->m_glReadBuffer_enc(ctx, src);
3183}
3184
3185void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3186 GL2Encoder* ctx = (GL2Encoder*)self;
3187 GLClientState* state = ctx->m_state;
3188
3189 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3190 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3191 GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3192 SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3193 lastBoundTarget != GL_TEXTURE_3D,
3194 GL_INVALID_OPERATION);
3195 state->attachTextureObject(target, attachment, texture);
3196
3197 GLint max3DTextureSize;
3198 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3199 SET_ERROR_IF(
3200 layer >= max3DTextureSize,
3201 GL_INVALID_VALUE);
3202
3203 ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3204}
3205
3206void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3207 GL2Encoder* ctx = (GL2Encoder*)self;
3208 GLClientState* state = ctx->m_state;
3209
3210 SET_ERROR_IF(
3211 target != GL_TEXTURE_2D &&
3212 target != GL_TEXTURE_CUBE_MAP,
3213 GL_INVALID_ENUM);
3214 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3215 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3216 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3217 SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3218 GL_INVALID_OPERATION);
3219 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3220
3221 state->setBoundTextureInternalFormat(target, internalformat);
3222 state->setBoundTextureDims(target, -1, width, height, 1);
3223 state->setBoundTextureImmutableFormat(target);
3224 ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
3225}
3226
3227void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3228 GL2Encoder* ctx = (GL2Encoder*)self;
3229
3230 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3231
3232 GLint maxCount = 0;
3233 ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3234
3235 SET_ERROR_IF(
3236 bufferMode == GL_SEPARATE_ATTRIBS &&
3237 maxCount < count,
3238 GL_INVALID_VALUE);
3239 SET_ERROR_IF(
3240 bufferMode != GL_INTERLEAVED_ATTRIBS &&
3241 bufferMode != GL_SEPARATE_ATTRIBS,
3242 GL_INVALID_ENUM);
3243
3244 if (!count) return;
3245
3246 GLint err = GL_NO_ERROR;
3247 std::string packed = packVarNames(count, varyings, &err);
3248 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3249
3250 ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3251}
3252
3253void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3254 GL2Encoder* ctx = (GL2Encoder*)self;
3255 GLClientState* state = ctx->m_state;
3256 ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3257 state->setTransformFeedbackActiveUnpaused(true);
3258}
3259
3260void GL2Encoder::s_glEndTransformFeedback(void* self) {
3261 GL2Encoder* ctx = (GL2Encoder*)self;
3262 GLClientState* state = ctx->m_state;
3263 ctx->m_glEndTransformFeedback_enc(ctx);
3264 state->setTransformFeedbackActiveUnpaused(false);
3265}
3266
3267void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3268 GL2Encoder* ctx = (GL2Encoder*)self;
3269 GLClientState* state = ctx->m_state;
3270 ctx->m_glPauseTransformFeedback_enc(ctx);
3271 state->setTransformFeedbackActiveUnpaused(false);
3272}
3273
3274void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3275 GL2Encoder* ctx = (GL2Encoder*)self;
3276 GLClientState* state = ctx->m_state;
3277 ctx->m_glResumeTransformFeedback_enc(ctx);
3278 state->setTransformFeedbackActiveUnpaused(true);
3279}
3280
3281void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3282 GLsizei width, GLsizei height, GLsizei depth,
3283 GLint border, GLenum format, GLenum type, const GLvoid* data) {
3284 GL2Encoder* ctx = (GL2Encoder*)self;
3285 GLClientState* state = ctx->m_state;
3286
3287 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3288 target != GL_TEXTURE_2D_ARRAY,
3289 GL_INVALID_ENUM);
3290 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3291 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3292
3293 // If unpack buffer is nonzero, verify unmapped state.
3294 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3295
3296 GLint max_texture_size;
3297 GLint max_3d_texture_size;
3298 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3299 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3300 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3301 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3302 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3303
3304 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3305 SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3306 SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3307 SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3308 SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3309 SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3310 SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3311 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3312 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3313 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3314 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3315 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3316 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3317 GL_INVALID_OPERATION);
3318 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3319 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3320 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3321 glSizeof(type)),
3322 GL_INVALID_OPERATION);
3323 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3324
3325 state->setBoundTextureInternalFormat(target, internalFormat);
3326 state->setBoundTextureFormat(target, format);
3327 state->setBoundTextureType(target, type);
3328 state->setBoundTextureDims(target, level, width, height, depth);
3329
3330 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3331 ctx->glTexImage3DOffsetAEMU(
3332 ctx, target, level, internalFormat,
3333 width, height, depth,
3334 border, format, type, (uintptr_t)data);
3335 } else {
3336 ctx->m_glTexImage3D_enc(ctx,
3337 target, level, internalFormat,
3338 width, height, depth,
3339 border, format, type, data);
3340 }
3341}
3342
3343void 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) {
3344 GL2Encoder* ctx = (GL2Encoder*)self;
3345 GLClientState* state = ctx->m_state;
3346
3347 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3348 target != GL_TEXTURE_2D_ARRAY,
3349 GL_INVALID_ENUM);
3350 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3351 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3352 // If unpack buffer is nonzero, verify unmapped state.
3353 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3354 GLint max_texture_size;
3355 GLint max_3d_texture_size;
3356 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3357 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3358 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3359 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3360 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3361 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3362 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3363 GLuint tex = state->getBoundTexture(target);
3364 GLsizei neededWidth = xoffset + width;
3365 GLsizei neededHeight = yoffset + height;
3366 GLsizei neededDepth = zoffset + depth;
3367
3368 SET_ERROR_IF(tex &&
3369 (neededWidth > state->queryTexWidth(level, tex) ||
3370 neededHeight > state->queryTexHeight(level, tex) ||
3371 neededDepth > state->queryTexDepth(level, tex)),
3372 GL_INVALID_VALUE);
3373 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3374 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3375 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3376 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3377 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3378 GL_INVALID_OPERATION);
3379 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3380 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3381 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3382 glSizeof(type)),
3383 GL_INVALID_OPERATION);
3384 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
3385 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3386
3387 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3388 ctx->glTexSubImage3DOffsetAEMU(ctx,
3389 target, level,
3390 xoffset, yoffset, zoffset,
3391 width, height, depth,
3392 format, type, (uintptr_t)data);
3393 } else {
3394 ctx->m_glTexSubImage3D_enc(ctx,
3395 target, level,
3396 xoffset, yoffset, zoffset,
3397 width, height, depth,
3398 format, type, data);
3399 }
3400}
3401
3402void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
3403 GL2Encoder* ctx = (GL2Encoder*)self;
3404 GLClientState* state = ctx->m_state;
3405
3406 // Filter compressed formats support.
3407 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3408 // If unpack buffer is nonzero, verify unmapped state.
3409 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3410 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3411 SET_ERROR_IF(border, GL_INVALID_VALUE);
3412 // If unpack buffer is nonzero, verify buffer data fits.
3413 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3414 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3415 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3416 GL_INVALID_OPERATION);
3417 // TODO: Fix:
3418 // If |imageSize| is too small for compressed dimensions.
3419 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
3420 state->setBoundTextureInternalFormat(target, (GLint)internalformat);
3421 state->setBoundTextureDims(target, level, width, height, depth);
3422
3423 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3424 ctx->glCompressedTexImage3DOffsetAEMU(
3425 ctx, target, level, internalformat,
3426 width, height, depth, border,
3427 imageSize, (uintptr_t)data);
3428 } else {
3429 ctx->m_glCompressedTexImage3D_enc(
3430 ctx, target, level, internalformat,
3431 width, height, depth, border,
3432 imageSize, data);
3433 }
3434}
3435
3436void 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) {
3437 GL2Encoder* ctx = (GL2Encoder*)self;
3438 GLClientState* state = ctx->m_state;
3439
3440 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3441 // If unpack buffer is nonzero, verify unmapped state.
3442 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3443 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3444 // If unpack buffer is nonzero, verify buffer data fits.
3445 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3446 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3447 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3448 GL_INVALID_OPERATION);
3449 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3450
3451 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3452 ctx->glCompressedTexSubImage3DOffsetAEMU(
3453 ctx, target, level,
3454 xoffset, yoffset, zoffset,
3455 width, height, depth,
3456 format, imageSize, (uintptr_t)data);
3457 } else {
3458 ctx->m_glCompressedTexSubImage3D_enc(
3459 ctx, target, level,
3460 xoffset, yoffset, zoffset,
3461 width, height, depth,
3462 format, imageSize, data);
3463
3464 }
3465}
3466
3467void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
3468 GL2Encoder* ctx = (GL2Encoder*)self;
3469 GLClientState* state = ctx->m_state;
3470 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3471 target != GL_TEXTURE_2D_ARRAY,
3472 GL_INVALID_ENUM);
3473 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3474 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3475 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3476 SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
3477 GL_INVALID_OPERATION);
3478 SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
3479 GL_INVALID_OPERATION);
3480 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3481
3482 state->setBoundTextureInternalFormat(target, internalformat);
3483 state->setBoundTextureDims(target, -1, width, height, depth);
3484 state->setBoundTextureImmutableFormat(target);
3485 ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
3486 state->setBoundTextureImmutableFormat(target);
3487}
3488
3489void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
3490 GL2Encoder *ctx = (GL2Encoder *)self;
3491 assert(ctx->m_state != NULL);
3492 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3493 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3494
3495 bool has_client_vertex_arrays = false;
3496 bool has_indirect_arrays = false;
3497 ctx->getVBOUsage(&has_client_vertex_arrays,
3498 &has_indirect_arrays);
3499
3500 if (has_client_vertex_arrays ||
3501 (!has_client_vertex_arrays &&
3502 !has_indirect_arrays)) {
3503 ctx->sendVertexAttributes(first, count, true, primcount);
3504 ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
3505 } else {
3506 ctx->sendVertexAttributes(0, count, false, primcount);
3507 ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
3508 }
3509 ctx->m_stream->flush();
3510}
3511
3512void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
3513{
3514
3515 GL2Encoder *ctx = (GL2Encoder *)self;
3516 assert(ctx->m_state != NULL);
3517 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3518 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3519 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3520 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3521
3522 bool has_client_vertex_arrays = false;
3523 bool has_indirect_arrays = false;
3524 int nLocations = ctx->m_state->nLocations();
3525 GLintptr offset = 0;
3526
3527 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3528
3529 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3530 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3531 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3532 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3533 }
3534
3535 BufferData* buf = NULL;
3536 int minIndex = 0, maxIndex = 0;
3537
3538 // For validation/immediate index array purposes,
3539 // we need the min/max vertex index of the index array.
3540 // If the VBO != 0, this may not be the first time we have
3541 // used this particular index buffer. getBufferIndexRange
3542 // can more quickly get min/max vertex index by
3543 // caching previous results.
3544 if (ctx->m_state->currentIndexVbo() != 0) {
3545 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3546 offset = (GLintptr)indices;
3547 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3548 ctx->getBufferIndexRange(buf,
3549 indices,
3550 type,
3551 (size_t)count,
3552 (size_t)offset,
3553 &minIndex, &maxIndex);
3554 } else {
3555 // In this case, the |indices| field holds a real
3556 // array, so calculate the indices now. They will
3557 // also be needed to know how much data to
3558 // transfer to host.
3559 ctx->calcIndexRange(indices,
3560 type,
3561 count,
3562 &minIndex,
3563 &maxIndex);
3564 }
3565
3566 bool adjustIndices = true;
3567 if (ctx->m_state->currentIndexVbo() != 0) {
3568 if (!has_client_vertex_arrays) {
3569 ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
3570 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3571 ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
3572 ctx->flushDrawCall();
3573 adjustIndices = false;
3574 } else {
3575 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3576 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3577 }
3578 }
3579 if (adjustIndices) {
3580 void *adjustedIndices =
3581 ctx->recenterIndices(indices,
3582 type,
3583 count,
3584 minIndex);
3585
3586 if (has_indirect_arrays || 1) {
3587 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
3588 ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
3589 ctx->m_stream->flush();
3590 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3591 if(!has_indirect_arrays) {
3592 //ALOGD("unoptimized drawelements !!!\n");
3593 }
3594 } else {
3595 // we are all direct arrays and immidate mode index array -
3596 // rebuild the arrays and the index array;
3597 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3598 }
3599 }
3600}
3601
3602void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
3603{
3604
3605 GL2Encoder *ctx = (GL2Encoder *)self;
3606 assert(ctx->m_state != NULL);
3607 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3608 SET_ERROR_IF(end < start, GL_INVALID_VALUE);
3609 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3610 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3611 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3612
3613 bool has_client_vertex_arrays = false;
3614 bool has_indirect_arrays = false;
3615 int nLocations = ctx->m_state->nLocations();
3616 GLintptr offset = 0;
3617
3618 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3619
3620 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3621 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3622 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3623 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3624 }
3625
3626 BufferData* buf = NULL;
3627 int minIndex = 0, maxIndex = 0;
3628
3629 // For validation/immediate index array purposes,
3630 // we need the min/max vertex index of the index array.
3631 // If the VBO != 0, this may not be the first time we have
3632 // used this particular index buffer. getBufferIndexRange
3633 // can more quickly get min/max vertex index by
3634 // caching previous results.
3635 if (ctx->m_state->currentIndexVbo() != 0) {
3636 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3637 offset = (GLintptr)indices;
3638 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3639 ctx->getBufferIndexRange(buf,
3640 indices,
3641 type,
3642 (size_t)count,
3643 (size_t)offset,
3644 &minIndex, &maxIndex);
3645 } else {
3646 // In this case, the |indices| field holds a real
3647 // array, so calculate the indices now. They will
3648 // also be needed to know how much data to
3649 // transfer to host.
3650 ctx->calcIndexRange(indices,
3651 type,
3652 count,
3653 &minIndex,
3654 &maxIndex);
3655 }
3656
3657 bool adjustIndices = true;
3658 if (ctx->m_state->currentIndexVbo() != 0) {
3659 if (!has_client_vertex_arrays) {
3660 ctx->sendVertexAttributes(0, maxIndex + 1, false);
3661 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3662 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
3663 ctx->flushDrawCall();
3664 adjustIndices = false;
3665 } else {
3666 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3667 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3668 }
3669 }
3670 if (adjustIndices) {
3671 void *adjustedIndices =
3672 ctx->recenterIndices(indices,
3673 type,
3674 count,
3675 minIndex);
3676
3677 if (has_indirect_arrays || 1) {
3678 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
3679 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
3680 ctx->m_stream->flush();
3681 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3682 if(!has_indirect_arrays) {
3683 //ALOGD("unoptimized drawelements !!!\n");
3684 }
3685 } else {
3686 // we are all direct arrays and immidate mode index array -
3687 // rebuild the arrays and the index array;
3688 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3689 }
3690 }
3691}
3692
3693// struct GLStringKey {
3694// GLenum name;
3695// GLuint index;
3696// };
3697//
3698// struct GLStringKeyCompare {
3699// bool operator() (const GLStringKey& a,
3700// const GLStringKey& b) const {
3701// if (a.name != b.name) return a.name < b.name;
3702// if (a.index != b.index) return a.index < b.index;
3703// return false;
3704// }
3705// };
3706//
3707// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
3708//
3709// static GLStringStore sGLStringStore;
3710// bool sGLStringStoreInitialized = false;
3711
3712const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
3713 GL2Encoder *ctx = (GL2Encoder *)self;
3714 GLubyte *retval = (GLubyte *) "";
3715
3716 RET_AND_SET_ERROR_IF(
3717 name != GL_VENDOR &&
3718 name != GL_RENDERER &&
3719 name != GL_VERSION &&
3720 name != GL_EXTENSIONS,
3721 GL_INVALID_ENUM,
3722 retval);
3723
3724 RET_AND_SET_ERROR_IF(
3725 name == GL_VENDOR ||
3726 name == GL_RENDERER ||
3727 name == GL_VERSION ||
3728 name == GL_EXTENSIONS &&
3729 index != 0,
3730 GL_INVALID_VALUE,
3731 retval);
3732
3733 switch (name) {
3734 case GL_VENDOR:
3735 retval = gVendorString;
3736 break;
3737 case GL_RENDERER:
3738 retval = gRendererString;
3739 break;
3740 case GL_VERSION:
3741 retval = gVersionString;
3742 break;
3743 case GL_EXTENSIONS:
3744 retval = gExtensionsString;
3745 break;
3746 }
3747
3748 return retval;
3749}
3750
3751void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
3752 GL2Encoder *ctx = (GL2Encoder *)self;
3753
3754 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3755
3756 GLint linkStatus = 0;
3757 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
3758 GLint properLength = 0;
3759 ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
3760
3761 SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
3762 SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
3763
3764 ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
3765}
3766
3767void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
3768 GL2Encoder *ctx = (GL2Encoder *)self;
3769
3770 SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
3771 SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
3772 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
3773 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
3774 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
3775 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
3776 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
3777 ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
3778 GL_INVALID_OPERATION);
3779 /*
3780GL_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.
3781
3782GL_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.
3783
3784GL_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.
3785
3786GL_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.
3787*/
3788
3789 FboFormatInfo fbo_format_info;
3790 ctx->m_state->getBoundFramebufferFormat(
3791 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
3792 SET_ERROR_IF(
3793 fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3794 !GLESv2Validation::readPixelsFboFormatMatch(
3795 format, type, fbo_format_info.tex_type),
3796 GL_INVALID_OPERATION);
3797
3798 if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
3799 ctx->glReadPixelsOffsetAEMU(
3800 ctx, x, y, width, height,
3801 format, type, (uintptr_t)pixels);
3802 } else {
3803 ctx->m_glReadPixels_enc(
3804 ctx, x, y, width, height,
3805 format, type, pixels);
3806 }
3807}
3808
3809// Track enabled state for some things like:
3810// - Primitive restart
3811void GL2Encoder::s_glEnable(void* self, GLenum what) {
3812 GL2Encoder *ctx = (GL2Encoder *)self;
3813
3814 switch (what) {
3815 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
3816 ctx->m_primitiveRestartEnabled = true;
3817 break;
3818 }
3819
3820 ctx->m_glEnable_enc(ctx, what);
3821}
3822
3823void GL2Encoder::s_glDisable(void* self, GLenum what) {
3824 GL2Encoder *ctx = (GL2Encoder *)self;
3825
3826 switch (what) {
3827 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
3828 ctx->m_primitiveRestartEnabled = false;
3829 break;
3830 }
3831
3832 ctx->m_glDisable_enc(ctx, what);
3833}
3834
3835void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
3836 GL2Encoder *ctx = (GL2Encoder *)self;
3837
3838 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3839
3840 ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
3841}
3842
3843void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
3844 GL2Encoder *ctx = (GL2Encoder *)self;
3845
3846 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3847
3848 ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
3849}
3850
3851void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
3852 GL2Encoder *ctx = (GL2Encoder *)self;
3853
3854 SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3855
3856 ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
3857}
3858
3859void 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) {
3860 GL2Encoder *ctx = (GL2Encoder *)self;
3861 GLClientState* state = ctx->m_state;
3862
3863 bool validateColor = mask | GL_COLOR_BUFFER_BIT;
3864 bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
3865 bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
3866
3867 FboFormatInfo read_fbo_format_info;
3868 FboFormatInfo draw_fbo_format_info;
3869 if (validateColor) {
3870 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
3871 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
3872
3873 if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3874 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
3875 SET_ERROR_IF(
3876 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3877 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3878 !GLESv2Validation::blitFramebufferFormat(
3879 read_fbo_format_info.tex_type,
3880 draw_fbo_format_info.tex_type),
3881 GL_INVALID_OPERATION);
3882 }
3883 }
3884
3885 if (validateDepth) {
3886 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
3887 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
3888
3889 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3890 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
3891 SET_ERROR_IF(
3892 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3893 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3894 !GLESv2Validation::blitFramebufferFormat(
3895 read_fbo_format_info.rb_format,
3896 draw_fbo_format_info.rb_format),
3897 GL_INVALID_OPERATION);
3898 }
3899 }
3900
3901 if (validateStencil) {
3902 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
3903 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
3904
3905 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3906 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
3907 SET_ERROR_IF(
3908 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3909 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3910 !GLESv2Validation::blitFramebufferFormat(
3911 read_fbo_format_info.rb_format,
3912 draw_fbo_format_info.rb_format),
3913 GL_INVALID_OPERATION);
3914 }
3915 }
3916
3917 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
3918 SET_ERROR_IF(
3919 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3920 draw_fbo_format_info.rb_multisamples > 0,
3921 GL_INVALID_OPERATION);
3922 SET_ERROR_IF(
3923 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3924 draw_fbo_format_info.tex_multisamples > 0,
3925 GL_INVALID_OPERATION);
3926
3927 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
3928 SET_ERROR_IF(
3929 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3930 read_fbo_format_info.rb_multisamples > 0 &&
3931 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3932 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3933 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3934 (read_fbo_format_info.rb_format !=
3935 draw_fbo_format_info.rb_format),
3936 GL_INVALID_OPERATION);
3937 SET_ERROR_IF(
3938 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3939 read_fbo_format_info.rb_multisamples > 0 &&
3940 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3941 (srcX0 != dstX0 || srcY0 != dstY0 ||
3942 srcX1 != dstX1 || srcY1 != dstY1),
3943 GL_INVALID_OPERATION);
3944
3945 ctx->m_glBlitFramebuffer_enc(ctx,
3946 srcX0, srcY0, srcX1, srcY1,
3947 dstX0, dstY0, dstX1, dstY1,
3948 mask, filter);
3949}
3950
3951void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
3952 GL2Encoder *ctx = (GL2Encoder *)self;
3953
3954 SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
3955 pname != GL_SAMPLES,
3956 GL_INVALID_ENUM);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003957 ALOGD("%s: maj min %d %d", __FUNCTION__, ctx->majorVersion(), ctx->minorVersion());
3958 SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003959 SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
3960 !GLESv2Validation::colorRenderableFormat(internalformat) &&
3961 !GLESv2Validation::depthRenderableFormat(internalformat) &&
3962 !GLESv2Validation::stencilRenderableFormat(internalformat),
3963 GL_INVALID_ENUM);
3964 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
3965
3966 if (bufSize < 1) return;
3967
3968 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
3969 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
3970 switch (pname) {
3971 case GL_NUM_SAMPLE_COUNTS:
3972 *params = 3;
3973 break;
3974 case GL_SAMPLES:
3975 params[0] = 4;
3976 if (bufSize > 1) params[1] = 2;
3977 if (bufSize > 2) params[2] = 1;
3978 break;
3979 default:
3980 break;
3981 }
3982}
3983
3984void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
3985 GL2Encoder *ctx = (GL2Encoder *)self;
3986 GLClientState* state = ctx->m_state;
3987
3988 SET_ERROR_IF(target != GL_TEXTURE_2D &&
3989 target != GL_TEXTURE_3D &&
3990 target != GL_TEXTURE_CUBE_MAP,
3991 GL_INVALID_ENUM);
3992
3993 GLuint tex = state->getBoundTexture(target);
3994 GLenum internalformat = state->queryTexInternalFormat(tex);
3995 GLenum format = state->queryTexFormat(tex);
3996
3997 SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
3998 GL_INVALID_OPERATION);
3999 SET_ERROR_IF(tex &&
4000 !GLESv2Validation::unsizedFormat(internalformat) &&
4001 (!GLESv2Validation::colorRenderableFormat(internalformat) ||
4002 !GLESv2Validation::filterableTexFormat(internalformat)),
4003 GL_INVALID_OPERATION);
4004
4005 ctx->m_glGenerateMipmap_enc(ctx, target);
4006}
4007
4008void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4009 GL2Encoder *ctx = (GL2Encoder *)self;
4010 GLint maxCombinedUnits;
4011 ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4012 SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4013
4014 ctx->m_glBindSampler_enc(ctx, unit, sampler);
4015}
4016
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004017GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4018 GL2Encoder *ctx = (GL2Encoder *)self;
4019 uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4020 return (GLsync)(uintptr_t)syncHandle;
4021}
4022
4023GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4024 GL2Encoder *ctx = (GL2Encoder *)self;
4025 return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4026}
4027
4028void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4029 GL2Encoder *ctx = (GL2Encoder *)self;
4030 ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4031}
4032
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004033void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) {
4034 GL2Encoder *ctx = (GL2Encoder *)self;
4035
4036 if (!sync) return;
4037
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004038 ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4039}
4040
4041GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4042 GL2Encoder *ctx = (GL2Encoder *)self;
4043 return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4044}
4045
4046void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4047 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004048
4049 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4050
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004051 return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004052}
4053
4054#define LIMIT_CASE(target, lim) \
4055 case target: \
4056 ctx->glGetIntegerv(ctx, lim, &limit); \
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004057 SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004058 break; \
4059
4060void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) {
4061 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004062 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004063
4064 GLint limit;
4065
4066 switch (target) {
4067 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4068 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4069 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4070 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4071 default:
4072 break;
4073 }
4074
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004075 const GLClientState::VertexAttribBindingVector& currBindings =
4076 state->currentVertexBufferBindings();
4077
4078 switch (target) {
4079 case GL_VERTEX_BINDING_DIVISOR:
4080 case GL_VERTEX_BINDING_OFFSET:
4081 case GL_VERTEX_BINDING_STRIDE:
4082 case GL_VERTEX_BINDING_BUFFER:
4083 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4084 break;
4085 default:
4086 break;
4087 }
4088
4089 switch (target) {
4090 case GL_VERTEX_BINDING_DIVISOR:
4091 *params = currBindings[index].divisor;
4092 return;
4093 case GL_VERTEX_BINDING_OFFSET:
4094 *params = currBindings[index].offset;
4095 return;
4096 case GL_VERTEX_BINDING_STRIDE:
4097 *params = currBindings[index].effectiveStride;
4098 return;
4099 case GL_VERTEX_BINDING_BUFFER:
4100 *params = currBindings[index].buffer;
4101 return;
4102 default:
4103 break;
4104 }
4105
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004106 ctx->m_glGetIntegeri_v_enc(self, target, index, params);
4107}
4108
4109void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
4110 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004111 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004112
4113 GLint limit;
4114
4115 switch (target) {
4116 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4117 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4118 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4119 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4120 default:
4121 break;
4122 }
4123
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004124 const GLClientState::VertexAttribBindingVector& currBindings =
4125 state->currentVertexBufferBindings();
4126
4127 switch (target) {
4128 case GL_VERTEX_BINDING_DIVISOR:
4129 case GL_VERTEX_BINDING_OFFSET:
4130 case GL_VERTEX_BINDING_STRIDE:
4131 case GL_VERTEX_BINDING_BUFFER:
4132 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4133 break;
4134 default:
4135 break;
4136 }
4137
4138 switch (target) {
4139 case GL_VERTEX_BINDING_DIVISOR:
4140 *params = currBindings[index].divisor;
4141 return;
4142 case GL_VERTEX_BINDING_OFFSET:
4143 *params = currBindings[index].offset;
4144 return;
4145 case GL_VERTEX_BINDING_STRIDE:
4146 *params = currBindings[index].effectiveStride;
4147 return;
4148 case GL_VERTEX_BINDING_BUFFER:
4149 *params = currBindings[index].buffer;
4150 return;
4151 default:
4152 break;
4153 }
4154
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004155 ctx->m_glGetInteger64i_v_enc(self, target, index, params);
4156}
4157
4158void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4159 GL2Encoder *ctx = (GL2Encoder *)self;
4160 ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4161 if (pname == GL_SHADER_SOURCE_LENGTH) {
4162 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4163 if (shaderData) {
4164 int totalLen = 0;
4165 for (int i = 0; i < shaderData->sources.size(); i++) {
4166 totalLen += shaderData->sources[i].size();
4167 }
4168 if (totalLen != 0) {
4169 *params = totalLen + 1; // account for null terminator
4170 }
4171 }
4172 }
4173}
4174
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004175void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) {
4176 GL2Encoder *ctx = (GL2Encoder*)self;
4177 GLClientState* state = ctx->m_state;
4178 GLSharedGroupPtr shared = ctx->m_shared;
4179
4180 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4181 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4182 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4183
4184 ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program);
4185 if (!state->currentProgram()) {
4186 state->setCurrentShaderProgram(program);
4187 }
4188}
4189
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004190GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4191
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004192 ALOGD("%s: entry firststr %s", __FUNCTION__, strings[0]);
4193
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004194 GLint* length = NULL;
4195 GL2Encoder* ctx = (GL2Encoder*)self;
4196
4197 int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004198 ALOGD("%s: len %d\n", __FUNCTION__, len);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004199 char *str = new char[len + 1];
4200 glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004201 ALOGD("%s: packed %s", __FUNCTION__, str);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004202
4203 // Do GLSharedGroup and location WorkARound-specific initialization
4204 // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4205 uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4206 ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
4207 ShaderData* sData = spData->shaderData;
4208
4209 if (!replaceSamplerExternalWith2D(str, sData)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004210 ALOGD("%s: failed to do stuf\n", __FUNCTION__);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004211 delete [] str;
4212 ctx->setError(GL_OUT_OF_MEMORY);
4213 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4214 return -1;
4215 }
4216
4217 GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004218 ALOGD("%s: return from glcreateshaderprogramv. res %u\n", __FUNCTION__, res);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004219 delete [] str;
4220
4221 // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4222 GLint linkStatus = 0;
4223 ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4224 if (!linkStatus) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004225 ALOGD("%s: no link status :(\n", __FUNCTION__);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004226 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4227 return -1;
4228 }
4229
4230 ctx->m_shared->associateGLShaderProgram(res, spDataId);
4231
4232 GLint numUniforms = 0;
4233 ctx->glGetProgramiv(ctx, res, GL_ACTIVE_UNIFORMS, &numUniforms);
4234 ctx->m_shared->initShaderProgramData(res, numUniforms);
4235
4236 GLint maxLength=0;
4237 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4238
4239 GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4240
4241 for (GLint i = 0; i < numUniforms; ++i) {
4242 ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4243 GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4244 ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4245 }
4246
4247 ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4248
4249 delete [] name;
4250
4251 return res;
4252}
4253
4254void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4255{
4256 GL2Encoder *ctx = (GL2Encoder*)self;
4257 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4258 ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4259}
4260
4261void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4262{
4263 GL2Encoder *ctx = (GL2Encoder*)self;
4264 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4265 ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4266}
4267
4268void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4269{
4270 GL2Encoder *ctx = (GL2Encoder*)self;
4271 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004272 ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004273
4274 GLClientState* state = ctx->m_state;
4275 GLSharedGroupPtr shared = ctx->m_shared;
4276 GLenum target;
4277
4278 if (shared->setSamplerUniform(program, location, v0, &target)) {
4279 GLenum origActiveTexture = state->getActiveTextureUnit();
4280 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4281 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4282 }
4283 state->setActiveTextureUnit(origActiveTexture);
4284 }
4285}
4286
4287void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4288{
4289 GL2Encoder *ctx = (GL2Encoder*)self;
4290 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4291 ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4292}
4293
4294void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4295{
4296 GL2Encoder *ctx = (GL2Encoder*)self;
4297 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4298 ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4299
4300 GLClientState* state = ctx->m_state;
4301 GLSharedGroupPtr shared = ctx->m_shared;
4302 GLenum target;
4303
4304 if (shared->setSamplerUniform(program, location, v0, &target)) {
4305 GLenum origActiveTexture = state->getActiveTextureUnit();
4306 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4307 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4308 }
4309 state->setActiveTextureUnit(origActiveTexture);
4310 }
4311}
4312
4313void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4314{
4315 GL2Encoder *ctx = (GL2Encoder*)self;
4316 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4317 ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
4318}
4319
4320void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
4321{
4322 GL2Encoder *ctx = (GL2Encoder*)self;
4323 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4324 ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
4325}
4326
4327void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4328{
4329 GL2Encoder *ctx = (GL2Encoder*)self;
4330 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4331 ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
4332}
4333
4334void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
4335{
4336 GL2Encoder *ctx = (GL2Encoder*)self;
4337 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4338 ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
4339}
4340
4341void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4342{
4343 GL2Encoder *ctx = (GL2Encoder*)self;
4344 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4345 ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
4346}
4347
4348void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
4349{
4350 GL2Encoder *ctx = (GL2Encoder*)self;
4351 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4352 ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
4353}
4354
4355void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4356{
4357 GL2Encoder *ctx = (GL2Encoder*)self;
4358 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4359 ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
4360}
4361
4362void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
4363{
4364 GL2Encoder *ctx = (GL2Encoder*)self;
4365 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4366 ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
4367}
4368
4369void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4370{
4371 GL2Encoder *ctx = (GL2Encoder*)self;
4372 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4373 ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
4374}
4375
4376void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
4377{
4378 GL2Encoder *ctx = (GL2Encoder*)self;
4379 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4380 ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
4381}
4382
4383void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4384{
4385 GL2Encoder *ctx = (GL2Encoder*)self;
4386 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4387 ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
4388}
4389
4390void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
4391{
4392 GL2Encoder *ctx = (GL2Encoder*)self;
4393 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4394 ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
4395}
4396
4397void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4398{
4399 GL2Encoder *ctx = (GL2Encoder*)self;
4400 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4401 ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
4402}
4403
4404void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
4405{
4406 GL2Encoder *ctx = (GL2Encoder*)self;
4407 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4408 ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
4409}
4410
4411void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4412{
4413 GL2Encoder *ctx = (GL2Encoder*)self;
4414 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4415 ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
4416}
4417
4418void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
4419{
4420 GL2Encoder *ctx = (GL2Encoder*)self;
4421 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4422 ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
4423}
4424
4425void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4426{
4427 GL2Encoder *ctx = (GL2Encoder*)self;
4428 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4429 ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
4430}
4431
4432void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
4433{
4434 GL2Encoder *ctx = (GL2Encoder*)self;
4435 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4436 ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
4437}
4438
4439void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4440{
4441 GL2Encoder *ctx = (GL2Encoder*)self;
4442 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4443 ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
4444}
4445
4446void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4447{
4448 GL2Encoder *ctx = (GL2Encoder*)self;
4449 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4450 ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
4451}
4452
4453void GL2Encoder::s_glProgramUniformMatrix2x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4454{
4455 GL2Encoder *ctx = (GL2Encoder*)self;
4456 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4457 ctx->m_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
4458}
4459
4460void GL2Encoder::s_glProgramUniformMatrix2x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4461{
4462 GL2Encoder *ctx = (GL2Encoder*)self;
4463 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4464 ctx->m_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
4465}
4466
4467void GL2Encoder::s_glProgramUniformMatrix3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4468{
4469 GL2Encoder *ctx = (GL2Encoder*)self;
4470 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4471 ctx->m_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
4472}
4473
4474void GL2Encoder::s_glProgramUniformMatrix3x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4475{
4476 GL2Encoder *ctx = (GL2Encoder*)self;
4477 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4478 ctx->m_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
4479}
4480
4481void GL2Encoder::s_glProgramUniformMatrix3x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4482{
4483 GL2Encoder *ctx = (GL2Encoder*)self;
4484 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4485 ctx->m_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
4486}
4487
4488void GL2Encoder::s_glProgramUniformMatrix4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4489{
4490 GL2Encoder *ctx = (GL2Encoder*)self;
4491 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4492 ctx->m_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
4493}
4494
4495void GL2Encoder::s_glProgramUniformMatrix4x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4496{
4497 GL2Encoder *ctx = (GL2Encoder*)self;
4498 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4499 ctx->m_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
4500}
4501
4502void GL2Encoder::s_glProgramUniformMatrix4x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4503{
4504 GL2Encoder *ctx = (GL2Encoder*)self;
4505 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4506 ctx->m_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
4507}
4508
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004509void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) {
4510 GL2Encoder* ctx = (GL2Encoder*)self;
4511 ctx->m_glProgramParameteri_enc(self, program, pname, value);
4512}
4513
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004514void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
4515{
4516 GL2Encoder *ctx = (GL2Encoder*)self;
4517 GLClientState* state = ctx->m_state;
4518 GLSharedGroupPtr shared = ctx->m_shared;
4519
4520 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4521 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4522 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4523
4524 ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
4525 state->associateProgramWithPipeline(program, pipeline);
4526
4527 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4528 if (state->currentProgram()) {
4529 return;
4530 }
4531
4532 // Otherwise, update host texture 2D bindings.
4533 ctx->updateHostTexture2DBindingsFromProgramData(program);
4534}
4535
4536void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
4537{
4538 GL2Encoder *ctx = (GL2Encoder*)self;
4539 GLClientState* state = ctx->m_state;
4540
4541 ctx->m_glBindProgramPipeline_enc(self, pipeline);
4542
4543 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4544 if (!pipeline || state->currentProgram()) {
4545 return;
4546 }
4547
4548 GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
4549 for (; it != state->programPipelineEnd(); ++it) {
4550 if (it->second == pipeline) {
4551 ctx->updateHostTexture2DBindingsFromProgramData(it->first);
4552 }
4553 }
4554}
4555
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004556void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
4557 GL2Encoder *ctx = (GL2Encoder*)self;
4558 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4559 if (bufSize == 0) {
4560 if (length) *length = 0;
4561 return;
4562 }
4563
4564 // Avoid modifying |name| if |*length| < bufSize.
4565 GLint* intermediate = new GLint[bufSize];
4566 GLsizei* myLength = length ? length : new GLsizei;
4567 bool needFreeLength = length == NULL;
4568
4569 ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
4570 GLsizei writtenInts = *myLength;
4571 memcpy(params, intermediate, writtenInts * sizeof(GLint));
4572
4573 delete [] intermediate;
4574 if (needFreeLength)
4575 delete myLength;
4576}
4577
4578GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
4579 GL2Encoder *ctx = (GL2Encoder*)self;
4580 return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
4581}
4582
4583GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
4584 GL2Encoder *ctx = (GL2Encoder*)self;
4585 return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
4586}
4587
4588void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
4589 GL2Encoder *ctx = (GL2Encoder*)self;
4590 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4591 if (bufSize == 0) {
4592 if (length) *length = 0;
4593 return;
4594 }
4595
4596 // Avoid modifying |name| if |*length| < bufSize.
4597 char* intermediate = new char[bufSize];
4598 GLsizei* myLength = length ? length : new GLsizei;
4599 bool needFreeLength = length == NULL;
4600
4601 ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
4602 GLsizei writtenStrLen = *myLength;
4603 memcpy(name, intermediate, writtenStrLen + 1);
4604
4605 delete [] intermediate;
4606 if (needFreeLength)
4607 delete myLength;
4608}
4609
4610void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
4611 GL2Encoder *ctx = (GL2Encoder*)self;
4612 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4613 if (bufSize == 0) {
4614 if (length) *length = 0;
4615 return;
4616 }
4617
4618 // Avoid modifying |infoLog| if |*length| < bufSize.
4619 GLchar* intermediate = new GLchar[bufSize];
4620 GLsizei* myLength = length ? length : new GLsizei;
4621 bool needFreeLength = length == NULL;
4622
4623 ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
4624 GLsizei writtenStrLen = *myLength;
4625 memcpy(infoLog, intermediate, writtenStrLen + 1);
4626
4627 delete [] intermediate;
4628 if (needFreeLength)
4629 delete myLength;
4630}
4631
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004632void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
4633 GL2Encoder *ctx = (GL2Encoder*)self;
4634 GLClientState* state = ctx->m_state;
4635
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004636 SET_ERROR_IF(!isValidVertexAttribIndex(self, attribindex), GL_INVALID_VALUE);
4637 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4638
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004639 state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false);
4640 ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset);
4641}
4642
4643void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
4644 GL2Encoder *ctx = (GL2Encoder*)self;
4645 GLClientState* state = ctx->m_state;
4646
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004647 SET_ERROR_IF(!isValidVertexAttribIndex(self, attribindex), GL_INVALID_VALUE);
4648 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4649
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004650 state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true);
4651 ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset);
4652}
4653
4654void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004655 GL2Encoder *ctx = (GL2Encoder*)self;
4656 GLClientState* state = ctx->m_state;
4657
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004658 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4659
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004660 state->setVertexBindingDivisor(bindingindex, divisor);
4661 ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor);
4662}
4663
4664void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) {
4665 GL2Encoder *ctx = (GL2Encoder*)self;
4666 GLClientState* state = ctx->m_state;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004667 SET_ERROR_IF(!isValidVertexAttribIndex(self, attribindex), GL_INVALID_VALUE);
4668 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004669
4670 state->setVertexAttribBinding(attribindex, bindingindex);
4671 ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex);
4672}
4673
4674void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
4675 GL2Encoder *ctx = (GL2Encoder*)self;
4676 GLClientState* state = ctx->m_state;
4677
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004678 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
4679
4680 GLint maxStride;
4681 ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
4682 SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE);
4683
4684 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4685
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004686 state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride);
4687 ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride);
4688}
4689
4690void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) {
4691 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004692 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004693
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004694 bool hasClientArrays = false;
4695 ctx->getVBOUsage(&hasClientArrays, NULL);
4696
4697 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
4698 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4699 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
4700
4701 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004702 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004703 // BufferData* buf = ctx->getBufferData(target);
4704 // if (buf) {
4705 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
4706 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004707 ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect);
4708 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004709 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
4710 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004711 ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize);
4712 }
4713}
4714
4715void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) {
4716 GL2Encoder *ctx = (GL2Encoder*)self;
4717
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004718 GLClientState* state = ctx->m_state;
4719
4720 bool hasClientArrays = false;
4721 ctx->getVBOUsage(&hasClientArrays, NULL);
4722
4723 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
4724 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4725 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
4726
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004727 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004728
4729 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004730 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004731 // BufferData* buf = ctx->getBufferData(target);
4732 // if (buf) {
4733 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
4734 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004735 ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect);
4736 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004737 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
4738 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004739 ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize);
4740 }
4741
4742}
4743
4744void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
4745 GL2Encoder *ctx = (GL2Encoder*)self;
4746 GLClientState* state = ctx->m_state;
4747
4748 SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
4749 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
4750 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
4751 SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
4752 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004753 GLint max_samples;
4754 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
4755 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004756
4757 state->setBoundTextureInternalFormat(target, internalformat);
4758 state->setBoundTextureDims(target, 0, width, height, 1);
4759 state->setBoundTextureImmutableFormat(target);
4760 state->setBoundTextureSamples(target, samples);
4761
4762 ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
4763}
4764