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