• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <assert.h>
19 #include <ctype.h>
20 
21 #include <GLES2/gl2.h>
22 #include <GLES2/gl2ext.h>
23 #include <GLES2/gl2platform.h>
24 
25 #include <GLES3/gl3.h>
26 
27 #ifndef MIN
28 #define MIN(a, b) ((a) < (b) ? (a) : (b))
29 #endif
30 
31 static GLubyte *gVendorString= (GLubyte *) "Android";
32 static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 2.0";
33 static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 2.0";
34 static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external ";
35 
36 #define SET_ERROR_IF(condition,err) if((condition)) {                            \
37         ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
38         ctx->setError(err);                                    \
39         return;                                                  \
40     }
41 
42 
43 #define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) {                \
44         ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
45         ctx->setError(err);                                    \
46         return ret;                                              \
47     }
48 
49 
GL2Encoder(IOStream * stream,ChecksumCalculator * protocol)50 GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
51         : gl2_encoder_context_t(stream, protocol)
52 {
53     m_initialized = false;
54     m_state = NULL;
55     m_error = GL_NO_ERROR;
56     m_num_compressedTextureFormats = 0;
57     m_max_cubeMapTextureSize = 0;
58     m_max_renderBufferSize = 0;
59     m_max_textureSize = 0;
60     m_compressedTextureFormats = NULL;
61 
62     //overrides
63 #define OVERRIDE(name)  m_##name##_enc = this-> name ; this-> name = &s_##name
64 
65     OVERRIDE(glFlush);
66     OVERRIDE(glPixelStorei);
67     OVERRIDE(glGetString);
68     OVERRIDE(glBindBuffer);
69     OVERRIDE(glBufferData);
70     OVERRIDE(glBufferSubData);
71     OVERRIDE(glDeleteBuffers);
72     OVERRIDE(glDrawArrays);
73     OVERRIDE(glDrawElements);
74     OVERRIDE(glGetIntegerv);
75     OVERRIDE(glGetFloatv);
76     OVERRIDE(glGetBooleanv);
77     OVERRIDE(glVertexAttribPointer);
78     OVERRIDE(glEnableVertexAttribArray);
79     OVERRIDE(glDisableVertexAttribArray);
80     OVERRIDE(glGetVertexAttribiv);
81     OVERRIDE(glGetVertexAttribfv);
82     OVERRIDE(glGetVertexAttribPointerv);
83 
84     this->glShaderBinary = &s_glShaderBinary;
85     this->glShaderSource = &s_glShaderSource;
86     this->glFinish = &s_glFinish;
87 
88     OVERRIDE(glGetError);
89     OVERRIDE(glLinkProgram);
90     OVERRIDE(glDeleteProgram);
91     OVERRIDE(glGetUniformiv);
92     OVERRIDE(glGetUniformfv);
93     OVERRIDE(glCreateProgram);
94     OVERRIDE(glCreateShader);
95     OVERRIDE(glDeleteShader);
96     OVERRIDE(glAttachShader);
97     OVERRIDE(glDetachShader);
98     OVERRIDE(glGetAttachedShaders);
99     OVERRIDE(glGetShaderSource);
100     OVERRIDE(glGetShaderInfoLog);
101     OVERRIDE(glGetProgramInfoLog);
102 
103     OVERRIDE(glGetUniformLocation);
104     OVERRIDE(glUseProgram);
105 
106     OVERRIDE(glUniform1f);
107     OVERRIDE(glUniform1fv);
108     OVERRIDE(glUniform1i);
109     OVERRIDE(glUniform1iv);
110     OVERRIDE(glUniform2f);
111     OVERRIDE(glUniform2fv);
112     OVERRIDE(glUniform2i);
113     OVERRIDE(glUniform2iv);
114     OVERRIDE(glUniform3f);
115     OVERRIDE(glUniform3fv);
116     OVERRIDE(glUniform3i);
117     OVERRIDE(glUniform3iv);
118     OVERRIDE(glUniform4f);
119     OVERRIDE(glUniform4fv);
120     OVERRIDE(glUniform4i);
121     OVERRIDE(glUniform4iv);
122     OVERRIDE(glUniformMatrix2fv);
123     OVERRIDE(glUniformMatrix3fv);
124     OVERRIDE(glUniformMatrix4fv);
125 
126     OVERRIDE(glActiveTexture);
127     OVERRIDE(glBindTexture);
128     OVERRIDE(glDeleteTextures);
129     OVERRIDE(glGetTexParameterfv);
130     OVERRIDE(glGetTexParameteriv);
131     OVERRIDE(glTexParameterf);
132     OVERRIDE(glTexParameterfv);
133     OVERRIDE(glTexParameteri);
134     OVERRIDE(glTexParameteriv);
135     OVERRIDE(glTexImage2D);
136     OVERRIDE(glTexSubImage2D);
137     OVERRIDE(glCopyTexImage2D);
138 
139     OVERRIDE(glGenRenderbuffers);
140     OVERRIDE(glDeleteRenderbuffers);
141     OVERRIDE(glBindRenderbuffer);
142     OVERRIDE(glRenderbufferStorage);
143     OVERRIDE(glFramebufferRenderbuffer);
144 
145     OVERRIDE(glGenFramebuffers);
146     OVERRIDE(glDeleteFramebuffers);
147     OVERRIDE(glBindFramebuffer);
148     OVERRIDE(glFramebufferTexture2D);
149     OVERRIDE(glFramebufferTexture3DOES);
150     OVERRIDE(glGetFramebufferAttachmentParameteriv);
151 
152     OVERRIDE(glCheckFramebufferStatus);
153 }
154 
~GL2Encoder()155 GL2Encoder::~GL2Encoder()
156 {
157     delete m_compressedTextureFormats;
158 }
159 
s_glGetError(void * self)160 GLenum GL2Encoder::s_glGetError(void * self)
161 {
162     GL2Encoder *ctx = (GL2Encoder *)self;
163     GLenum err = ctx->getError();
164     if(err != GL_NO_ERROR) {
165         ctx->setError(GL_NO_ERROR);
166         return err;
167     }
168 
169     return ctx->m_glGetError_enc(self);
170 
171 }
172 
s_glFlush(void * self)173 void GL2Encoder::s_glFlush(void *self)
174 {
175     GL2Encoder *ctx = (GL2Encoder *) self;
176     ctx->m_glFlush_enc(self);
177     ctx->m_stream->flush();
178 }
179 
s_glGetString(void * self,GLenum name)180 const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
181 {
182     (void)self;
183 
184     GLubyte *retval =  (GLubyte *) "";
185     switch(name) {
186     case GL_VENDOR:
187         retval = gVendorString;
188         break;
189     case GL_RENDERER:
190         retval = gRendererString;
191         break;
192     case GL_VERSION:
193         retval = gVersionString;
194         break;
195     case GL_EXTENSIONS:
196         retval = gExtensionsString;
197         break;
198     }
199     return retval;
200 }
201 
s_glPixelStorei(void * self,GLenum param,GLint value)202 void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
203 {
204     GL2Encoder *ctx = (GL2Encoder *)self;
205     ctx->m_glPixelStorei_enc(ctx, param, value);
206     assert(ctx->m_state != NULL);
207     ctx->m_state->setPixelStore(param, value);
208 }
209 
210 
s_glBindBuffer(void * self,GLenum target,GLuint id)211 void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
212 {
213     GL2Encoder *ctx = (GL2Encoder *) self;
214     assert(ctx->m_state != NULL);
215     ctx->m_state->bindBuffer(target, id);
216     // TODO set error state if needed;
217     ctx->m_glBindBuffer_enc(self, target, id);
218 }
219 
s_glBufferData(void * self,GLenum target,GLsizeiptr size,const GLvoid * data,GLenum usage)220 void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
221 {
222     GL2Encoder *ctx = (GL2Encoder *) self;
223     SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
224     GLuint bufferId = ctx->m_state->getBuffer(target);
225     SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
226     SET_ERROR_IF(size<0, GL_INVALID_VALUE);
227 
228     ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
229     ctx->m_glBufferData_enc(self, target, size, data, usage);
230 }
231 
s_glBufferSubData(void * self,GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid * data)232 void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
233 {
234     GL2Encoder *ctx = (GL2Encoder *) self;
235     SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
236     GLuint bufferId = ctx->m_state->getBuffer(target);
237     SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
238 
239     GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
240     SET_ERROR_IF(res, res);
241 
242     ctx->m_glBufferSubData_enc(self, target, offset, size, data);
243 }
244 
s_glDeleteBuffers(void * self,GLsizei n,const GLuint * buffers)245 void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
246 {
247     GL2Encoder *ctx = (GL2Encoder *) self;
248     SET_ERROR_IF(n<0, GL_INVALID_VALUE);
249     for (int i=0; i<n; i++) {
250         ctx->m_shared->deleteBufferData(buffers[i]);
251         ctx->m_state->unBindBuffer(buffers[i]);
252         ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
253     }
254 }
255 
isValidVertexAttribIndex(void * self,GLuint indx)256 static bool isValidVertexAttribIndex(void *self, GLuint indx)
257 {
258     GL2Encoder *ctx = (GL2Encoder *) self;
259     GLint maxIndex;
260     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
261     return indx < maxIndex;
262 }
263 
isValidVertexAttribType(GLenum type)264 static bool isValidVertexAttribType(GLenum type)
265 {
266     bool retval = false;
267     switch (type) {
268     case GL_BYTE:
269     case GL_UNSIGNED_BYTE:
270     case GL_SHORT:
271     case GL_UNSIGNED_SHORT:
272     case GL_FIXED:
273     case GL_FLOAT:
274     // The following are technically only available if certain GLES2 extensions are.
275     // However, they are supported by desktop GL3, which is a reasonable requirement
276     // for the desktop GL version. Therefore, consider them valid.
277     case GL_INT:
278     case GL_UNSIGNED_INT:
279     case GL_HALF_FLOAT_OES:
280         retval = true;
281         break;
282     }
283     return retval;
284 }
285 
s_glVertexAttribPointer(void * self,GLuint indx,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid * ptr)286 void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
287 {
288     GL2Encoder *ctx = (GL2Encoder *)self;
289     assert(ctx->m_state != NULL);
290     SET_ERROR_IF(!isValidVertexAttribIndex(self, indx), GL_INVALID_VALUE);
291     SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
292     SET_ERROR_IF(!isValidVertexAttribType(type), GL_INVALID_ENUM);
293     SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
294     ctx->m_state->setState(indx, size, type, normalized, stride, ptr);
295 }
296 
s_glGetIntegerv(void * self,GLenum param,GLint * ptr)297 void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
298 {
299     GL2Encoder *ctx = (GL2Encoder *) self;
300     assert(ctx->m_state != NULL);
301     GLClientState* state = ctx->m_state;
302 
303     switch (param) {
304     case GL_NUM_SHADER_BINARY_FORMATS:
305         *ptr = 0;
306         break;
307     case GL_SHADER_BINARY_FORMATS:
308         // do nothing
309         break;
310 
311     case GL_COMPRESSED_TEXTURE_FORMATS: {
312         GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
313         if (ctx->m_num_compressedTextureFormats > 0 &&
314                 compressedTextureFormats != NULL) {
315             memcpy(ptr, compressedTextureFormats,
316                     ctx->m_num_compressedTextureFormats * sizeof(GLint));
317         }
318         break;
319     }
320 
321     case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
322     case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
323     case GL_MAX_TEXTURE_IMAGE_UNITS:
324         ctx->m_glGetIntegerv_enc(self, param, ptr);
325         *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
326         break;
327 
328     case GL_TEXTURE_BINDING_2D:
329         *ptr = state->getBoundTexture(GL_TEXTURE_2D);
330         break;
331     case GL_TEXTURE_BINDING_EXTERNAL_OES:
332         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
333         break;
334 
335     case GL_MAX_VERTEX_ATTRIBS:
336         if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
337             ctx->m_glGetIntegerv_enc(self, param, ptr);
338             ctx->m_state->setMaxVertexAttribs(*ptr);
339         }
340         break;
341     case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
342         if (ctx->m_max_cubeMapTextureSize != 0) {
343             *ptr = ctx->m_max_cubeMapTextureSize;
344         } else {
345             ctx->m_glGetIntegerv_enc(self, param, ptr);
346             ctx->m_max_cubeMapTextureSize = *ptr;
347         }
348         break;
349     case GL_MAX_RENDERBUFFER_SIZE:
350         if (ctx->m_max_renderBufferSize != 0) {
351             *ptr = ctx->m_max_renderBufferSize;
352         } else {
353             ctx->m_glGetIntegerv_enc(self, param, ptr);
354             ctx->m_max_renderBufferSize = *ptr;
355         }
356         break;
357     case GL_MAX_TEXTURE_SIZE:
358         if (ctx->m_max_textureSize != 0) {
359             *ptr = ctx->m_max_textureSize;
360         } else {
361             ctx->m_glGetIntegerv_enc(self, param, ptr);
362             ctx->m_max_textureSize = *ptr;
363         }
364         break;
365     default:
366         if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
367             ctx->m_glGetIntegerv_enc(self, param, ptr);
368         }
369         break;
370     }
371 }
372 
373 
s_glGetFloatv(void * self,GLenum param,GLfloat * ptr)374 void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
375 {
376     GL2Encoder *ctx = (GL2Encoder *)self;
377     assert(ctx->m_state != NULL);
378     GLClientState* state = ctx->m_state;
379 
380     switch (param) {
381     case GL_NUM_SHADER_BINARY_FORMATS:
382         *ptr = 0;
383         break;
384     case GL_SHADER_BINARY_FORMATS:
385         // do nothing
386         break;
387 
388     case GL_COMPRESSED_TEXTURE_FORMATS: {
389         GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
390         if (ctx->m_num_compressedTextureFormats > 0 &&
391                 compressedTextureFormats != NULL) {
392             for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
393                 ptr[i] = (GLfloat) compressedTextureFormats[i];
394             }
395         }
396         break;
397     }
398 
399     case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
400     case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
401     case GL_MAX_TEXTURE_IMAGE_UNITS:
402         ctx->m_glGetFloatv_enc(self, param, ptr);
403         *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
404         break;
405 
406     case GL_TEXTURE_BINDING_2D:
407         *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
408         break;
409     case GL_TEXTURE_BINDING_EXTERNAL_OES:
410         *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
411         break;
412 
413     default:
414         if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
415             ctx->m_glGetFloatv_enc(self, param, ptr);
416         }
417         break;
418     }
419 }
420 
421 
s_glGetBooleanv(void * self,GLenum param,GLboolean * ptr)422 void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
423 {
424     GL2Encoder *ctx = (GL2Encoder *)self;
425     assert(ctx->m_state != NULL);
426     GLClientState* state = ctx->m_state;
427 
428     switch (param) {
429     case GL_NUM_SHADER_BINARY_FORMATS:
430         *ptr = GL_FALSE;
431         break;
432     case GL_SHADER_BINARY_FORMATS:
433         // do nothing
434         break;
435 
436     case GL_COMPRESSED_TEXTURE_FORMATS: {
437         GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
438         if (ctx->m_num_compressedTextureFormats > 0 &&
439                 compressedTextureFormats != NULL) {
440             for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
441                 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
442             }
443         }
444         break;
445     }
446 
447     case GL_TEXTURE_BINDING_2D:
448         *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
449         break;
450     case GL_TEXTURE_BINDING_EXTERNAL_OES:
451         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
452                 ? GL_TRUE : GL_FALSE;
453         break;
454 
455     default:
456         if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
457             ctx->m_glGetBooleanv_enc(self, param, ptr);
458         }
459         *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
460         break;
461     }
462 }
463 
464 
s_glEnableVertexAttribArray(void * self,GLuint index)465 void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
466 {
467     GL2Encoder *ctx = (GL2Encoder *)self;
468     assert(ctx->m_state);
469     SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
470     ctx->m_state->enable(index, 1);
471 }
472 
s_glDisableVertexAttribArray(void * self,GLuint index)473 void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
474 {
475     GL2Encoder *ctx = (GL2Encoder *)self;
476     assert(ctx->m_state);
477     SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
478     ctx->m_state->enable(index, 0);
479 }
480 
481 
s_glGetVertexAttribiv(void * self,GLuint index,GLenum pname,GLint * params)482 void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
483 {
484     GL2Encoder *ctx = (GL2Encoder *)self;
485     assert(ctx->m_state);
486     GLint maxIndex;
487     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
488     SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
489 
490     if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
491         ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
492     }
493 }
494 
s_glGetVertexAttribfv(void * self,GLuint index,GLenum pname,GLfloat * params)495 void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
496 {
497     GL2Encoder *ctx = (GL2Encoder *)self;
498     assert(ctx->m_state);
499     GLint maxIndex;
500     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
501     SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
502 
503     if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
504         ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
505     }
506 }
507 
s_glGetVertexAttribPointerv(void * self,GLuint index,GLenum pname,GLvoid ** pointer)508 void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
509 {
510     GL2Encoder *ctx = (GL2Encoder *)self;
511     if (ctx->m_state == NULL) return;
512     GLint maxIndex;
513     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
514     SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
515     SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
516     (void)pname;
517 
518     const GLClientState::VertexAttribState *va_state = ctx->m_state->getState(index);
519     if (va_state != NULL) {
520         *pointer = va_state->data;
521     }
522 }
523 
524 
sendVertexAttributes(GLint first,GLsizei count)525 void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count)
526 {
527     assert(m_state);
528 
529     GLuint lastBoundVbo = m_state->currentArrayVbo();
530     for (int i = 0; i < m_state->nLocations(); i++) {
531         bool enableDirty;
532         const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty);
533 
534         if (!state) {
535             continue;
536         }
537 
538         if (!enableDirty && !state->enabled) {
539             continue;
540         }
541 
542         if (state->enabled) {
543             if (lastBoundVbo != state->bufferObject) {
544                 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject);
545                 lastBoundVbo = state->bufferObject;
546             }
547 
548             unsigned int datalen = state->elementSize * count;
549             int stride = state->stride == 0 ? state->elementSize : state->stride;
550             int firstIndex = stride * first;
551 
552             if (state->bufferObject == 0) {
553                 m_glEnableVertexAttribArray_enc(this, i);
554                 this->glVertexAttribPointerData(this, i, state->size, state->type, state->normalized, state->stride,
555                                                 (unsigned char *)state->data + firstIndex, datalen);
556             } else {
557                 const BufferData* buf = m_shared->getBufferData(state->bufferObject);
558                 // The following expression actually means bufLen = stride*count;
559                 // But the last element doesn't have to fill up the whole stride.
560                 // So it becomes the current form.
561                 unsigned int bufLen = stride * (count - 1) + state->elementSize;
562                 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
563                     m_glEnableVertexAttribArray_enc(this, i);
564                     this->glVertexAttribPointerOffset(this, i, state->size, state->type, state->normalized, state->stride,
565                                                   (uintptr_t) state->data + firstIndex);
566                 } else {
567                     ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute.");
568                     m_glDisableVertexAttribArray_enc(this, i);
569                 }
570             }
571         } else {
572             this->m_glDisableVertexAttribArray_enc(this, i);
573         }
574     }
575 
576     if (lastBoundVbo != m_state->currentArrayVbo()) {
577         this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
578     }
579 }
580 
isValidDrawMode(GLenum mode)581 static bool isValidDrawMode(GLenum mode)
582 {
583     bool retval = false;
584     switch (mode) {
585     case GL_POINTS:
586     case GL_LINE_STRIP:
587     case GL_LINE_LOOP:
588     case GL_LINES:
589     case GL_TRIANGLE_STRIP:
590     case GL_TRIANGLE_FAN:
591     case GL_TRIANGLES:
592         retval = true;
593     }
594     return retval;
595 }
596 
s_glDrawArrays(void * self,GLenum mode,GLint first,GLsizei count)597 void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
598 {
599     GL2Encoder *ctx = (GL2Encoder *)self;
600     assert(ctx->m_state != NULL);
601     SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
602     SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
603 
604     bool has_arrays = false;
605     int nLocations = ctx->m_state->nLocations();
606     for (int i = 0; i < nLocations; i++) {
607         const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
608         if (state->enabled) {
609             if (state->bufferObject || state->data)  {
610                 has_arrays = true;
611             }
612             else {
613                 ALOGE("glDrawArrays: a vertex attribute array is enabled with no data bound\n");
614                 ctx->setError(GL_INVALID_OPERATION);
615                 return;
616             }
617         }
618     }
619 
620     ctx->sendVertexAttributes(first, count);
621     ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
622     ctx->m_stream->flush();
623 }
624 
625 
s_glDrawElements(void * self,GLenum mode,GLsizei count,GLenum type,const void * indices)626 void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
627 {
628 
629     GL2Encoder *ctx = (GL2Encoder *)self;
630     assert(ctx->m_state != NULL);
631     SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
632     SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
633     SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
634 
635     bool has_immediate_arrays = false;
636     bool has_indirect_arrays = false;
637     int nLocations = ctx->m_state->nLocations();
638     GLintptr offset = 0;
639 
640     for (int i = 0; i < nLocations; i++) {
641         const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
642         if (state->enabled) {
643             if (state->bufferObject != 0) {
644                 has_indirect_arrays = true;
645             } else if (state->data) {
646                 has_immediate_arrays = true;
647             } else {
648                 ALOGW("glDrawElements: a vertex attribute array is enabled with no data bound\n");
649                 ctx->setError(GL_INVALID_OPERATION);
650                 return;
651             }
652         }
653     }
654 
655     if (!has_immediate_arrays && !has_indirect_arrays) {
656         ALOGE("glDrawElements: no data bound to the command - ignoring\n");
657         GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
658         SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
659         return;
660     }
661 
662     if (ctx->m_state->currentIndexVbo() != 0) {
663         offset = (GLintptr)indices;
664         BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
665         indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + offset);
666     }
667     int minIndex = 0, maxIndex = 0;
668     switch(type) {
669     case GL_BYTE:
670     case GL_UNSIGNED_BYTE:
671         GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex);
672         break;
673     case GL_SHORT:
674     case GL_UNSIGNED_SHORT:
675         GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex);
676         break;
677     case GL_INT:
678     case GL_UNSIGNED_INT:
679         GLUtils::minmax<unsigned int>((unsigned int *)indices, count, &minIndex, &maxIndex);
680         break;
681     default:
682         ALOGE("unsupported index buffer type %d\n", type);
683     }
684 
685     bool adjustIndices = true;
686     if (ctx->m_state->currentIndexVbo() != 0) {
687         if (!has_immediate_arrays) {
688             ctx->sendVertexAttributes(0, maxIndex + 1);
689             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
690             ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
691             ctx->m_stream->flush();
692             adjustIndices = false;
693         } else {
694             BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
695             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
696         }
697     }
698     if (adjustIndices) {
699         void *adjustedIndices = (void*)indices;
700 
701         if (minIndex != 0) {
702             adjustedIndices =  ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
703             switch(type) {
704             case GL_BYTE:
705             case GL_UNSIGNED_BYTE:
706                 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices,
707                                                  (unsigned char *)adjustedIndices,
708                                                  count, -minIndex);
709                 break;
710             case GL_SHORT:
711             case GL_UNSIGNED_SHORT:
712                 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices,
713                                                   (unsigned short *)adjustedIndices,
714                                                   count, -minIndex);
715                 break;
716             case GL_INT:
717             case GL_UNSIGNED_INT:
718                 GLUtils::shiftIndices<unsigned int>((unsigned int *)indices,
719                                                  (unsigned int *)adjustedIndices,
720                                                  count, -minIndex);
721                 break;
722             default:
723                 ALOGE("unsupported index buffer type %d\n", type);
724             }
725         }
726         if (has_indirect_arrays || 1) {
727             ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1);
728             ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
729                                     count * glSizeof(type));
730             ctx->m_stream->flush();
731             // XXX - OPTIMIZATION (see the other else branch) should be implemented
732             if(!has_indirect_arrays) {
733                 //ALOGD("unoptimized drawelements !!!\n");
734             }
735         } else {
736             // we are all direct arrays and immidate mode index array -
737             // rebuild the arrays and the index array;
738             ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
739         }
740     }
741 }
742 
743 
getCompressedTextureFormats()744 GLint * GL2Encoder::getCompressedTextureFormats()
745 {
746     if (m_compressedTextureFormats == NULL) {
747         this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
748                             &m_num_compressedTextureFormats);
749         if (m_num_compressedTextureFormats > 0) {
750             // get number of texture formats;
751             m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
752             this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
753         }
754     }
755     return m_compressedTextureFormats;
756 }
757 
758 // Replace uses of samplerExternalOES with sampler2D, recording the names of
759 // modified shaders in data. Also remove
760 //   #extension GL_OES_EGL_image_external : require
761 // statements.
762 //
763 // This implementation assumes the input has already been pre-processed. If not,
764 // a few cases will be mishandled:
765 //
766 // 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
767 //    the following code:
768 //      #if 1
769 //      uniform sampler2D mySampler;
770 //      #else
771 //      uniform samplerExternalOES mySampler;
772 //      #endif
773 //
774 // 2. Comments that look like sampler declarations will be incorrectly modified
775 //    and recorded:
776 //      // samplerExternalOES hahaFooledYou
777 //
778 // 3. However, GLSL ES does not have a concatentation operator, so things like
779 //    this (valid in C) are invalid and not a problem:
780 //      #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
781 //      SAMPLER(ExternalOES, mySampler);
782 //
replaceSamplerExternalWith2D(char * const str,ShaderData * const data)783 static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
784 {
785     static const char STR_HASH_EXTENSION[] = "#extension";
786     static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
787     static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
788     static const char STR_SAMPLER2D_SPACE[]      = "sampler2D         ";
789 
790     // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
791     char* c = str;
792     while ((c = strstr(c, STR_HASH_EXTENSION))) {
793         char* start = c;
794         c += sizeof(STR_HASH_EXTENSION)-1;
795         while (isspace(*c) && *c != '\0') {
796             c++;
797         }
798         if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
799                 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
800         {
801             // #extension statements are terminated by end of line
802             c = start;
803             while (*c != '\0' && *c != '\r' && *c != '\n') {
804                 *c++ = ' ';
805             }
806         }
807     }
808 
809     // -- replace "samplerExternalOES" with "sampler2D" and record name
810     c = str;
811     while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
812         // Make sure "samplerExternalOES" isn't a substring of a larger token
813         if (c == str || !isspace(*(c-1))) {
814             c++;
815             continue;
816         }
817         char* sampler_start = c;
818         c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
819         if (!isspace(*c) && *c != '\0') {
820             continue;
821         }
822 
823         // capture sampler name
824         while (isspace(*c) && *c != '\0') {
825             c++;
826         }
827         if (!isalpha(*c) && *c != '_') {
828             // not an identifier
829             return false;
830         }
831         char* name_start = c;
832         do {
833             c++;
834         } while (isalnum(*c) || *c == '_');
835         data->samplerExternalNames.push_back(
836                 android::String8(name_start, c - name_start));
837 
838         // memcpy instead of strcpy since we don't want the NUL terminator
839         memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
840     }
841 
842     return true;
843 }
844 
s_glShaderBinary(void * self,GLsizei n,const GLuint * shaders,GLenum binaryformat,const void * binary,GLsizei length)845 void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
846 {
847     GL2Encoder* ctx = (GL2Encoder*)self;
848     // Although it is not supported, need to set proper error code.
849     SET_ERROR_IF(1, GL_INVALID_ENUM);
850 }
851 
s_glShaderSource(void * self,GLuint shader,GLsizei count,const GLchar * const * string,const GLint * length)852 void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
853 {
854     GL2Encoder* ctx = (GL2Encoder*)self;
855     ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
856     SET_ERROR_IF(!ctx->m_shared->isObject(shader), GL_INVALID_VALUE);
857     SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
858     SET_ERROR_IF((count<0), GL_INVALID_VALUE);
859 
860     int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
861     char *str = new char[len + 1];
862     glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
863 
864     // TODO: pre-process str before calling replaceSamplerExternalWith2D().
865     // Perhaps we can borrow Mesa's pre-processor?
866 
867     if (!replaceSamplerExternalWith2D(str, shaderData)) {
868         delete[] str;
869         ctx->setError(GL_OUT_OF_MEMORY);
870         return;
871     }
872 
873     ctx->glShaderString(ctx, shader, str, len + 1);
874     delete[] str;
875 }
876 
s_glFinish(void * self)877 void GL2Encoder::s_glFinish(void *self)
878 {
879     GL2Encoder *ctx = (GL2Encoder *)self;
880     ctx->glFinishRoundTrip(self);
881 }
882 
s_glLinkProgram(void * self,GLuint program)883 void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
884 {
885     GL2Encoder *ctx = (GL2Encoder *)self;
886     ctx->m_glLinkProgram_enc(self, program);
887 
888     GLint linkStatus = 0;
889     ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
890     if (!linkStatus)
891         return;
892 
893     //get number of active uniforms in the program
894     GLint numUniforms=0;
895     ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
896     ctx->m_shared->initProgramData(program,numUniforms);
897 
898     //get the length of the longest uniform name
899     GLint maxLength=0;
900     ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
901 
902     GLint size;
903     GLenum type;
904     GLchar *name = new GLchar[maxLength+1];
905     GLint location;
906     //for each active uniform, get its size and starting location.
907     for (GLint i=0 ; i<numUniforms ; ++i)
908     {
909         ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
910         location = ctx->m_glGetUniformLocation_enc(self, program, name);
911         ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
912     }
913     ctx->m_shared->setupLocationShiftWAR(program);
914 
915     delete[] name;
916 }
917 
s_glDeleteProgram(void * self,GLuint program)918 void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
919 {
920     GL2Encoder *ctx = (GL2Encoder*)self;
921     ctx->m_glDeleteProgram_enc(self, program);
922 
923     ctx->m_shared->deleteProgramData(program);
924 }
925 
s_glGetUniformiv(void * self,GLuint program,GLint location,GLint * params)926 void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
927 {
928     GL2Encoder *ctx = (GL2Encoder*)self;
929     SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
930     SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
931     SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
932     GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
933     SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
934     ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
935 }
s_glGetUniformfv(void * self,GLuint program,GLint location,GLfloat * params)936 void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
937 {
938     GL2Encoder *ctx = (GL2Encoder*)self;
939     SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
940     SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
941     SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
942     GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
943     SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
944     ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
945 }
946 
s_glCreateProgram(void * self)947 GLuint GL2Encoder::s_glCreateProgram(void * self)
948 {
949     GL2Encoder *ctx = (GL2Encoder*)self;
950     GLuint program = ctx->m_glCreateProgram_enc(self);
951     if (program!=0)
952         ctx->m_shared->addProgramData(program);
953     return program;
954 }
955 
s_glCreateShader(void * self,GLenum shaderType)956 GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
957 {
958     GL2Encoder *ctx = (GL2Encoder*)self;
959     RET_AND_SET_ERROR_IF(((shaderType != GL_VERTEX_SHADER) && (shaderType != GL_FRAGMENT_SHADER)),
960         GL_INVALID_ENUM, 0);
961     GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
962     if (shader != 0) {
963         if (!ctx->m_shared->addShaderData(shader)) {
964             ctx->m_glDeleteShader_enc(self, shader);
965             return 0;
966         }
967     }
968     return shader;
969 }
970 
s_glGetAttachedShaders(void * self,GLuint program,GLsizei maxCount,GLsizei * count,GLuint * shaders)971 void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
972         GLsizei* count, GLuint* shaders)
973 {
974     GL2Encoder *ctx = (GL2Encoder*)self;
975     SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
976     ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
977 }
978 
s_glGetShaderSource(void * self,GLuint shader,GLsizei bufsize,GLsizei * length,GLchar * source)979 void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
980             GLsizei* length, GLchar* source)
981 {
982     GL2Encoder *ctx = (GL2Encoder*)self;
983     SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
984     ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
985 }
986 
s_glGetShaderInfoLog(void * self,GLuint shader,GLsizei bufsize,GLsizei * length,GLchar * infolog)987 void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
988         GLsizei* length, GLchar* infolog)
989 {
990     GL2Encoder *ctx = (GL2Encoder*)self;
991     SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
992     ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
993 }
994 
s_glGetProgramInfoLog(void * self,GLuint program,GLsizei bufsize,GLsizei * length,GLchar * infolog)995 void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
996         GLsizei* length, GLchar* infolog)
997 {
998     GL2Encoder *ctx = (GL2Encoder*)self;
999     SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1000     ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1001 }
1002 
s_glDeleteShader(void * self,GLenum shader)1003 void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1004 {
1005     GL2Encoder *ctx = (GL2Encoder*)self;
1006     ctx->m_glDeleteShader_enc(self,shader);
1007     ctx->m_shared->unrefShaderData(shader);
1008 }
1009 
s_glAttachShader(void * self,GLuint program,GLuint shader)1010 void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1011 {
1012     GL2Encoder *ctx = (GL2Encoder*)self;
1013     ctx->m_glAttachShader_enc(self, program, shader);
1014     ctx->m_shared->attachShader(program, shader);
1015 }
1016 
s_glDetachShader(void * self,GLuint program,GLuint shader)1017 void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1018 {
1019     GL2Encoder *ctx = (GL2Encoder*)self;
1020     ctx->m_glDetachShader_enc(self, program, shader);
1021     ctx->m_shared->detachShader(program, shader);
1022 }
1023 
s_glGetUniformLocation(void * self,GLuint program,const GLchar * name)1024 int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1025 {
1026     if (!name) return -1;
1027 
1028     GL2Encoder *ctx = (GL2Encoder*)self;
1029 
1030     // if we need the uniform location WAR
1031     // parse array index from the end of the name string
1032     int arrIndex = 0;
1033     bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1034     if (needLocationWAR) {
1035         int namelen = strlen(name);
1036         if (name[namelen-1] == ']') {
1037             const char *brace = strrchr(name,'[');
1038             if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1039                 return -1;
1040             }
1041 
1042         }
1043     }
1044 
1045     int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1046     if (hostLoc >= 0 && needLocationWAR) {
1047         return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1048     }
1049     return hostLoc;
1050 }
1051 
updateHostTexture2DBinding(GLenum texUnit,GLenum newTarget)1052 bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1053 {
1054     if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1055         return false;
1056 
1057     m_state->setActiveTextureUnit(texUnit);
1058 
1059     GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1060     if (newTarget != oldTarget) {
1061         if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1062             m_state->disableTextureTarget(GL_TEXTURE_2D);
1063             m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1064         } else {
1065             m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1066             m_state->enableTextureTarget(GL_TEXTURE_2D);
1067         }
1068         m_glActiveTexture_enc(this, texUnit);
1069         m_glBindTexture_enc(this, GL_TEXTURE_2D,
1070                 m_state->getBoundTexture(newTarget));
1071         return true;
1072     }
1073 
1074     return false;
1075 }
1076 
s_glUseProgram(void * self,GLuint program)1077 void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1078 {
1079     GL2Encoder *ctx = (GL2Encoder*)self;
1080     GLClientState* state = ctx->m_state;
1081     GLSharedGroupPtr shared = ctx->m_shared;
1082 
1083     SET_ERROR_IF(program && !shared->isObject(program), GL_INVALID_VALUE);
1084     SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1085 
1086     ctx->m_glUseProgram_enc(self, program);
1087     ctx->m_state->setCurrentProgram(program);
1088 
1089     GLenum origActiveTexture = state->getActiveTextureUnit();
1090     GLenum hostActiveTexture = origActiveTexture;
1091     GLint samplerIdx = -1;
1092     GLint samplerVal;
1093     GLenum samplerTarget;
1094     while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1095         if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1096             continue;
1097         if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
1098                 samplerTarget))
1099         {
1100             hostActiveTexture = GL_TEXTURE0 + samplerVal;
1101         }
1102     }
1103     state->setActiveTextureUnit(origActiveTexture);
1104     if (hostActiveTexture != origActiveTexture) {
1105         ctx->m_glActiveTexture_enc(self, origActiveTexture);
1106     }
1107 }
1108 
s_glUniform1f(void * self,GLint location,GLfloat x)1109 void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1110 {
1111     GL2Encoder *ctx = (GL2Encoder*)self;
1112     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1113     ctx->m_glUniform1f_enc(self, hostLoc, x);
1114 }
1115 
s_glUniform1fv(void * self,GLint location,GLsizei count,const GLfloat * v)1116 void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1117 {
1118     GL2Encoder *ctx = (GL2Encoder*)self;
1119     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1120     ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1121 }
1122 
s_glUniform1i(void * self,GLint location,GLint x)1123 void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1124 {
1125     GL2Encoder *ctx = (GL2Encoder*)self;
1126     GLClientState* state = ctx->m_state;
1127     GLSharedGroupPtr shared = ctx->m_shared;
1128 
1129     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1130     ctx->m_glUniform1i_enc(self, hostLoc, x);
1131 
1132     GLenum target;
1133     if (shared->setSamplerUniform(state->currentProgram(), location, x, &target)) {
1134         GLenum origActiveTexture = state->getActiveTextureUnit();
1135         if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1136             ctx->m_glActiveTexture_enc(self, origActiveTexture);
1137         }
1138         state->setActiveTextureUnit(origActiveTexture);
1139     }
1140 }
1141 
s_glUniform1iv(void * self,GLint location,GLsizei count,const GLint * v)1142 void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1143 {
1144     GL2Encoder *ctx = (GL2Encoder*)self;
1145     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1146     ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1147 }
1148 
s_glUniform2f(void * self,GLint location,GLfloat x,GLfloat y)1149 void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1150 {
1151     GL2Encoder *ctx = (GL2Encoder*)self;
1152     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1153     ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1154 }
1155 
s_glUniform2fv(void * self,GLint location,GLsizei count,const GLfloat * v)1156 void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1157 {
1158     GL2Encoder *ctx = (GL2Encoder*)self;
1159     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1160     ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1161 }
1162 
s_glUniform2i(void * self,GLint location,GLint x,GLint y)1163 void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1164 {
1165     GL2Encoder *ctx = (GL2Encoder*)self;
1166     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1167     ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1168 }
1169 
s_glUniform2iv(void * self,GLint location,GLsizei count,const GLint * v)1170 void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1171 {
1172     GL2Encoder *ctx = (GL2Encoder*)self;
1173     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1174     ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1175 }
1176 
s_glUniform3f(void * self,GLint location,GLfloat x,GLfloat y,GLfloat z)1177 void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1178 {
1179     GL2Encoder *ctx = (GL2Encoder*)self;
1180     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1181     ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1182 }
1183 
s_glUniform3fv(void * self,GLint location,GLsizei count,const GLfloat * v)1184 void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1185 {
1186     GL2Encoder *ctx = (GL2Encoder*)self;
1187     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1188     ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1189 }
1190 
s_glUniform3i(void * self,GLint location,GLint x,GLint y,GLint z)1191 void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1192 {
1193     GL2Encoder *ctx = (GL2Encoder*)self;
1194     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1195     ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1196 }
1197 
s_glUniform3iv(void * self,GLint location,GLsizei count,const GLint * v)1198 void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1199 {
1200     GL2Encoder *ctx = (GL2Encoder*)self;
1201     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1202     ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1203 }
1204 
s_glUniform4f(void * self,GLint location,GLfloat x,GLfloat y,GLfloat z,GLfloat w)1205 void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1206 {
1207     GL2Encoder *ctx = (GL2Encoder*)self;
1208     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1209     ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1210 }
1211 
s_glUniform4fv(void * self,GLint location,GLsizei count,const GLfloat * v)1212 void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1213 {
1214     GL2Encoder *ctx = (GL2Encoder*)self;
1215     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1216     ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1217 }
1218 
s_glUniform4i(void * self,GLint location,GLint x,GLint y,GLint z,GLint w)1219 void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1220 {
1221     GL2Encoder *ctx = (GL2Encoder*)self;
1222     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1223     ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1224 }
1225 
s_glUniform4iv(void * self,GLint location,GLsizei count,const GLint * v)1226 void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1227 {
1228     GL2Encoder *ctx = (GL2Encoder*)self;
1229     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1230     ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1231 }
1232 
s_glUniformMatrix2fv(void * self,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1233 void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1234 {
1235     GL2Encoder *ctx = (GL2Encoder*)self;
1236     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1237     ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1238 }
1239 
s_glUniformMatrix3fv(void * self,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1240 void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1241 {
1242     GL2Encoder *ctx = (GL2Encoder*)self;
1243     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1244     ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1245 }
1246 
s_glUniformMatrix4fv(void * self,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1247 void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1248 {
1249     GL2Encoder *ctx = (GL2Encoder*)self;
1250     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1251     ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1252 }
1253 
s_glActiveTexture(void * self,GLenum texture)1254 void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1255 {
1256     GL2Encoder* ctx = (GL2Encoder*)self;
1257     GLClientState* state = ctx->m_state;
1258     GLenum err;
1259 
1260     SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1261 
1262     ctx->m_glActiveTexture_enc(ctx, texture);
1263 }
1264 
s_glBindTexture(void * self,GLenum target,GLuint texture)1265 void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1266 {
1267     GL2Encoder* ctx = (GL2Encoder*)self;
1268     GLClientState* state = ctx->m_state;
1269     GLenum err;
1270     GLboolean firstUse;
1271 
1272     SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1273 
1274     if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1275         ctx->m_glBindTexture_enc(ctx, target, texture);
1276         return;
1277     }
1278 
1279     GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1280 
1281     if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1282         ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1283         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1284                 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1285         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1286                 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1287         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1288                 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1289 
1290         if (target != priorityTarget) {
1291             ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1292                     state->getBoundTexture(GL_TEXTURE_2D));
1293         }
1294     }
1295 
1296     if (target == priorityTarget) {
1297         ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1298     }
1299 }
1300 
s_glDeleteTextures(void * self,GLsizei n,const GLuint * textures)1301 void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1302 {
1303     GL2Encoder* ctx = (GL2Encoder*)self;
1304     GLClientState* state = ctx->m_state;
1305 
1306     state->deleteTextures(n, textures);
1307     ctx->m_glDeleteTextures_enc(ctx, n, textures);
1308 }
1309 
s_glGetTexParameterfv(void * self,GLenum target,GLenum pname,GLfloat * params)1310 void GL2Encoder::s_glGetTexParameterfv(void* self,
1311         GLenum target, GLenum pname, GLfloat* params)
1312 {
1313     GL2Encoder* ctx = (GL2Encoder*)self;
1314     const GLClientState* state = ctx->m_state;
1315 
1316     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1317         ctx->override2DTextureTarget(target);
1318         ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
1319         ctx->restore2DTextureTarget(target);
1320     } else {
1321         ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1322     }
1323 }
1324 
s_glGetTexParameteriv(void * self,GLenum target,GLenum pname,GLint * params)1325 void GL2Encoder::s_glGetTexParameteriv(void* self,
1326         GLenum target, GLenum pname, GLint* params)
1327 {
1328     GL2Encoder* ctx = (GL2Encoder*)self;
1329     const GLClientState* state = ctx->m_state;
1330 
1331     switch (pname) {
1332     case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1333         *params = 1;
1334         break;
1335 
1336     default:
1337         if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1338             ctx->override2DTextureTarget(target);
1339             ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
1340             ctx->restore2DTextureTarget(target);
1341         } else {
1342             ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1343         }
1344         break;
1345     }
1346 }
1347 
isValidTextureExternalParam(GLenum pname,GLenum param)1348 static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1349 {
1350     switch (pname) {
1351     case GL_TEXTURE_MIN_FILTER:
1352     case GL_TEXTURE_MAG_FILTER:
1353         return param == GL_NEAREST || param == GL_LINEAR;
1354 
1355     case GL_TEXTURE_WRAP_S:
1356     case GL_TEXTURE_WRAP_T:
1357         return param == GL_CLAMP_TO_EDGE;
1358 
1359     default:
1360         return true;
1361     }
1362 }
1363 
s_glTexParameterf(void * self,GLenum target,GLenum pname,GLfloat param)1364 void GL2Encoder::s_glTexParameterf(void* self,
1365         GLenum target, GLenum pname, GLfloat param)
1366 {
1367     GL2Encoder* ctx = (GL2Encoder*)self;
1368     const GLClientState* state = ctx->m_state;
1369 
1370     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1371             !isValidTextureExternalParam(pname, (GLenum)param)),
1372             GL_INVALID_ENUM);
1373 
1374     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1375         ctx->override2DTextureTarget(target);
1376         ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
1377         ctx->restore2DTextureTarget(target);
1378     } else {
1379         ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1380     }
1381 }
1382 
s_glTexParameterfv(void * self,GLenum target,GLenum pname,const GLfloat * params)1383 void GL2Encoder::s_glTexParameterfv(void* self,
1384         GLenum target, GLenum pname, const GLfloat* params)
1385 {
1386     GL2Encoder* ctx = (GL2Encoder*)self;
1387     const GLClientState* state = ctx->m_state;
1388 
1389     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1390             !isValidTextureExternalParam(pname, (GLenum)params[0])),
1391             GL_INVALID_ENUM);
1392 
1393     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1394         ctx->override2DTextureTarget(target);
1395         ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
1396         ctx->restore2DTextureTarget(target);
1397     } else {
1398         ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1399     }
1400 }
1401 
s_glTexParameteri(void * self,GLenum target,GLenum pname,GLint param)1402 void GL2Encoder::s_glTexParameteri(void* self,
1403         GLenum target, GLenum pname, GLint param)
1404 {
1405     GL2Encoder* ctx = (GL2Encoder*)self;
1406     const GLClientState* state = ctx->m_state;
1407 
1408     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1409             !isValidTextureExternalParam(pname, (GLenum)param)),
1410             GL_INVALID_ENUM);
1411 
1412     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1413         ctx->override2DTextureTarget(target);
1414         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
1415         ctx->restore2DTextureTarget(target);
1416     } else {
1417         ctx->m_glTexParameteri_enc(ctx, target, pname, param);
1418     }
1419 }
1420 
s_glTexImage2D(void * self,GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const GLvoid * pixels)1421 void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
1422         GLint internalformat, GLsizei width, GLsizei height, GLint border,
1423         GLenum format, GLenum type, const GLvoid* pixels)
1424 {
1425     GL2Encoder* ctx = (GL2Encoder*)self;
1426     GLClientState* state = ctx->m_state;
1427     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1428         ctx->override2DTextureTarget(target);
1429         state->setBoundTextureInternalFormat(target, internalformat);
1430         state->setBoundTextureFormat(target, format);
1431         state->setBoundTextureType(target, type);
1432 
1433         ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1434                 height, border, format, type, pixels);
1435         ctx->restore2DTextureTarget(target);
1436     } else {
1437         ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1438                 height, border, format, type, pixels);
1439     }
1440 }
1441 
s_glTexSubImage2D(void * self,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)1442 void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
1443         GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
1444         GLenum type, const GLvoid* pixels)
1445 {
1446     GL2Encoder* ctx = (GL2Encoder*)self;
1447 
1448     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1449         ctx->override2DTextureTarget(target);
1450         ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
1451                 height, format, type, pixels);
1452         ctx->restore2DTextureTarget(target);
1453     } else {
1454         ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
1455                 height, format, type, pixels);
1456     }
1457 }
1458 
s_glCopyTexImage2D(void * self,GLenum target,GLint level,GLenum internalformat,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)1459 void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
1460         GLenum internalformat, GLint x, GLint y,
1461         GLsizei width, GLsizei height, GLint border)
1462 {
1463     GL2Encoder* ctx = (GL2Encoder*)self;
1464     GLClientState* state = ctx->m_state;
1465 
1466     // This is needed to work around underlying OpenGL drivers
1467     // (such as those feeding some some AMD GPUs) that expect
1468     // positive components of cube maps to be defined _before_
1469     // the negative components (otherwise a segfault occurs).
1470     GLenum extraTarget =
1471         state->copyTexImageLuminanceCubeMapAMDWorkaround
1472             (target, level, internalformat);
1473 
1474     if (extraTarget) {
1475         ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
1476                                     x, y, width, height, border);
1477     }
1478 
1479     ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
1480                                 x, y, width, height, border);
1481 }
1482 
s_glTexParameteriv(void * self,GLenum target,GLenum pname,const GLint * params)1483 void GL2Encoder::s_glTexParameteriv(void* self,
1484         GLenum target, GLenum pname, const GLint* params)
1485 {
1486     GL2Encoder* ctx = (GL2Encoder*)self;
1487     const GLClientState* state = ctx->m_state;
1488 
1489     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1490             !isValidTextureExternalParam(pname, (GLenum)params[0])),
1491             GL_INVALID_ENUM);
1492 
1493     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1494         ctx->override2DTextureTarget(target);
1495         ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
1496         ctx->restore2DTextureTarget(target);
1497     } else {
1498         ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
1499     }
1500 }
1501 
texture2DNeedsOverride(GLenum target) const1502 bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
1503     return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
1504            target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1505 }
1506 
override2DTextureTarget(GLenum target)1507 void GL2Encoder::override2DTextureTarget(GLenum target)
1508 {
1509     if (texture2DNeedsOverride(target)) {
1510         m_glBindTexture_enc(this, GL_TEXTURE_2D,
1511                 m_state->getBoundTexture(target));
1512     }
1513 }
1514 
restore2DTextureTarget(GLenum target)1515 void GL2Encoder::restore2DTextureTarget(GLenum target)
1516 {
1517     if (texture2DNeedsOverride(target)) {
1518         m_glBindTexture_enc(this, GL_TEXTURE_2D,
1519                 m_state->getBoundTexture(
1520                     m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)));
1521     }
1522 }
1523 
s_glGenRenderbuffers(void * self,GLsizei n,GLuint * renderbuffers)1524 void GL2Encoder::s_glGenRenderbuffers(void* self,
1525         GLsizei n, GLuint* renderbuffers) {
1526     GL2Encoder* ctx = (GL2Encoder*)self;
1527     GLClientState* state = ctx->m_state;
1528 
1529     SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1530 
1531     ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
1532     state->addRenderbuffers(n, renderbuffers);
1533 }
1534 
s_glDeleteRenderbuffers(void * self,GLsizei n,const GLuint * renderbuffers)1535 void GL2Encoder::s_glDeleteRenderbuffers(void* self,
1536         GLsizei n, const GLuint* renderbuffers) {
1537     GL2Encoder* ctx = (GL2Encoder*)self;
1538     GLClientState* state = ctx->m_state;
1539 
1540     SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1541 
1542     ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
1543     state->removeRenderbuffers(n, renderbuffers);
1544 }
1545 
s_glBindRenderbuffer(void * self,GLenum target,GLuint renderbuffer)1546 void GL2Encoder::s_glBindRenderbuffer(void* self,
1547         GLenum target, GLuint renderbuffer) {
1548     GL2Encoder* ctx = (GL2Encoder*)self;
1549     GLClientState* state = ctx->m_state;
1550 
1551     SET_ERROR_IF((target != GL_RENDERBUFFER),
1552                  GL_INVALID_ENUM);
1553 
1554     ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
1555     state->bindRenderbuffer(target, renderbuffer);
1556 }
1557 
s_glRenderbufferStorage(void * self,GLenum target,GLenum internalformat,GLsizei width,GLsizei height)1558 void GL2Encoder::s_glRenderbufferStorage(void* self,
1559         GLenum target, GLenum internalformat,
1560         GLsizei width, GLsizei height) {
1561     GL2Encoder* ctx = (GL2Encoder*) self;
1562     GLClientState* state = ctx->m_state;
1563 
1564     SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
1565     switch (internalformat) {
1566     // Funny internal formats
1567     // that will cause an incomplete framebuffer
1568     // attachment error. For dEQP,
1569     // we can also just abort early here in
1570     // RenderbufferStorage with a GL_INVALID_ENUM.
1571     case GL_DEPTH_COMPONENT32F:
1572     case GL_R8:
1573     case GL_R8UI:
1574     case GL_R8I:
1575     case GL_R16UI:
1576     case GL_R16I:
1577     case GL_R32UI:
1578     case GL_R32I:
1579     case GL_RG8:
1580     case GL_RG8UI:
1581     case GL_RG8I:
1582     case GL_RG16UI:
1583     case GL_RG16I:
1584     case GL_RG32UI:
1585     case GL_RG32I:
1586     case GL_SRGB8_ALPHA8:
1587     case GL_RGBA8UI:
1588     case GL_RGBA8I:
1589     case GL_RGB10_A2UI:
1590     case GL_RGBA16UI:
1591     case GL_RGBA16I:
1592     case GL_RGBA32I:
1593     case GL_RGBA32UI:
1594     case GL_R11F_G11F_B10F:
1595     case GL_R32F:
1596     case GL_RG32F:
1597     case GL_RGB32F:
1598     case GL_RGBA32F:
1599         SET_ERROR_IF(true, GL_INVALID_ENUM);
1600         break;
1601     // These 4 formats are still not OK,
1602     // but dEQP expects GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT or
1603     // GL_FRAMEBUFFER_UNSUPPORTED,
1604     // not a GL_INVALID_ENUM from earlier on.
1605     // So let's forward these to the rest of
1606     // FBO initialization
1607     case GL_R16F:
1608     case GL_RG16F:
1609     case GL_RGB16F:
1610     case GL_RGBA16F:
1611     // dEQP expects GL_FRAMEBUFFER_UNSUPPORTED or GL_FRAMEBUFFER_COMPLETE
1612     // for this format
1613     case GL_RGB10_A2:
1614     // These formats are OK
1615     case GL_DEPTH_COMPONENT16:
1616     case GL_DEPTH_COMPONENT24:
1617     case GL_DEPTH_COMPONENT32_OES:
1618     case GL_RGBA4:
1619     case GL_RGB5_A1:
1620     case GL_RGB565:
1621     case GL_RGB8_OES:
1622     case GL_RGBA8_OES:
1623     case GL_STENCIL_INDEX8:
1624     case GL_DEPTH32F_STENCIL8:
1625     case GL_DEPTH24_STENCIL8_OES:
1626         break;
1627     // Everything else: still not OK,
1628     // and they need the GL_INVALID_ENUM
1629     default:
1630         SET_ERROR_IF(true, GL_INVALID_ENUM);
1631     }
1632 
1633     state->setBoundRenderbufferFormat(internalformat);
1634     ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
1635                                      width, height);
1636 }
1637 
s_glFramebufferRenderbuffer(void * self,GLenum target,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)1638 void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
1639         GLenum target, GLenum attachment,
1640         GLenum renderbuffertarget, GLuint renderbuffer) {
1641     GL2Encoder* ctx = (GL2Encoder*)self;
1642     GLClientState* state = ctx->m_state;
1643 
1644     state->attachRbo(attachment, renderbuffer);
1645 
1646     ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
1647 }
1648 
s_glGenFramebuffers(void * self,GLsizei n,GLuint * framebuffers)1649 void GL2Encoder::s_glGenFramebuffers(void* self,
1650         GLsizei n, GLuint* framebuffers) {
1651     GL2Encoder* ctx = (GL2Encoder*)self;
1652     GLClientState* state = ctx->m_state;
1653 
1654     SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1655 
1656     ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
1657     state->addFramebuffers(n, framebuffers);
1658 }
1659 
s_glDeleteFramebuffers(void * self,GLsizei n,const GLuint * framebuffers)1660 void GL2Encoder::s_glDeleteFramebuffers(void* self,
1661         GLsizei n, const GLuint* framebuffers) {
1662     GL2Encoder* ctx = (GL2Encoder*)self;
1663     GLClientState* state = ctx->m_state;
1664 
1665     SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1666 
1667     ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
1668     state->removeFramebuffers(n, framebuffers);
1669 }
1670 
s_glBindFramebuffer(void * self,GLenum target,GLuint framebuffer)1671 void GL2Encoder::s_glBindFramebuffer(void* self,
1672         GLenum target, GLuint framebuffer) {
1673     GL2Encoder* ctx = (GL2Encoder*)self;
1674     GLClientState* state = ctx->m_state;
1675 
1676     SET_ERROR_IF((target != GL_FRAMEBUFFER),
1677                  GL_INVALID_ENUM);
1678 
1679     state->bindFramebuffer(target, framebuffer);
1680 
1681     ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
1682 }
1683 
s_glFramebufferTexture2D(void * self,GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)1684 void GL2Encoder::s_glFramebufferTexture2D(void* self,
1685         GLenum target, GLenum attachment,
1686         GLenum textarget, GLuint texture, GLint level) {
1687     GL2Encoder* ctx = (GL2Encoder*)self;
1688     GLClientState* state = ctx->m_state;
1689 
1690     state->attachTextureObject(attachment, texture);
1691 
1692     ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
1693 }
1694 
s_glFramebufferTexture3DOES(void * self,GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLint zoffset)1695 void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
1696         GLenum target, GLenum attachment,
1697         GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
1698     GL2Encoder* ctx = (GL2Encoder*)self;
1699     GLClientState* state = ctx->m_state;
1700 
1701     state->attachTextureObject(attachment, texture);
1702 
1703     ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
1704 }
1705 
s_glGetFramebufferAttachmentParameteriv(void * self,GLenum target,GLenum attachment,GLenum pname,GLint * params)1706 void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
1707         GLenum target, GLenum attachment, GLenum pname, GLint* params) {
1708     GL2Encoder* ctx = (GL2Encoder*)self;
1709     const GLClientState* state = ctx->m_state;
1710 
1711     SET_ERROR_IF(state->boundFramebuffer() == 0,
1712                  GL_INVALID_OPERATION);
1713     SET_ERROR_IF((pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) &&
1714                  (!state->attachmentHasObject(attachment)),
1715                  GL_INVALID_ENUM);
1716 
1717     ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
1718 }
1719 
isCompleteFbo(const GLClientState * state,GLenum attachment) const1720 bool GL2Encoder::isCompleteFbo(const GLClientState* state,
1721                                GLenum attachment) const {
1722     FboFormatInfo fbo_format_info;
1723     state->getBoundFramebufferFormat(attachment, &fbo_format_info);
1724 
1725     bool res;
1726     switch (fbo_format_info.type) {
1727     case FBO_ATTACHMENT_RENDERBUFFER:
1728         switch (fbo_format_info.rb_format) {
1729         case GL_R16F:
1730         case GL_RG16F:
1731         case GL_RGB16F:
1732         case GL_RGBA16F:
1733             res = false;
1734             break;
1735         case GL_STENCIL_INDEX8:
1736             if (attachment == GL_STENCIL_ATTACHMENT) {
1737                 res = true;
1738             } else {
1739                 res = false;
1740             }
1741             break;
1742         default:
1743             res = true;
1744         }
1745         break;
1746     case FBO_ATTACHMENT_TEXTURE:
1747         switch (fbo_format_info.tex_internalformat) {
1748         case GL_RED:
1749         case GL_RG:
1750         case GL_R16F:
1751         case GL_RG16F:
1752         case GL_RGBA16F:
1753         case GL_RGB16F:
1754         case GL_R11F_G11F_B10F:
1755             res = false;
1756             break;
1757         // No float/half-float formats allowed for RGB(A)
1758         case GL_RGB:
1759         case GL_RGBA:
1760             switch (fbo_format_info.tex_type) {
1761             case GL_FLOAT:
1762             case GL_HALF_FLOAT_OES:
1763             case GL_UNSIGNED_INT_10F_11F_11F_REV:
1764                 res = false;
1765                 break;
1766             default:
1767                 res = true;
1768             }
1769             break;
1770         default:
1771             res = true;
1772         }
1773         break;
1774     case FBO_ATTACHMENT_NONE:
1775         res = true;
1776         break;
1777     default:
1778         res = true;
1779     }
1780     return res;
1781 }
1782 
s_glCheckFramebufferStatus(void * self,GLenum target)1783 GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
1784     GL2Encoder* ctx = (GL2Encoder*)self;
1785     GLClientState* state = ctx->m_state;
1786 
1787     bool complete = ctx->isCompleteFbo(state, GL_COLOR_ATTACHMENT0) &&
1788                     ctx->isCompleteFbo(state, GL_DEPTH_ATTACHMENT) &&
1789                     ctx->isCompleteFbo(state, GL_STENCIL_ATTACHMENT);
1790     if (!complete) {
1791         state->setCheckFramebufferStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
1792         return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1793     } else {
1794         GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
1795         state->setCheckFramebufferStatus(host_checkstatus);
1796         return host_checkstatus;
1797     }
1798 }
1799