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
37static GLubyte *gVendorString= (GLubyte *) "Android";
38static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 3.0";
39static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 3.0";
40static 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
70GL2Encoder::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
349GL2Encoder::~GL2Encoder()
350{
351    delete m_compressedTextureFormats;
352}
353
354GLenum GL2Encoder::s_glGetError(void * self)
355{
356    GL2Encoder *ctx = (GL2Encoder *)self;
357    GLenum err = ctx->getError();
358    if(err != GL_NO_ERROR) {
359        ctx->setError(GL_NO_ERROR);
360        return err;
361    }
362
363    return ctx->m_glGetError_enc(self);
364
365}
366
367void GL2Encoder::s_glFlush(void *self)
368{
369    GL2Encoder *ctx = (GL2Encoder *) self;
370    ctx->m_glFlush_enc(self);
371    ctx->m_stream->flush();
372}
373
374const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
375{
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
403void 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}
412void 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
422void 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
435void 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
449void 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
458void 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
472static 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
485void 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
523void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
524{
525    GL2Encoder *ctx = (GL2Encoder *) self;
526    assert(ctx->m_state != NULL);
527    GLClientState* state = ctx->m_state;
528
529    switch (param) {
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
646void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
647{
648    GL2Encoder *ctx = (GL2Encoder *)self;
649    assert(ctx->m_state != NULL);
650    GLClientState* state = ctx->m_state;
651
652    switch (param) {
653    case GL_NUM_SHADER_BINARY_FORMATS:
654        *ptr = 0;
655        break;
656    case GL_SHADER_BINARY_FORMATS:
657        // do nothing
658        break;
659
660    case GL_COMPRESSED_TEXTURE_FORMATS: {
661        GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
662        if (ctx->m_num_compressedTextureFormats > 0 &&
663                compressedTextureFormats != NULL) {
664            for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
665                ptr[i] = (GLfloat) compressedTextureFormats[i];
666            }
667        }
668        break;
669    }
670
671    case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
672    case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
673    case GL_MAX_TEXTURE_IMAGE_UNITS:
674        ctx->m_glGetFloatv_enc(self, param, ptr);
675        *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
676        break;
677
678    case GL_TEXTURE_BINDING_2D:
679        *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
680        break;
681    case GL_TEXTURE_BINDING_EXTERNAL_OES:
682        *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
683        break;
684
685    default:
686        if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
687            ctx->m_glGetFloatv_enc(self, param, ptr);
688        }
689        break;
690    }
691}
692
693
694void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
695{
696    GL2Encoder *ctx = (GL2Encoder *)self;
697    assert(ctx->m_state != NULL);
698    GLClientState* state = ctx->m_state;
699
700    switch (param) {
701    case GL_NUM_SHADER_BINARY_FORMATS:
702        *ptr = GL_FALSE;
703        break;
704    case GL_SHADER_BINARY_FORMATS:
705        // do nothing
706        break;
707
708    case GL_COMPRESSED_TEXTURE_FORMATS: {
709        GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
710        if (ctx->m_num_compressedTextureFormats > 0 &&
711                compressedTextureFormats != NULL) {
712            for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
713                ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
714            }
715        }
716        break;
717    }
718
719    case GL_TEXTURE_BINDING_2D:
720        *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
721        break;
722    case GL_TEXTURE_BINDING_EXTERNAL_OES:
723        *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
724                ? GL_TRUE : GL_FALSE;
725        break;
726
727    default:
728        if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
729            ctx->m_glGetBooleanv_enc(self, param, ptr);
730        }
731        *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
732        break;
733    }
734}
735
736
737void 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
746void 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
756void 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
769void 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
782void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
783{
784    GL2Encoder *ctx = (GL2Encoder *)self;
785    if (ctx->m_state == NULL) return;
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
795void 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
827void* GL2Encoder::recenterIndices(const void* src,
828                                  GLenum type,
829                                  GLsizei count,
830                                  int minIndex) {
831
832    void* adjustedIndices = (void*)src;
833
834    if (minIndex != 0) {
835        adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count);
836        switch(type) {
837        case GL_BYTE:
838        case GL_UNSIGNED_BYTE:
839            GLUtils::shiftIndicesExcept(
840                    (unsigned char *)src,
841                    (unsigned char *)adjustedIndices,
842                    count, -minIndex,
843                    m_primitiveRestartEnabled,
844                    (unsigned char)m_primitiveRestartIndex);
845            break;
846        case GL_SHORT:
847        case GL_UNSIGNED_SHORT:
848            GLUtils::shiftIndicesExcept(
849                    (unsigned short *)src,
850                    (unsigned short *)adjustedIndices,
851                    count, -minIndex,
852                    m_primitiveRestartEnabled,
853                    (unsigned short)m_primitiveRestartIndex);
854            break;
855        case GL_INT:
856        case GL_UNSIGNED_INT:
857            GLUtils::shiftIndicesExcept(
858                    (unsigned int *)src,
859                    (unsigned int *)adjustedIndices,
860                    count, -minIndex,
861                    m_primitiveRestartEnabled,
862                    (unsigned int)m_primitiveRestartIndex);
863            break;
864        default:
865            ALOGE("unsupported index buffer type %d\n", type);
866        }
867    }
868
869    return adjustedIndices;
870}
871
872void GL2Encoder::getBufferIndexRange(BufferData* buf,
873                                     const void* dataWithOffset,
874                                     GLenum type,
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
898void GL2Encoder::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) const {
899    if (hasClientArrays) *hasClientArrays = false;
900    if (hasVBOs) *hasVBOs = false;
901
902    for (int i = 0; i < m_state->nLocations(); i++) {
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
917void 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
1019void 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
1030static 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
1046void 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
1070void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
1071{
1072
1073    GL2Encoder *ctx = (GL2Encoder *)self;
1074    assert(ctx->m_state != NULL);
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
1161GLint * GL2Encoder::getCompressedTextureFormats()
1162{
1163    if (m_compressedTextureFormats == NULL) {
1164        this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
1165                            &m_num_compressedTextureFormats);
1166        if (m_num_compressedTextureFormats > 0) {
1167            // get number of texture formats;
1168            m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
1169            this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
1170        }
1171    }
1172    return m_compressedTextureFormats;
1173}
1174
1175// Replace uses of samplerExternalOES with sampler2D, recording the names of
1176// modified shaders in data. Also remove
1177//   #extension GL_OES_EGL_image_external : require
1178// statements.
1179//
1180// This implementation assumes the input has already been pre-processed. If not,
1181// a few cases will be mishandled:
1182//
1183// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
1184//    the following code:
1185//      #if 1
1186//      uniform sampler2D mySampler;
1187//      #else
1188//      uniform samplerExternalOES mySampler;
1189//      #endif
1190//
1191// 2. Comments that look like sampler declarations will be incorrectly modified
1192//    and recorded:
1193//      // samplerExternalOES hahaFooledYou
1194//
1195// 3. However, GLSL ES does not have a concatentation operator, so things like
1196//    this (valid in C) are invalid and not a problem:
1197//      #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
1198//      SAMPLER(ExternalOES, mySampler);
1199//
1200static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
1201{
1202    static const char STR_HASH_EXTENSION[] = "#extension";
1203    static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
1204    static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
1205    static const char STR_SAMPLER2D_SPACE[]      = "sampler2D         ";
1206
1207    // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
1208    char* c = str;
1209    while ((c = strstr(c, STR_HASH_EXTENSION))) {
1210        char* start = c;
1211        c += sizeof(STR_HASH_EXTENSION)-1;
1212        while (isspace(*c) && *c != '\0') {
1213            c++;
1214        }
1215        if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
1216                sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
1217        {
1218            // #extension statements are terminated by end of line
1219            c = start;
1220            while (*c != '\0' && *c != '\r' && *c != '\n') {
1221                *c++ = ' ';
1222            }
1223        }
1224    }
1225
1226    // -- replace "samplerExternalOES" with "sampler2D" and record name
1227    c = str;
1228    while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
1229        // Make sure "samplerExternalOES" isn't a substring of a larger token
1230        if (c == str || !isspace(*(c-1))) {
1231            c++;
1232            continue;
1233        }
1234        char* sampler_start = c;
1235        c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
1236        if (!isspace(*c) && *c != '\0') {
1237            continue;
1238        }
1239
1240        // capture sampler name
1241        while (isspace(*c) && *c != '\0') {
1242            c++;
1243        }
1244        if (!isalpha(*c) && *c != '_') {
1245            // not an identifier
1246            return false;
1247        }
1248        char* name_start = c;
1249        do {
1250            c++;
1251        } while (isalnum(*c) || *c == '_');
1252        data->samplerExternalNames.push_back(
1253                android::String8(name_start, c - name_start));
1254
1255        // memcpy instead of strcpy since we don't want the NUL terminator
1256        memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
1257    }
1258
1259    return true;
1260}
1261
1262void 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
1269void 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
1300void GL2Encoder::s_glFinish(void *self)
1301{
1302    GL2Encoder *ctx = (GL2Encoder *)self;
1303    ctx->glFinishRoundTrip(self);
1304}
1305
1306void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1307{
1308    GL2Encoder *ctx = (GL2Encoder *)self;
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
1346void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1347{
1348    GL2Encoder *ctx = (GL2Encoder*)self;
1349    ctx->m_glDeleteProgram_enc(self, program);
1350
1351    ctx->m_shared->deleteProgramData(program);
1352}
1353
1354void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1355{
1356    GL2Encoder *ctx = (GL2Encoder*)self;
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}
1364void 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
1375GLuint GL2Encoder::s_glCreateProgram(void * self)
1376{
1377    GL2Encoder *ctx = (GL2Encoder*)self;
1378    GLuint program = ctx->m_glCreateProgram_enc(self);
1379    if (program!=0)
1380        ctx->m_shared->addProgramData(program);
1381    return program;
1382}
1383
1384GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1385{
1386    GL2Encoder *ctx = (GL2Encoder*)self;
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
1398void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1399        GLsizei* count, GLuint* shaders)
1400{
1401    GL2Encoder *ctx = (GL2Encoder*)self;
1402    SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1403    ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1404}
1405
1406void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1407            GLsizei* length, GLchar* source)
1408{
1409    GL2Encoder *ctx = (GL2Encoder*)self;
1410    SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1411    ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
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
1428void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1429        GLsizei* length, GLchar* infolog)
1430{
1431    GL2Encoder *ctx = (GL2Encoder*)self;
1432    SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1433    ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1434}
1435
1436void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1437        GLsizei* length, GLchar* infolog)
1438{
1439    GL2Encoder *ctx = (GL2Encoder*)self;
1440    SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1441    ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1442}
1443
1444void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1445{
1446    GL2Encoder *ctx = (GL2Encoder*)self;
1447    ctx->m_glDeleteShader_enc(self,shader);
1448    ctx->m_shared->unrefShaderData(shader);
1449}
1450
1451void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1452{
1453    GL2Encoder *ctx = (GL2Encoder*)self;
1454    ctx->m_glAttachShader_enc(self, program, shader);
1455    ctx->m_shared->attachShader(program, shader);
1456}
1457
1458void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1459{
1460    GL2Encoder *ctx = (GL2Encoder*)self;
1461    ctx->m_glDetachShader_enc(self, program, shader);
1462    ctx->m_shared->detachShader(program, shader);
1463}
1464
1465int 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
1478int 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
1501bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1502{
1503    if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1504        return false;
1505
1506    m_state->setActiveTextureUnit(texUnit);
1507
1508    GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1509    if (newTarget != oldTarget) {
1510        if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1511            m_state->disableTextureTarget(GL_TEXTURE_2D);
1512            m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1513        } else {
1514            m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1515            m_state->enableTextureTarget(GL_TEXTURE_2D);
1516        }
1517        m_glActiveTexture_enc(this, texUnit);
1518        m_glBindTexture_enc(this, GL_TEXTURE_2D,
1519                m_state->getBoundTexture(newTarget));
1520        return true;
1521    }
1522
1523    return false;
1524}
1525
1526void 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
1551void 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
1566void 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
1573void 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
1580void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1581{
1582    GL2Encoder *ctx = (GL2Encoder*)self;
1583    GLClientState* state = ctx->m_state;
1584    GLSharedGroupPtr shared = ctx->m_shared;
1585
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
1599void 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
1606void 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
1613void 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
1620void 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
1627void 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
1634void 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
1641void 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
1648void 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
1655void 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
1662void 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
1669void 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
1676void 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
1683void 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
1690void 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
1697void 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
1704void 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
1711void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1712{
1713    GL2Encoder* ctx = (GL2Encoder*)self;
1714    GLClientState* state = ctx->m_state;
1715    GLenum err;
1716
1717    SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1718
1719    ctx->m_glActiveTexture_enc(ctx, texture);
1720}
1721
1722void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1723{
1724    GL2Encoder* ctx = (GL2Encoder*)self;
1725    GLClientState* state = ctx->m_state;
1726    GLenum err;
1727    GLboolean firstUse;
1728
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
1759void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1760{
1761    GL2Encoder* ctx = (GL2Encoder*)self;
1762    GLClientState* state = ctx->m_state;
1763
1764    state->deleteTextures(n, textures);
1765    ctx->m_glDeleteTextures_enc(ctx, n, textures);
1766}
1767
1768void GL2Encoder::s_glGetTexParameterfv(void* self,
1769        GLenum target, GLenum pname, GLfloat* params)
1770{
1771    GL2Encoder* ctx = (GL2Encoder*)self;
1772    const GLClientState* state = ctx->m_state;
1773
1774    if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1775        ctx->override2DTextureTarget(target);
1776        ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
1777        ctx->restore2DTextureTarget(target);
1778    } else {
1779        ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1780    }
1781}
1782
1783void GL2Encoder::s_glGetTexParameteriv(void* self,
1784        GLenum target, GLenum pname, GLint* params)
1785{
1786    GL2Encoder* ctx = (GL2Encoder*)self;
1787    const GLClientState* state = ctx->m_state;
1788
1789    switch (pname) {
1790    case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1791        *params = 1;
1792        break;
1793
1794    default:
1795        if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1796            ctx->override2DTextureTarget(target);
1797            ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
1798            ctx->restore2DTextureTarget(target);
1799        } else {
1800            ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1801        }
1802        break;
1803    }
1804}
1805
1806static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1807{
1808    switch (pname) {
1809    case GL_TEXTURE_MIN_FILTER:
1810    case GL_TEXTURE_MAG_FILTER:
1811        return param == GL_NEAREST || param == GL_LINEAR;
1812
1813    case GL_TEXTURE_WRAP_S:
1814    case GL_TEXTURE_WRAP_T:
1815        return param == GL_CLAMP_TO_EDGE;
1816
1817    default:
1818        return true;
1819    }
1820}
1821
1822void GL2Encoder::s_glTexParameterf(void* self,
1823        GLenum target, GLenum pname, GLfloat param)
1824{
1825    GL2Encoder* ctx = (GL2Encoder*)self;
1826    const GLClientState* state = ctx->m_state;
1827
1828    SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1829            !isValidTextureExternalParam(pname, (GLenum)param)),
1830            GL_INVALID_ENUM);
1831
1832    if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1833        ctx->override2DTextureTarget(target);
1834        ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
1835        ctx->restore2DTextureTarget(target);
1836    } else {
1837        ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1838    }
1839}
1840
1841void GL2Encoder::s_glTexParameterfv(void* self,
1842        GLenum target, GLenum pname, const GLfloat* params)
1843{
1844    GL2Encoder* ctx = (GL2Encoder*)self;
1845    const GLClientState* state = ctx->m_state;
1846
1847    SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1848            !isValidTextureExternalParam(pname, (GLenum)params[0])),
1849            GL_INVALID_ENUM);
1850
1851    if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1852        ctx->override2DTextureTarget(target);
1853        ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
1854        ctx->restore2DTextureTarget(target);
1855    } else {
1856        ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1857    }
1858}
1859
1860void GL2Encoder::s_glTexParameteri(void* self,
1861        GLenum target, GLenum pname, GLint param)
1862{
1863    GL2Encoder* ctx = (GL2Encoder*)self;
1864    const GLClientState* state = ctx->m_state;
1865
1866    SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1867            !isValidTextureExternalParam(pname, (GLenum)param)),
1868            GL_INVALID_ENUM);
1869
1870    if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1871        ctx->override2DTextureTarget(target);
1872        ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
1873        ctx->restore2DTextureTarget(target);
1874    } else {
1875        ctx->m_glTexParameteri_enc(ctx, target, pname, param);
1876    }
1877}
1878
1879static int ilog2(uint32_t x) {
1880    int p = 0;
1881    while ((1 << p) < x)
1882        p++;
1883    return p;
1884}
1885
1886void 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
1965void 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
2034void 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
2063void 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
2082bool 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
2087void 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
2095void 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
2104void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2105    m_state->setBoundEGLImage(target, eglImage);
2106}
2107
2108
2109GLuint GL2Encoder::boundBuffer(GLenum target) const {
2110    return m_state->getBuffer(target);
2111}
2112
2113BufferData* GL2Encoder::getBufferData(GLenum target) const {
2114    GLuint bufferId = m_state->getBuffer(target);
2115    if (!bufferId) return NULL;
2116    return m_shared->getBufferData(bufferId);
2117}
2118
2119BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2120    if (!bufferId) return NULL;
2121    return m_shared->getBufferData(bufferId);
2122}
2123
2124bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2125    return m_shared->getBufferData(buffer)->m_mapped;
2126}
2127
2128bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2129    BufferData* buf = getBufferData(target);
2130    if (!buf) return false;
2131    return buf->m_mapped;
2132}
2133
2134void GL2Encoder::s_glGenRenderbuffers(void* self,
2135        GLsizei n, GLuint* renderbuffers) {
2136    GL2Encoder* ctx = (GL2Encoder*)self;
2137    GLClientState* state = ctx->m_state;
2138
2139    SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2140
2141    ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2142    state->addRenderbuffers(n, renderbuffers);
2143}
2144
2145void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2146        GLsizei n, const GLuint* renderbuffers) {
2147    GL2Encoder* ctx = (GL2Encoder*)self;
2148    GLClientState* state = ctx->m_state;
2149
2150    SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2151
2152    ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
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
2168void GL2Encoder::s_glBindRenderbuffer(void* self,
2169        GLenum target, GLuint renderbuffer) {
2170    GL2Encoder* ctx = (GL2Encoder*)self;
2171    GLClientState* state = ctx->m_state;
2172
2173    SET_ERROR_IF((target != GL_RENDERBUFFER),
2174                 GL_INVALID_ENUM);
2175
2176    ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2177    state->bindRenderbuffer(target, renderbuffer);
2178}
2179
2180void 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
2198void 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
2211void GL2Encoder::s_glGenFramebuffers(void* self,
2212        GLsizei n, GLuint* framebuffers) {
2213    GL2Encoder* ctx = (GL2Encoder*)self;
2214    GLClientState* state = ctx->m_state;
2215
2216    SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2217
2218    ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2219    state->addFramebuffers(n, framebuffers);
2220}
2221
2222void GL2Encoder::s_glDeleteFramebuffers(void* self,
2223        GLsizei n, const GLuint* framebuffers) {
2224    GL2Encoder* ctx = (GL2Encoder*)self;
2225    GLClientState* state = ctx->m_state;
2226
2227    SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2228
2229    ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2230    state->removeFramebuffers(n, framebuffers);
2231}
2232
2233void GL2Encoder::s_glBindFramebuffer(void* self,
2234        GLenum target, GLuint framebuffer) {
2235    GL2Encoder* ctx = (GL2Encoder*)self;
2236    GLClientState* state = ctx->m_state;
2237
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
2245void GL2Encoder::s_glFramebufferTexture2D(void* self,
2246        GLenum target, GLenum attachment,
2247        GLenum textarget, GLuint texture, GLint level) {
2248    GL2Encoder* ctx = (GL2Encoder*)self;
2249    GLClientState* state = ctx->m_state;
2250
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
2258void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2259        GLenum target, GLenum attachment,
2260        GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2261    GL2Encoder* ctx = (GL2Encoder*)self;
2262    GLClientState* state = ctx->m_state;
2263
2264    state->attachTextureObject(target, attachment, texture);
2265
2266    ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2267}
2268
2269void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2270        GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2271    GL2Encoder* ctx = (GL2Encoder*)self;
2272    const GLClientState* state = ctx->m_state;
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
2298bool 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
2386bool 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
2399GLenum 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
2418void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2419    GL2Encoder* ctx = (GL2Encoder*)self;
2420    GLClientState* state = ctx->m_state;
2421    SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2422
2423    ctx->m_glGenVertexArrays_enc(self, n, arrays);
2424    for (int i = 0; i < n; i++) {
2425        ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2426    }
2427    state->addVertexArrayObjects(n, arrays);
2428}
2429
2430void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2431    GL2Encoder* ctx = (GL2Encoder*)self;
2432    GLClientState* state = ctx->m_state;
2433    SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2434
2435    ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2436    for (int i = 0; i < n; i++) {
2437        ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2438    }
2439    state->removeVertexArrayObjects(n, arrays);
2440}
2441
2442void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2443    ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2444    GL2Encoder* ctx = (GL2Encoder*)self;
2445    GLClientState* state = ctx->m_state;
2446    SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2447    ctx->m_glBindVertexArray_enc(self, array);
2448    state->setVertexArrayObject(array);
2449}
2450
2451void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2452    GL2Encoder* ctx = (GL2Encoder*)self;
2453    GLClientState* state = ctx->m_state;
2454
2455    // begin validation (lots)
2456
2457    RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2458
2459    GLuint boundBuffer = ctx->m_state->getBuffer(target);
2460
2461    RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2462
2463    BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2464    RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2465
2466    GLsizeiptr bufferDataSize = buf->m_size;
2467
2468    RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2469    RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2470    RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2471    RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2472
2473    RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2474    RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2475    RET_AND_SET_ERROR_IF(
2476        (access & GL_MAP_READ_BIT) &&
2477             ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2478              (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2479              (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2480              (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2481
2482    // end validation; actually do stuff now
2483
2484    buf->m_mapped = true;
2485    buf->m_mappedAccess = access;
2486    buf->m_mappedOffset = offset;
2487    buf->m_mappedLength = length;
2488
2489    char* todo = (char*)buf->m_fixedBuffer.ptr() + offset;
2490    ctx->glMapBufferRangeAEMU(
2491            ctx, target,
2492            offset, length,
2493            access,
2494            todo);
2495
2496    return todo;
2497}
2498
2499GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
2500    GL2Encoder* ctx = (GL2Encoder*)self;
2501    GLClientState* state = ctx->m_state;
2502
2503    RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
2504
2505    GLuint boundBuffer = ctx->m_state->getBuffer(target);
2506
2507    RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
2508
2509    BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2510    RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
2511    RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
2512
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
2540void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
2541    GL2Encoder* ctx = (GL2Encoder*)self;
2542    GLClientState* state = ctx->m_state;
2543
2544    SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2545
2546    GLuint boundBuffer = ctx->m_state->getBuffer(target);
2547    SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
2548
2549    BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2550    SET_ERROR_IF(!buf, GL_INVALID_VALUE);
2551    SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
2552    SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
2553
2554    SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
2555    SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
2556    SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
2557
2558    GLintptr totalOffset = buf->m_mappedOffset + offset;
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
2570void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
2571    GL2Encoder* ctx = (GL2Encoder*)self;
2572    GLClientState* state = ctx->m_state;
2573
2574    SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2575    // Filter compressed formats support.
2576    SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
2577    // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
2578    GLint max_texture_size;
2579    GLint max_cube_map_texture_size;
2580    ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2581    ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2582    SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2583    SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2584    SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2585    SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2586    SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2587    SET_ERROR_IF(border, GL_INVALID_VALUE);
2588    // If unpack buffer is nonzero, verify unmapped state.
2589    SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2590    SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2591    // If unpack buffer is nonzero, verify buffer data fits.
2592    SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2593                 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2594                 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2595                 GL_INVALID_OPERATION);
2596    // TODO: Fix:
2597    // If |imageSize| is inconsistent with compressed dimensions.
2598    // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
2599
2600    GLenum stateTarget = target;
2601    if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2602        target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2603        target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2604        target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2605        target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2606        target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2607        stateTarget = GL_TEXTURE_CUBE_MAP;
2608    state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
2609    state->setBoundTextureDims(stateTarget, level, width, height, 1);
2610
2611    if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2612        ctx->glCompressedTexImage2DOffsetAEMU(
2613                ctx, target, level, internalformat,
2614                width, height, border,
2615                imageSize, (uintptr_t)data);
2616    } else {
2617        ctx->m_glCompressedTexImage2D_enc(
2618                ctx, target, level, internalformat,
2619                width, height, border,
2620                imageSize, data);
2621    }
2622}
2623
2624void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
2625    GL2Encoder* ctx = (GL2Encoder*)self;
2626    GLClientState* state = ctx->m_state;
2627
2628    SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2629    // If unpack buffer is nonzero, verify unmapped state.
2630    SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2631    GLint max_texture_size;
2632    GLint max_cube_map_texture_size;
2633    ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2634    ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2635    SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2636    SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2637    SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2638    SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2639    // If unpack buffer is nonzero, verify buffer data fits.
2640    SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2641                 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2642                 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2643                 GL_INVALID_OPERATION);
2644    SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2645
2646    if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2647        ctx->glCompressedTexSubImage2DOffsetAEMU(
2648                ctx, target, level,
2649                xoffset, yoffset,
2650                width, height, format,
2651                imageSize, (uintptr_t)data);
2652    } else {
2653        ctx->m_glCompressedTexSubImage2D_enc(
2654                ctx, target, level,
2655                xoffset, yoffset,
2656                width, height, format,
2657                imageSize, data);
2658    }
2659}
2660
2661void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
2662    GL2Encoder* ctx = (GL2Encoder*)self;
2663    GLClientState* state = ctx->m_state;
2664
2665    SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2666
2667    // Only works with certain targets
2668    SET_ERROR_IF(
2669        !(target == GL_ATOMIC_COUNTER_BUFFER ||
2670          target == GL_SHADER_STORAGE_BUFFER ||
2671          target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2672          target == GL_UNIFORM_BUFFER),
2673        GL_INVALID_ENUM);
2674
2675    // Can't exceed range
2676    SET_ERROR_IF(index < 0 ||
2677                 index >= state->getMaxIndexedBufferBindings(target),
2678                 GL_INVALID_VALUE);
2679    SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
2680    SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
2681                  target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
2682                 (size % 4 || offset % 4),
2683                 GL_INVALID_VALUE);
2684
2685    GLint ssbo_offset_align, ubo_offset_align;
2686    ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
2687    ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
2688    SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
2689                 offset % ssbo_offset_align,
2690                 GL_INVALID_VALUE);
2691    SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
2692                 offset % ubo_offset_align,
2693                 GL_INVALID_VALUE);
2694
2695    state->bindBuffer(target, buffer);
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
2701void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
2702    GL2Encoder* ctx = (GL2Encoder*)self;
2703    GLClientState* state = ctx->m_state;
2704
2705    SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2706
2707    // Only works with certain targets
2708    SET_ERROR_IF(
2709        !(target == GL_ATOMIC_COUNTER_BUFFER ||
2710          target == GL_SHADER_STORAGE_BUFFER ||
2711          target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2712          target == GL_UNIFORM_BUFFER),
2713        GL_INVALID_ENUM);
2714    // Can't exceed range
2715    SET_ERROR_IF(index < 0 ||
2716                 index >= state->getMaxIndexedBufferBindings(target),
2717                 GL_INVALID_VALUE);
2718
2719    state->bindBuffer(target, buffer);
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
2726void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
2727    GL2Encoder* ctx = (GL2Encoder*)self;
2728    GLClientState* state = ctx->m_state;
2729
2730    SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
2731    SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
2732    SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
2733                  readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
2734                  readtarget == GL_DRAW_INDIRECT_BUFFER ||
2735                  readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2736    SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
2737                  writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
2738                  writetarget == GL_DRAW_INDIRECT_BUFFER ||
2739                  writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2740    SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
2741    SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
2742    SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
2743    SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
2744    SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
2745    SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
2746    SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
2747    SET_ERROR_IF(
2748        ctx->getBufferData(readtarget) &&
2749        (readoffset + size > ctx->getBufferData(readtarget)->m_size),
2750        GL_INVALID_VALUE);
2751    SET_ERROR_IF(
2752        ctx->getBufferData(writetarget) &&
2753        (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
2754        GL_INVALID_VALUE);
2755    SET_ERROR_IF(readtarget == writetarget &&
2756                 !((writeoffset >= readoffset + size) ||
2757                   (readoffset >= writeoffset + size)),
2758                 GL_INVALID_VALUE);
2759
2760    ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
2761}
2762
2763void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
2764    GL2Encoder* ctx = (GL2Encoder*)self;
2765
2766    SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2767    SET_ERROR_IF(
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
2815void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
2816    GL2Encoder* ctx = (GL2Encoder*)self;
2817
2818    SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2819    SET_ERROR_IF(
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
2867void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
2868    GL2Encoder* ctx = (GL2Encoder*)self;
2869    SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2870    SET_ERROR_IF(
2871        target == GL_ATOMIC_COUNTER_BUFFER ||
2872        target == GL_DISPATCH_INDIRECT_BUFFER ||
2873        target == GL_DRAW_INDIRECT_BUFFER ||
2874        target == GL_SHADER_STORAGE_BUFFER,
2875        GL_INVALID_ENUM);
2876    SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
2877    SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
2878    if (!params) return;
2879
2880    BufferData* buf = ctx->getBufferData(target);
2881
2882    if (!buf || !buf->m_mapped) { *params = NULL; return; }
2883
2884    *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
2885}
2886
2887static const char* const kNameDelimiter = ";";
2888
2889static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
2890
2891#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
2892
2893    std::string packed;
2894    // validate the array of char[]'s
2895    const char* currName;
2896    for (GLsizei i = 0; i < count; i++) {
2897        currName = names[i];
2898        VALIDATE(!currName, GL_INVALID_OPERATION);
2899        // check if has reasonable size
2900        size_t len = strlen(currName);
2901        VALIDATE(!len, GL_INVALID_OPERATION);
2902        // check for our delimiter, which if present
2903        // in the name, means an invalid name anyway.
2904        VALIDATE(strstr(currName, kNameDelimiter),
2905                 GL_INVALID_OPERATION);
2906        packed += currName;
2907        packed += ";";
2908    }
2909
2910    *err_out = GL_NO_ERROR;
2911    return packed;
2912}
2913
2914void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
2915    GL2Encoder* ctx = (GL2Encoder*)self;
2916
2917    if (!uniformCount) return;
2918
2919    GLint err = GL_NO_ERROR;
2920    std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
2921    SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
2922
2923    bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
2924    std::vector<int> arrIndices;
2925    for (size_t i = 0; i < uniformCount; i++) {
2926        int err;
2927        arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
2928        if (err) {
2929            ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
2930            return;
2931        }
2932    }
2933
2934    ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
2935
2936    for (int i = 0; i < uniformCount; i++) {
2937        if (uniformIndices[i] >= 0 && needLocationWAR) {
2938            uniformIndices[i] =
2939                ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
2940        }
2941    }
2942}
2943
2944void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
2945    GL2Encoder *ctx = (GL2Encoder*)self;
2946    GLClientState* state = ctx->m_state;
2947    GLSharedGroupPtr shared = ctx->m_shared;
2948
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
2962void 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
2968void 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
2974void 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
2980void 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
2986void 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
2992void 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
2998void 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
3004void 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
3010void 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
3016void 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
3022void 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
3028void 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
3034void 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
3040void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3041    GL2Encoder *ctx = (GL2Encoder*)self;
3042    SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3043    SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3044    SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3045    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3046    SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3047    ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3048}
3049
3050void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3051    GL2Encoder* ctx = (GL2Encoder*)self;
3052    GLClientState* state = ctx->m_state;
3053
3054    // refresh client state's # active uniforms in this block
3055    if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3056        // TODO if worth it: cache uniform count and other params,
3057        // invalidate on program relinking.
3058        GLint numActiveUniforms;
3059        ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3060                program, uniformBlockIndex,
3061                GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3062                &numActiveUniforms);
3063        ctx->m_state->setNumActiveUniformsInUniformBlock(
3064                program, uniformBlockIndex, numActiveUniforms);
3065    }
3066
3067    ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3068            program, uniformBlockIndex,
3069            pname, params);
3070}
3071
3072void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3073    GL2Encoder *ctx = (GL2Encoder *)self;
3074    assert(ctx->m_state);
3075    GLint maxIndex;
3076    ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3077    SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3078
3079    if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3080        ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3081    }
3082}
3083
3084void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3085    GL2Encoder *ctx = (GL2Encoder *)self;
3086    assert(ctx->m_state);
3087    GLint maxIndex;
3088    ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3089    SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3090
3091    if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3092        ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3093    }
3094}
3095
3096void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3097    GL2Encoder *ctx = (GL2Encoder *)self;
3098    assert(ctx->m_state != NULL);
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
3127void 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
3136void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3137        GLenum target, GLsizei samples, GLenum internalformat,
3138        GLsizei width, GLsizei height) {
3139    GL2Encoder *ctx = (GL2Encoder *)self;
3140    GLClientState* state = ctx->m_state;
3141
3142    SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3143    SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3144
3145    GLint max_samples;
3146    ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3147    SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3148
3149    state->setBoundRenderbufferFormat(internalformat);
3150    state->setBoundRenderbufferSamples(samples);
3151    ctx->m_glRenderbufferStorageMultisample_enc(
3152            self, target, samples, internalformat, width, height);
3153}
3154
3155void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3156    GL2Encoder* ctx = (GL2Encoder*)self;
3157    SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3158    SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3159    for (int i = 0; i < n; i++) {
3160        SET_ERROR_IF(
3161            bufs[i] != GL_NONE &&
3162            bufs[i] != GL_BACK &&
3163            glUtilsColorAttachmentIndex(bufs[i]) == -1,
3164            GL_INVALID_ENUM);
3165        SET_ERROR_IF(
3166            !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3167            glUtilsColorAttachmentIndex(bufs[i]) != -1,
3168            GL_INVALID_OPERATION);
3169        SET_ERROR_IF(
3170            ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3171            ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3172              glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3173             (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3174              bufs[i] != GL_NONE)),
3175            GL_INVALID_OPERATION);
3176    }
3177
3178    ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3179}
3180
3181void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3182    GL2Encoder* ctx = (GL2Encoder*)self;
3183
3184    SET_ERROR_IF(
3185        glUtilsColorAttachmentIndex(src) != -1 &&
3186         (glUtilsColorAttachmentIndex(src) >=
3187         ctx->m_state->getMaxColorAttachments()),
3188        GL_INVALID_OPERATION);
3189    SET_ERROR_IF(
3190        src != GL_NONE &&
3191        src != GL_BACK &&
3192        src > GL_COLOR_ATTACHMENT0 &&
3193        src < GL_DEPTH_ATTACHMENT &&
3194        (src - GL_COLOR_ATTACHMENT0) >
3195        ctx->m_state->getMaxColorAttachments(),
3196        GL_INVALID_OPERATION);
3197    SET_ERROR_IF(
3198        src != GL_NONE &&
3199        src != GL_BACK &&
3200        glUtilsColorAttachmentIndex(src) == -1,
3201        GL_INVALID_ENUM);
3202    SET_ERROR_IF(
3203        !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3204        src != GL_NONE &&
3205        src != GL_BACK,
3206        GL_INVALID_OPERATION);
3207    SET_ERROR_IF(
3208        ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3209        src != GL_NONE &&
3210        glUtilsColorAttachmentIndex(src) == -1,
3211        GL_INVALID_OPERATION);
3212
3213    ctx->m_glReadBuffer_enc(ctx, src);
3214}
3215
3216void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3217    GL2Encoder* ctx = (GL2Encoder*)self;
3218    GLClientState* state = ctx->m_state;
3219
3220    SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3221    SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3222    GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3223    SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3224                 lastBoundTarget != GL_TEXTURE_3D,
3225                 GL_INVALID_OPERATION);
3226    state->attachTextureObject(target, attachment, texture);
3227
3228    GLint max3DTextureSize;
3229    ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3230    SET_ERROR_IF(
3231            layer >= max3DTextureSize,
3232            GL_INVALID_VALUE);
3233
3234    ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3235}
3236
3237void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3238    GL2Encoder* ctx = (GL2Encoder*)self;
3239    GLClientState* state = ctx->m_state;
3240
3241    SET_ERROR_IF(
3242        target != GL_TEXTURE_2D &&
3243        target != GL_TEXTURE_CUBE_MAP,
3244        GL_INVALID_ENUM);
3245    SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3246    SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3247    SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3248    SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3249                 GL_INVALID_OPERATION);
3250    SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3251
3252    state->setBoundTextureInternalFormat(target, internalformat);
3253    state->setBoundTextureDims(target, -1, width, height, 1);
3254    state->setBoundTextureImmutableFormat(target);
3255    ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
3256}
3257
3258void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3259    GL2Encoder* ctx = (GL2Encoder*)self;
3260
3261    SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3262
3263    GLint maxCount = 0;
3264    ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3265
3266    SET_ERROR_IF(
3267        bufferMode == GL_SEPARATE_ATTRIBS &&
3268        maxCount < count,
3269        GL_INVALID_VALUE);
3270    SET_ERROR_IF(
3271        bufferMode != GL_INTERLEAVED_ATTRIBS &&
3272        bufferMode != GL_SEPARATE_ATTRIBS,
3273        GL_INVALID_ENUM);
3274
3275    if (!count) return;
3276
3277    GLint err = GL_NO_ERROR;
3278    std::string packed = packVarNames(count, varyings, &err);
3279    SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3280
3281    ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3282}
3283
3284void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3285    GL2Encoder* ctx = (GL2Encoder*)self;
3286    GLClientState* state = ctx->m_state;
3287    ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3288    state->setTransformFeedbackActiveUnpaused(true);
3289}
3290
3291void GL2Encoder::s_glEndTransformFeedback(void* self) {
3292    GL2Encoder* ctx = (GL2Encoder*)self;
3293    GLClientState* state = ctx->m_state;
3294    ctx->m_glEndTransformFeedback_enc(ctx);
3295    state->setTransformFeedbackActiveUnpaused(false);
3296}
3297
3298void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3299    GL2Encoder* ctx = (GL2Encoder*)self;
3300    GLClientState* state = ctx->m_state;
3301    ctx->m_glPauseTransformFeedback_enc(ctx);
3302    state->setTransformFeedbackActiveUnpaused(false);
3303}
3304
3305void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3306    GL2Encoder* ctx = (GL2Encoder*)self;
3307    GLClientState* state = ctx->m_state;
3308    ctx->m_glResumeTransformFeedback_enc(ctx);
3309    state->setTransformFeedbackActiveUnpaused(true);
3310}
3311
3312void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3313                               GLsizei width, GLsizei height, GLsizei depth,
3314                               GLint border, GLenum format, GLenum type, const GLvoid* data) {
3315    GL2Encoder* ctx = (GL2Encoder*)self;
3316    GLClientState* state = ctx->m_state;
3317
3318    SET_ERROR_IF(target != GL_TEXTURE_3D &&
3319                 target != GL_TEXTURE_2D_ARRAY,
3320                 GL_INVALID_ENUM);
3321    SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3322    SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3323
3324    // If unpack buffer is nonzero, verify unmapped state.
3325    SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3326
3327    GLint max_texture_size;
3328    GLint max_3d_texture_size;
3329    ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3330    ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3331    SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3332    SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3333    SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3334
3335    SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3336    SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3337    SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3338    SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3339    SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3340    SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3341    SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3342    SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3343    // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3344    SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3345                 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3346                 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3347                  ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3348                 GL_INVALID_OPERATION);
3349    SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3350                 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3351                 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3352                  glSizeof(type)),
3353                 GL_INVALID_OPERATION);
3354    SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3355
3356    state->setBoundTextureInternalFormat(target, internalFormat);
3357    state->setBoundTextureFormat(target, format);
3358    state->setBoundTextureType(target, type);
3359    state->setBoundTextureDims(target, level, width, height, depth);
3360
3361    if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3362        ctx->glTexImage3DOffsetAEMU(
3363                ctx, target, level, internalFormat,
3364                width, height, depth,
3365                border, format, type, (uintptr_t)data);
3366    } else {
3367        ctx->m_glTexImage3D_enc(ctx,
3368                target, level, internalFormat,
3369                width, height, depth,
3370                border, format, type, data);
3371    }
3372}
3373
3374void GL2Encoder::s_glTexSubImage3D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* data) {
3375    GL2Encoder* ctx = (GL2Encoder*)self;
3376    GLClientState* state = ctx->m_state;
3377
3378    SET_ERROR_IF(target != GL_TEXTURE_3D &&
3379                 target != GL_TEXTURE_2D_ARRAY,
3380                 GL_INVALID_ENUM);
3381    SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3382    SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3383    // If unpack buffer is nonzero, verify unmapped state.
3384    SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3385    GLint max_texture_size;
3386    GLint max_3d_texture_size;
3387    ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3388    ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3389    SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3390    SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3391    SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3392    SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3393    SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3394    GLuint tex = state->getBoundTexture(target);
3395    GLsizei neededWidth = xoffset + width;
3396    GLsizei neededHeight = yoffset + height;
3397    GLsizei neededDepth = zoffset + depth;
3398
3399    SET_ERROR_IF(tex &&
3400                 (neededWidth > state->queryTexWidth(level, tex) ||
3401                  neededHeight > state->queryTexHeight(level, tex) ||
3402                  neededDepth > state->queryTexDepth(level, tex)),
3403                 GL_INVALID_VALUE);
3404    // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3405    SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3406                 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3407                 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3408                  ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3409                 GL_INVALID_OPERATION);
3410    SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3411                 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3412                 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3413                  glSizeof(type)),
3414                 GL_INVALID_OPERATION);
3415    SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
3416    SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3417
3418    if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3419        ctx->glTexSubImage3DOffsetAEMU(ctx,
3420                target, level,
3421                xoffset, yoffset, zoffset,
3422                width, height, depth,
3423                format, type, (uintptr_t)data);
3424    } else {
3425        ctx->m_glTexSubImage3D_enc(ctx,
3426                target, level,
3427                xoffset, yoffset, zoffset,
3428                width, height, depth,
3429                format, type, data);
3430    }
3431}
3432
3433void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
3434    GL2Encoder* ctx = (GL2Encoder*)self;
3435    GLClientState* state = ctx->m_state;
3436
3437    // Filter compressed formats support.
3438    SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3439    // If unpack buffer is nonzero, verify unmapped state.
3440    SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3441    SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3442    SET_ERROR_IF(border, GL_INVALID_VALUE);
3443    // If unpack buffer is nonzero, verify buffer data fits.
3444    SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3445                 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3446                 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3447                 GL_INVALID_OPERATION);
3448    // TODO: Fix:
3449    // If |imageSize| is too small for compressed dimensions.
3450    // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
3451    state->setBoundTextureInternalFormat(target, (GLint)internalformat);
3452    state->setBoundTextureDims(target, level, width, height, depth);
3453
3454    if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3455        ctx->glCompressedTexImage3DOffsetAEMU(
3456                ctx, target, level, internalformat,
3457                width, height, depth, border,
3458                imageSize, (uintptr_t)data);
3459    } else {
3460        ctx->m_glCompressedTexImage3D_enc(
3461                ctx, target, level, internalformat,
3462                width, height, depth, border,
3463                imageSize, data);
3464    }
3465}
3466
3467void GL2Encoder::s_glCompressedTexSubImage3D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) {
3468    GL2Encoder* ctx = (GL2Encoder*)self;
3469    GLClientState* state = ctx->m_state;
3470
3471    SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3472    // If unpack buffer is nonzero, verify unmapped state.
3473    SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3474    SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3475    // If unpack buffer is nonzero, verify buffer data fits.
3476    SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3477                 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3478                 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3479                 GL_INVALID_OPERATION);
3480    SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3481
3482    if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3483        ctx->glCompressedTexSubImage3DOffsetAEMU(
3484                ctx, target, level,
3485                xoffset, yoffset, zoffset,
3486                width, height, depth,
3487                format, imageSize, (uintptr_t)data);
3488    } else {
3489        ctx->m_glCompressedTexSubImage3D_enc(
3490                ctx, target, level,
3491                xoffset, yoffset, zoffset,
3492                width, height, depth,
3493                format, imageSize, data);
3494
3495    }
3496}
3497
3498void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
3499    GL2Encoder* ctx = (GL2Encoder*)self;
3500    GLClientState* state = ctx->m_state;
3501    SET_ERROR_IF(target != GL_TEXTURE_3D &&
3502                 target != GL_TEXTURE_2D_ARRAY,
3503                 GL_INVALID_ENUM);
3504    SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3505    SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3506    SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3507    SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
3508                 GL_INVALID_OPERATION);
3509    SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
3510                 GL_INVALID_OPERATION);
3511    SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3512
3513    state->setBoundTextureInternalFormat(target, internalformat);
3514    state->setBoundTextureDims(target, -1, width, height, depth);
3515    state->setBoundTextureImmutableFormat(target);
3516    ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
3517    state->setBoundTextureImmutableFormat(target);
3518}
3519
3520void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
3521    GL2Encoder *ctx = (GL2Encoder *)self;
3522    assert(ctx->m_state != NULL);
3523    SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3524    SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3525
3526    bool has_client_vertex_arrays = false;
3527    bool has_indirect_arrays = false;
3528    ctx->getVBOUsage(&has_client_vertex_arrays,
3529                     &has_indirect_arrays);
3530
3531    if (has_client_vertex_arrays ||
3532        (!has_client_vertex_arrays &&
3533         !has_indirect_arrays)) {
3534        ctx->sendVertexAttributes(first, count, true, primcount);
3535        ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
3536    } else {
3537        ctx->sendVertexAttributes(0, count, false, primcount);
3538        ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
3539    }
3540    ctx->m_stream->flush();
3541}
3542
3543void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
3544{
3545
3546    GL2Encoder *ctx = (GL2Encoder *)self;
3547    assert(ctx->m_state != NULL);
3548    SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3549    SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3550    SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3551    SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3552
3553    bool has_client_vertex_arrays = false;
3554    bool has_indirect_arrays = false;
3555    int nLocations = ctx->m_state->nLocations();
3556    GLintptr offset = 0;
3557
3558    ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3559
3560    if (!has_client_vertex_arrays && !has_indirect_arrays) {
3561        // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3562        GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3563        SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3564    }
3565
3566    BufferData* buf = NULL;
3567    int minIndex = 0, maxIndex = 0;
3568
3569    // For validation/immediate index array purposes,
3570    // we need the min/max vertex index of the index array.
3571    // If the VBO != 0, this may not be the first time we have
3572    // used this particular index buffer. getBufferIndexRange
3573    // can more quickly get min/max vertex index by
3574    // caching previous results.
3575    if (ctx->m_state->currentIndexVbo() != 0) {
3576        buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3577        offset = (GLintptr)indices;
3578        indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3579        ctx->getBufferIndexRange(buf,
3580                                 indices,
3581                                 type,
3582                                 (size_t)count,
3583                                 (size_t)offset,
3584                                 &minIndex, &maxIndex);
3585    } else {
3586        // In this case, the |indices| field holds a real
3587        // array, so calculate the indices now. They will
3588        // also be needed to know how much data to
3589        // transfer to host.
3590        ctx->calcIndexRange(indices,
3591                            type,
3592                            count,
3593                            &minIndex,
3594                            &maxIndex);
3595    }
3596
3597    bool adjustIndices = true;
3598    if (ctx->m_state->currentIndexVbo() != 0) {
3599        if (!has_client_vertex_arrays) {
3600            ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
3601            ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3602            ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
3603            ctx->flushDrawCall();
3604            adjustIndices = false;
3605        } else {
3606            BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3607            ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3608        }
3609    }
3610    if (adjustIndices) {
3611        void *adjustedIndices =
3612            ctx->recenterIndices(indices,
3613                                 type,
3614                                 count,
3615                                 minIndex);
3616
3617        if (has_indirect_arrays || 1) {
3618            ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
3619            ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
3620            ctx->m_stream->flush();
3621            // XXX - OPTIMIZATION (see the other else branch) should be implemented
3622            if(!has_indirect_arrays) {
3623                //ALOGD("unoptimized drawelements !!!\n");
3624            }
3625        } else {
3626            // we are all direct arrays and immidate mode index array -
3627            // rebuild the arrays and the index array;
3628            ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3629        }
3630    }
3631}
3632
3633void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
3634{
3635
3636    GL2Encoder *ctx = (GL2Encoder *)self;
3637    assert(ctx->m_state != NULL);
3638    SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3639    SET_ERROR_IF(end < start, GL_INVALID_VALUE);
3640    SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3641    SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3642    SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3643
3644    bool has_client_vertex_arrays = false;
3645    bool has_indirect_arrays = false;
3646    int nLocations = ctx->m_state->nLocations();
3647    GLintptr offset = 0;
3648
3649    ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3650
3651    if (!has_client_vertex_arrays && !has_indirect_arrays) {
3652        // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3653        GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3654        SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3655    }
3656
3657    BufferData* buf = NULL;
3658    int minIndex = 0, maxIndex = 0;
3659
3660    // For validation/immediate index array purposes,
3661    // we need the min/max vertex index of the index array.
3662    // If the VBO != 0, this may not be the first time we have
3663    // used this particular index buffer. getBufferIndexRange
3664    // can more quickly get min/max vertex index by
3665    // caching previous results.
3666    if (ctx->m_state->currentIndexVbo() != 0) {
3667        buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3668        offset = (GLintptr)indices;
3669        indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3670        ctx->getBufferIndexRange(buf,
3671                                 indices,
3672                                 type,
3673                                 (size_t)count,
3674                                 (size_t)offset,
3675                                 &minIndex, &maxIndex);
3676    } else {
3677        // In this case, the |indices| field holds a real
3678        // array, so calculate the indices now. They will
3679        // also be needed to know how much data to
3680        // transfer to host.
3681        ctx->calcIndexRange(indices,
3682                            type,
3683                            count,
3684                            &minIndex,
3685                            &maxIndex);
3686    }
3687
3688    bool adjustIndices = true;
3689    if (ctx->m_state->currentIndexVbo() != 0) {
3690        if (!has_client_vertex_arrays) {
3691            ctx->sendVertexAttributes(0, maxIndex + 1, false);
3692            ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3693            ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
3694            ctx->flushDrawCall();
3695            adjustIndices = false;
3696        } else {
3697            BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3698            ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3699        }
3700    }
3701    if (adjustIndices) {
3702        void *adjustedIndices =
3703            ctx->recenterIndices(indices,
3704                                 type,
3705                                 count,
3706                                 minIndex);
3707
3708        if (has_indirect_arrays || 1) {
3709            ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
3710            ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
3711            ctx->m_stream->flush();
3712            // XXX - OPTIMIZATION (see the other else branch) should be implemented
3713            if(!has_indirect_arrays) {
3714                //ALOGD("unoptimized drawelements !!!\n");
3715            }
3716        } else {
3717            // we are all direct arrays and immidate mode index array -
3718            // rebuild the arrays and the index array;
3719            ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3720        }
3721    }
3722}
3723
3724// struct GLStringKey {
3725//     GLenum name;
3726//     GLuint index;
3727// };
3728//
3729// struct GLStringKeyCompare {
3730//     bool operator() (const GLStringKey& a,
3731//                      const GLStringKey& b) const {
3732//         if (a.name != b.name) return a.name < b.name;
3733//         if (a.index != b.index) return a.index < b.index;
3734//         return false;
3735//     }
3736// };
3737//
3738// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
3739//
3740// static GLStringStore sGLStringStore;
3741// bool sGLStringStoreInitialized = false;
3742
3743const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
3744    GL2Encoder *ctx = (GL2Encoder *)self;
3745    GLubyte *retval =  (GLubyte *) "";
3746
3747    RET_AND_SET_ERROR_IF(
3748        name != GL_VENDOR &&
3749        name != GL_RENDERER &&
3750        name != GL_VERSION &&
3751        name != GL_EXTENSIONS,
3752        GL_INVALID_ENUM,
3753        retval);
3754
3755    RET_AND_SET_ERROR_IF(
3756        name == GL_VENDOR ||
3757        name == GL_RENDERER ||
3758        name == GL_VERSION ||
3759        name == GL_EXTENSIONS &&
3760        index != 0,
3761        GL_INVALID_VALUE,
3762        retval);
3763
3764    switch (name) {
3765    case GL_VENDOR:
3766        retval = gVendorString;
3767        break;
3768    case GL_RENDERER:
3769        retval = gRendererString;
3770        break;
3771    case GL_VERSION:
3772        retval = gVersionString;
3773        break;
3774    case GL_EXTENSIONS:
3775        retval = gExtensionsString;
3776        break;
3777    }
3778
3779    return retval;
3780}
3781
3782void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
3783    GL2Encoder *ctx = (GL2Encoder *)self;
3784
3785    SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3786
3787    GLint linkStatus = 0;
3788    ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
3789    GLint properLength = 0;
3790    ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
3791
3792    SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
3793    SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
3794
3795    ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
3796}
3797
3798void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
3799    GL2Encoder *ctx = (GL2Encoder *)self;
3800
3801    SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
3802    SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
3803    SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
3804    SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
3805    SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
3806                 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
3807                 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
3808                  ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
3809                 GL_INVALID_OPERATION);
3810    /*
3811GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is a fixed point normalized surface and format and type are neither GL_RGBA and GL_UNSIGNED_BYTE, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
3812
3813GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is a floating point surface and format and type are neither GL_RGBA and GL_FLOAT, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
3814
3815GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is a signed integer surface and format and type are neither GL_RGBA_INTEGER and GL_INT, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
3816
3817GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is an unsigned integer surface and format and type are neither GL_RGBA_INTEGER and GL_UNSIGNED_INT, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
3818*/
3819
3820    FboFormatInfo fbo_format_info;
3821    ctx->m_state->getBoundFramebufferFormat(
3822            GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
3823    SET_ERROR_IF(
3824        fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3825        !GLESv2Validation::readPixelsFboFormatMatch(
3826            format, type, fbo_format_info.tex_type),
3827        GL_INVALID_OPERATION);
3828
3829    if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
3830        ctx->glReadPixelsOffsetAEMU(
3831                ctx, x, y, width, height,
3832                format, type, (uintptr_t)pixels);
3833    } else {
3834        ctx->m_glReadPixels_enc(
3835                ctx, x, y, width, height,
3836                format, type, pixels);
3837    }
3838}
3839
3840// Track enabled state for some things like:
3841// - Primitive restart
3842void GL2Encoder::s_glEnable(void* self, GLenum what) {
3843    GL2Encoder *ctx = (GL2Encoder *)self;
3844
3845    switch (what) {
3846    case GL_PRIMITIVE_RESTART_FIXED_INDEX:
3847        ctx->m_primitiveRestartEnabled = true;
3848        break;
3849    }
3850
3851    ctx->m_glEnable_enc(ctx, what);
3852}
3853
3854void GL2Encoder::s_glDisable(void* self, GLenum what) {
3855    GL2Encoder *ctx = (GL2Encoder *)self;
3856
3857    switch (what) {
3858    case GL_PRIMITIVE_RESTART_FIXED_INDEX:
3859        ctx->m_primitiveRestartEnabled = false;
3860        break;
3861    }
3862
3863    ctx->m_glDisable_enc(ctx, what);
3864}
3865
3866void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
3867    GL2Encoder *ctx = (GL2Encoder *)self;
3868
3869    SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3870
3871    ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
3872}
3873
3874void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
3875    GL2Encoder *ctx = (GL2Encoder *)self;
3876
3877    SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3878
3879    ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
3880}
3881
3882void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
3883    GL2Encoder *ctx = (GL2Encoder *)self;
3884
3885    SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
3886
3887    ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
3888}
3889
3890void GL2Encoder::s_glBlitFramebuffer(void* self, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
3891    GL2Encoder *ctx = (GL2Encoder *)self;
3892    GLClientState* state = ctx->m_state;
3893
3894    bool validateColor = mask | GL_COLOR_BUFFER_BIT;
3895    bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
3896    bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
3897
3898    FboFormatInfo read_fbo_format_info;
3899    FboFormatInfo draw_fbo_format_info;
3900    if (validateColor) {
3901        state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
3902        state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
3903
3904        if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3905            draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
3906            SET_ERROR_IF(
3907                    state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3908                    state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3909                    !GLESv2Validation::blitFramebufferFormat(
3910                        read_fbo_format_info.tex_type,
3911                        draw_fbo_format_info.tex_type),
3912                    GL_INVALID_OPERATION);
3913        }
3914    }
3915
3916    if (validateDepth) {
3917        state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
3918        state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
3919
3920        if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3921            draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
3922            SET_ERROR_IF(
3923                    state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3924                    state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3925                    !GLESv2Validation::blitFramebufferFormat(
3926                        read_fbo_format_info.rb_format,
3927                        draw_fbo_format_info.rb_format),
3928                    GL_INVALID_OPERATION);
3929        }
3930    }
3931
3932    if (validateStencil) {
3933        state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
3934        state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
3935
3936        if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3937            draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
3938            SET_ERROR_IF(
3939                    state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3940                    state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3941                    !GLESv2Validation::blitFramebufferFormat(
3942                        read_fbo_format_info.rb_format,
3943                        draw_fbo_format_info.rb_format),
3944                    GL_INVALID_OPERATION);
3945        }
3946    }
3947
3948    state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
3949    SET_ERROR_IF(
3950            draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3951            draw_fbo_format_info.rb_multisamples > 0,
3952            GL_INVALID_OPERATION);
3953    SET_ERROR_IF(
3954            draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3955            draw_fbo_format_info.tex_multisamples > 0,
3956            GL_INVALID_OPERATION);
3957
3958    state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
3959    SET_ERROR_IF(
3960            read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3961            read_fbo_format_info.rb_multisamples > 0 &&
3962            draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3963            state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3964            state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3965            (read_fbo_format_info.rb_format !=
3966             draw_fbo_format_info.rb_format),
3967            GL_INVALID_OPERATION);
3968    SET_ERROR_IF(
3969            read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3970            read_fbo_format_info.rb_multisamples > 0 &&
3971            draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
3972            (srcX0 != dstX0 || srcY0 != dstY0 ||
3973             srcX1 != dstX1 || srcY1 != dstY1),
3974            GL_INVALID_OPERATION);
3975
3976	ctx->m_glBlitFramebuffer_enc(ctx,
3977            srcX0, srcY0, srcX1, srcY1,
3978            dstX0, dstY0, dstX1, dstY1,
3979            mask, filter);
3980}
3981
3982void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
3983    GL2Encoder *ctx = (GL2Encoder *)self;
3984
3985    SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
3986                 pname != GL_SAMPLES,
3987                 GL_INVALID_ENUM);
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
4014void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
4015    GL2Encoder *ctx = (GL2Encoder *)self;
4016    GLClientState* state = ctx->m_state;
4017
4018    SET_ERROR_IF(target != GL_TEXTURE_2D &&
4019                 target != GL_TEXTURE_3D &&
4020                 target != GL_TEXTURE_CUBE_MAP,
4021                 GL_INVALID_ENUM);
4022
4023    GLuint tex = state->getBoundTexture(target);
4024    GLenum internalformat = state->queryTexInternalFormat(tex);
4025    GLenum format = state->queryTexFormat(tex);
4026
4027    SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
4028                 GL_INVALID_OPERATION);
4029    SET_ERROR_IF(tex &&
4030                 !GLESv2Validation::unsizedFormat(internalformat) &&
4031                 !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4032                   GLESv2Validation::filterableTexFormat(ctx, internalformat)),
4033                 GL_INVALID_OPERATION);
4034
4035    ctx->m_glGenerateMipmap_enc(ctx, target);
4036}
4037
4038void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4039    GL2Encoder *ctx = (GL2Encoder *)self;
4040    GLint maxCombinedUnits;
4041    ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4042    SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4043
4044    ctx->m_glBindSampler_enc(ctx, unit, sampler);
4045}
4046
4047GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4048    GL2Encoder *ctx = (GL2Encoder *)self;
4049    uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4050    return (GLsync)(uintptr_t)syncHandle;
4051}
4052
4053GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4054    GL2Encoder *ctx = (GL2Encoder *)self;
4055    return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4056}
4057
4058void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4059    GL2Encoder *ctx = (GL2Encoder *)self;
4060    ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4061}
4062
4063void 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
4071GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4072    GL2Encoder *ctx = (GL2Encoder *)self;
4073    return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4074}
4075
4076void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4077    GL2Encoder *ctx = (GL2Encoder *)self;
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
4090void 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
4139void 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
4188void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4189    GL2Encoder *ctx = (GL2Encoder *)self;
4190    ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4191    if (pname == GL_SHADER_SOURCE_LENGTH) {
4192        ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4193        if (shaderData) {
4194            int totalLen = 0;
4195            for (int i = 0; i < shaderData->sources.size(); i++) {
4196                totalLen += shaderData->sources[i].size();
4197            }
4198            if (totalLen != 0) {
4199                *params = totalLen + 1; // account for null terminator
4200            }
4201        }
4202    }
4203}
4204
4205void 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
4220GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4221
4222    GLint* length = NULL;
4223    GL2Encoder* ctx = (GL2Encoder*)self;
4224
4225    int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
4226    char *str = new char[len + 1];
4227    glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
4228
4229    // Do GLSharedGroup and location WorkARound-specific initialization
4230    // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4231    uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4232    ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
4233    ShaderData* sData = spData->shaderData;
4234
4235    if (!replaceSamplerExternalWith2D(str, sData)) {
4236        delete [] str;
4237        ctx->setError(GL_OUT_OF_MEMORY);
4238        ctx->m_shared->deleteShaderProgramDataById(spDataId);
4239        return -1;
4240    }
4241
4242    GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
4243    delete [] str;
4244
4245    // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4246    GLint linkStatus = 0;
4247    ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4248    if (!linkStatus) {
4249        ctx->m_shared->deleteShaderProgramDataById(spDataId);
4250        return -1;
4251    }
4252
4253    ctx->m_shared->associateGLShaderProgram(res, spDataId);
4254
4255    GLint numUniforms = 0;
4256    ctx->glGetProgramiv(ctx, res, GL_ACTIVE_UNIFORMS, &numUniforms);
4257    ctx->m_shared->initShaderProgramData(res, numUniforms);
4258
4259    GLint maxLength=0;
4260    ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4261
4262    GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4263
4264    for (GLint i = 0; i < numUniforms; ++i) {
4265        ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4266        GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4267        ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4268    }
4269
4270    ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4271
4272    delete [] name;
4273
4274    return res;
4275}
4276
4277void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4278{
4279    GL2Encoder *ctx = (GL2Encoder*)self;
4280    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4281    ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4282}
4283
4284void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4285{
4286    GL2Encoder *ctx = (GL2Encoder*)self;
4287    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4288    ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4289}
4290
4291void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4292{
4293    GL2Encoder *ctx = (GL2Encoder*)self;
4294    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
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
4310void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4311{
4312    GL2Encoder *ctx = (GL2Encoder*)self;
4313    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4314    ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4315}
4316
4317void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4318{
4319    GL2Encoder *ctx = (GL2Encoder*)self;
4320    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4321    ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4322
4323    GLClientState* state = ctx->m_state;
4324    GLSharedGroupPtr shared = ctx->m_shared;
4325    GLenum target;
4326
4327    if (shared->setSamplerUniform(program, location, v0, &target)) {
4328        GLenum origActiveTexture = state->getActiveTextureUnit();
4329        if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4330            ctx->m_glActiveTexture_enc(self, origActiveTexture);
4331        }
4332        state->setActiveTextureUnit(origActiveTexture);
4333    }
4334}
4335
4336void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4337{
4338    GL2Encoder *ctx = (GL2Encoder*)self;
4339    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4340    ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
4341}
4342
4343void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
4344{
4345    GL2Encoder *ctx = (GL2Encoder*)self;
4346    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4347    ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
4348}
4349
4350void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4351{
4352    GL2Encoder *ctx = (GL2Encoder*)self;
4353    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4354    ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
4355}
4356
4357void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
4358{
4359    GL2Encoder *ctx = (GL2Encoder*)self;
4360    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4361    ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
4362}
4363
4364void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4365{
4366    GL2Encoder *ctx = (GL2Encoder*)self;
4367    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4368    ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
4369}
4370
4371void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
4372{
4373    GL2Encoder *ctx = (GL2Encoder*)self;
4374    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4375    ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
4376}
4377
4378void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4379{
4380    GL2Encoder *ctx = (GL2Encoder*)self;
4381    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4382    ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
4383}
4384
4385void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
4386{
4387    GL2Encoder *ctx = (GL2Encoder*)self;
4388    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4389    ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
4390}
4391
4392void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4393{
4394    GL2Encoder *ctx = (GL2Encoder*)self;
4395    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4396    ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
4397}
4398
4399void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
4400{
4401    GL2Encoder *ctx = (GL2Encoder*)self;
4402    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4403    ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
4404}
4405
4406void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4407{
4408    GL2Encoder *ctx = (GL2Encoder*)self;
4409    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4410    ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
4411}
4412
4413void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
4414{
4415    GL2Encoder *ctx = (GL2Encoder*)self;
4416    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4417    ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
4418}
4419
4420void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4421{
4422    GL2Encoder *ctx = (GL2Encoder*)self;
4423    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4424    ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
4425}
4426
4427void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
4428{
4429    GL2Encoder *ctx = (GL2Encoder*)self;
4430    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4431    ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
4432}
4433
4434void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4435{
4436    GL2Encoder *ctx = (GL2Encoder*)self;
4437    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4438    ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
4439}
4440
4441void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
4442{
4443    GL2Encoder *ctx = (GL2Encoder*)self;
4444    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4445    ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
4446}
4447
4448void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4449{
4450    GL2Encoder *ctx = (GL2Encoder*)self;
4451    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4452    ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
4453}
4454
4455void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
4456{
4457    GL2Encoder *ctx = (GL2Encoder*)self;
4458    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4459    ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
4460}
4461
4462void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4463{
4464    GL2Encoder *ctx = (GL2Encoder*)self;
4465    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4466    ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
4467}
4468
4469void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4470{
4471    GL2Encoder *ctx = (GL2Encoder*)self;
4472    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4473    ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
4474}
4475
4476void GL2Encoder::s_glProgramUniformMatrix2x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4477{
4478    GL2Encoder *ctx = (GL2Encoder*)self;
4479    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4480    ctx->m_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
4481}
4482
4483void GL2Encoder::s_glProgramUniformMatrix2x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4484{
4485    GL2Encoder *ctx = (GL2Encoder*)self;
4486    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4487    ctx->m_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
4488}
4489
4490void GL2Encoder::s_glProgramUniformMatrix3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4491{
4492    GL2Encoder *ctx = (GL2Encoder*)self;
4493    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4494    ctx->m_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
4495}
4496
4497void GL2Encoder::s_glProgramUniformMatrix3x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4498{
4499    GL2Encoder *ctx = (GL2Encoder*)self;
4500    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4501    ctx->m_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
4502}
4503
4504void GL2Encoder::s_glProgramUniformMatrix3x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4505{
4506    GL2Encoder *ctx = (GL2Encoder*)self;
4507    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4508    ctx->m_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
4509}
4510
4511void GL2Encoder::s_glProgramUniformMatrix4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4512{
4513    GL2Encoder *ctx = (GL2Encoder*)self;
4514    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4515    ctx->m_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
4516}
4517
4518void GL2Encoder::s_glProgramUniformMatrix4x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4519{
4520    GL2Encoder *ctx = (GL2Encoder*)self;
4521    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4522    ctx->m_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
4523}
4524
4525void GL2Encoder::s_glProgramUniformMatrix4x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4526{
4527    GL2Encoder *ctx = (GL2Encoder*)self;
4528    GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4529    ctx->m_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
4530}
4531
4532void 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
4537void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
4538{
4539    GL2Encoder *ctx = (GL2Encoder*)self;
4540    GLClientState* state = ctx->m_state;
4541    GLSharedGroupPtr shared = ctx->m_shared;
4542
4543    SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4544    SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4545    SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4546
4547    ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
4548    state->associateProgramWithPipeline(program, pipeline);
4549
4550    // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4551    if (state->currentProgram()) {
4552        return;
4553    }
4554
4555    // Otherwise, update host texture 2D bindings.
4556    ctx->updateHostTexture2DBindingsFromProgramData(program);
4557}
4558
4559void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
4560{
4561    GL2Encoder *ctx = (GL2Encoder*)self;
4562    GLClientState* state = ctx->m_state;
4563
4564    ctx->m_glBindProgramPipeline_enc(self, pipeline);
4565
4566    // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4567    if (!pipeline || state->currentProgram()) {
4568        return;
4569    }
4570
4571    GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
4572    for (; it != state->programPipelineEnd(); ++it) {
4573        if (it->second == pipeline) {
4574            ctx->updateHostTexture2DBindingsFromProgramData(it->first);
4575        }
4576    }
4577}
4578
4579void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
4580    GL2Encoder *ctx = (GL2Encoder*)self;
4581    SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4582    if (bufSize == 0) {
4583        if (length) *length = 0;
4584        return;
4585    }
4586
4587    // Avoid modifying |name| if |*length| < bufSize.
4588    GLint* intermediate = new GLint[bufSize];
4589    GLsizei* myLength = length ? length : new GLsizei;
4590    bool needFreeLength = length == NULL;
4591
4592    ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
4593    GLsizei writtenInts = *myLength;
4594    memcpy(params, intermediate, writtenInts * sizeof(GLint));
4595
4596    delete [] intermediate;
4597    if (needFreeLength)
4598        delete myLength;
4599}
4600
4601GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
4602    GL2Encoder *ctx = (GL2Encoder*)self;
4603    return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
4604}
4605
4606GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
4607    GL2Encoder *ctx = (GL2Encoder*)self;
4608    return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
4609}
4610
4611void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
4612    GL2Encoder *ctx = (GL2Encoder*)self;
4613    SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4614    if (bufSize == 0) {
4615        if (length) *length = 0;
4616        return;
4617    }
4618
4619    // Avoid modifying |name| if |*length| < bufSize.
4620    char* intermediate = new char[bufSize];
4621    GLsizei* myLength = length ? length : new GLsizei;
4622    bool needFreeLength = length == NULL;
4623
4624    ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
4625    GLsizei writtenStrLen = *myLength;
4626    memcpy(name, intermediate, writtenStrLen + 1);
4627
4628    delete [] intermediate;
4629    if (needFreeLength)
4630        delete myLength;
4631}
4632
4633void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
4634    GL2Encoder *ctx = (GL2Encoder*)self;
4635    SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4636    if (bufSize == 0) {
4637        if (length) *length = 0;
4638        return;
4639    }
4640
4641    // Avoid modifying |infoLog| if |*length| < bufSize.
4642    GLchar* intermediate = new GLchar[bufSize];
4643    GLsizei* myLength = length ? length : new GLsizei;
4644    bool needFreeLength = length == NULL;
4645
4646    ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
4647    GLsizei writtenStrLen = *myLength;
4648    memcpy(infoLog, intermediate, writtenStrLen + 1);
4649
4650    delete [] intermediate;
4651    if (needFreeLength)
4652        delete myLength;
4653}
4654
4655void 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
4666void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
4667    GL2Encoder *ctx = (GL2Encoder*)self;
4668    GLClientState* state = ctx->m_state;
4669
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
4677void 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
4687void 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
4697void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
4698    GL2Encoder *ctx = (GL2Encoder*)self;
4699    GLClientState* state = ctx->m_state;
4700
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
4713void 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
4738void 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
4767void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
4768    GL2Encoder *ctx = (GL2Encoder*)self;
4769    GLClientState* state = ctx->m_state;
4770
4771    SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
4772    SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
4773    SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
4774    SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
4775    SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
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