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 #include <cmath>
21 
22 #ifndef MIN
23 #define MIN(a, b) ((a) < (b) ? (a) : (b))
24 #endif
25 
26 static GLubyte *gVendorString= (GLubyte *) "Android";
27 static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 2.0";
28 static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 2.0";
29 static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external ";
30 
31 #define SET_ERROR_IF(condition,err) if((condition)) {                            \
32         ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
33         ctx->setError(err);                                    \
34         return;                                                  \
35     }
36 
37 
38 #define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) {                \
39         ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
40         ctx->setError(err);                                    \
41         return ret;                                              \
42     }
43 
44 
GL2Encoder(IOStream * stream,ChecksumCalculator * protocol)45 GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
46         : gl2_encoder_context_t(stream, protocol)
47 {
48     m_initialized = false;
49     m_state = NULL;
50     m_error = GL_NO_ERROR;
51     m_num_compressedTextureFormats = 0;
52     m_max_cubeMapTextureSize = 0;
53     m_max_renderBufferSize = 0;
54     m_max_textureSize = 0;
55     m_compressedTextureFormats = NULL;
56 
57     //overrides
58 #define OVERRIDE(name)  m_##name##_enc = this-> name ; this-> name = &s_##name
59 
60     OVERRIDE(glFlush);
61     OVERRIDE(glPixelStorei);
62     OVERRIDE(glGetString);
63     OVERRIDE(glBindBuffer);
64     OVERRIDE(glBufferData);
65     OVERRIDE(glBufferSubData);
66     OVERRIDE(glDeleteBuffers);
67     OVERRIDE(glDrawArrays);
68     OVERRIDE(glDrawElements);
69     OVERRIDE(glGetIntegerv);
70     OVERRIDE(glGetFloatv);
71     OVERRIDE(glGetBooleanv);
72     OVERRIDE(glVertexAttribPointer);
73     OVERRIDE(glEnableVertexAttribArray);
74     OVERRIDE(glDisableVertexAttribArray);
75     OVERRIDE(glGetVertexAttribiv);
76     OVERRIDE(glGetVertexAttribfv);
77     OVERRIDE(glGetVertexAttribPointerv);
78 
79     this->glShaderBinary = &s_glShaderBinary;
80     this->glShaderSource = &s_glShaderSource;
81     this->glFinish = &s_glFinish;
82 
83     OVERRIDE(glGetError);
84     OVERRIDE(glLinkProgram);
85     OVERRIDE(glDeleteProgram);
86     OVERRIDE(glGetUniformiv);
87     OVERRIDE(glGetUniformfv);
88     OVERRIDE(glCreateProgram);
89     OVERRIDE(glCreateShader);
90     OVERRIDE(glDeleteShader);
91     OVERRIDE(glAttachShader);
92     OVERRIDE(glDetachShader);
93     OVERRIDE(glGetAttachedShaders);
94     OVERRIDE(glGetShaderSource);
95     OVERRIDE(glGetShaderInfoLog);
96     OVERRIDE(glGetProgramInfoLog);
97 
98     OVERRIDE(glGetUniformLocation);
99     OVERRIDE(glUseProgram);
100 
101     OVERRIDE(glUniform1f);
102     OVERRIDE(glUniform1fv);
103     OVERRIDE(glUniform1i);
104     OVERRIDE(glUniform1iv);
105     OVERRIDE(glUniform2f);
106     OVERRIDE(glUniform2fv);
107     OVERRIDE(glUniform2i);
108     OVERRIDE(glUniform2iv);
109     OVERRIDE(glUniform3f);
110     OVERRIDE(glUniform3fv);
111     OVERRIDE(glUniform3i);
112     OVERRIDE(glUniform3iv);
113     OVERRIDE(glUniform4f);
114     OVERRIDE(glUniform4fv);
115     OVERRIDE(glUniform4i);
116     OVERRIDE(glUniform4iv);
117     OVERRIDE(glUniformMatrix2fv);
118     OVERRIDE(glUniformMatrix3fv);
119     OVERRIDE(glUniformMatrix4fv);
120 
121     OVERRIDE(glActiveTexture);
122     OVERRIDE(glBindTexture);
123     OVERRIDE(glDeleteTextures);
124     OVERRIDE(glGetTexParameterfv);
125     OVERRIDE(glGetTexParameteriv);
126     OVERRIDE(glTexParameterf);
127     OVERRIDE(glTexParameterfv);
128     OVERRIDE(glTexParameteri);
129     OVERRIDE(glTexParameteriv);
130     OVERRIDE(glTexImage2D);
131     OVERRIDE(glTexSubImage2D);
132 }
133 
~GL2Encoder()134 GL2Encoder::~GL2Encoder()
135 {
136     delete m_compressedTextureFormats;
137 }
138 
s_glGetError(void * self)139 GLenum GL2Encoder::s_glGetError(void * self)
140 {
141     GL2Encoder *ctx = (GL2Encoder *)self;
142     GLenum err = ctx->getError();
143     if(err != GL_NO_ERROR) {
144         ctx->setError(GL_NO_ERROR);
145         return err;
146     }
147 
148     return ctx->m_glGetError_enc(self);
149 
150 }
151 
s_glFlush(void * self)152 void GL2Encoder::s_glFlush(void *self)
153 {
154     GL2Encoder *ctx = (GL2Encoder *) self;
155     ctx->m_glFlush_enc(self);
156     ctx->m_stream->flush();
157 }
158 
s_glGetString(void * self,GLenum name)159 const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
160 {
161     (void)self;
162 
163     GLubyte *retval =  (GLubyte *) "";
164     switch(name) {
165     case GL_VENDOR:
166         retval = gVendorString;
167         break;
168     case GL_RENDERER:
169         retval = gRendererString;
170         break;
171     case GL_VERSION:
172         retval = gVersionString;
173         break;
174     case GL_EXTENSIONS:
175         retval = gExtensionsString;
176         break;
177     }
178     return retval;
179 }
180 
s_glPixelStorei(void * self,GLenum param,GLint value)181 void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
182 {
183     GL2Encoder *ctx = (GL2Encoder *)self;
184     ctx->m_glPixelStorei_enc(ctx, param, value);
185     assert(ctx->m_state != NULL);
186     ctx->m_state->setPixelStore(param, value);
187 }
188 
189 
s_glBindBuffer(void * self,GLenum target,GLuint id)190 void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
191 {
192     GL2Encoder *ctx = (GL2Encoder *) self;
193     assert(ctx->m_state != NULL);
194     ctx->m_state->bindBuffer(target, id);
195     // TODO set error state if needed;
196     ctx->m_glBindBuffer_enc(self, target, id);
197 }
198 
s_glBufferData(void * self,GLenum target,GLsizeiptr size,const GLvoid * data,GLenum usage)199 void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
200 {
201     GL2Encoder *ctx = (GL2Encoder *) self;
202     SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
203     GLuint bufferId = ctx->m_state->getBuffer(target);
204     SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
205     SET_ERROR_IF(size<0, GL_INVALID_VALUE);
206 
207     ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
208     ctx->m_glBufferData_enc(self, target, size, data, usage);
209 }
210 
s_glBufferSubData(void * self,GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid * data)211 void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
212 {
213     GL2Encoder *ctx = (GL2Encoder *) self;
214     SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
215     GLuint bufferId = ctx->m_state->getBuffer(target);
216     SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
217 
218     GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
219     SET_ERROR_IF(res, res);
220 
221     ctx->m_glBufferSubData_enc(self, target, offset, size, data);
222 }
223 
s_glDeleteBuffers(void * self,GLsizei n,const GLuint * buffers)224 void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
225 {
226     GL2Encoder *ctx = (GL2Encoder *) self;
227     SET_ERROR_IF(n<0, GL_INVALID_VALUE);
228     for (int i=0; i<n; i++) {
229         ctx->m_shared->deleteBufferData(buffers[i]);
230         ctx->m_state->unBindBuffer(buffers[i]);
231         ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
232     }
233 }
234 
s_glVertexAttribPointer(void * self,GLuint indx,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid * ptr)235 void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
236 {
237     GL2Encoder *ctx = (GL2Encoder *)self;
238     assert(ctx->m_state != NULL);
239     ctx->m_state->setState(indx, size, type, normalized, stride, ptr);
240 }
241 
s_glGetIntegerv(void * self,GLenum param,GLint * ptr)242 void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
243 {
244     GL2Encoder *ctx = (GL2Encoder *) self;
245     assert(ctx->m_state != NULL);
246     GLClientState* state = ctx->m_state;
247 
248     switch (param) {
249     case GL_NUM_SHADER_BINARY_FORMATS:
250         *ptr = 0;
251         break;
252     case GL_SHADER_BINARY_FORMATS:
253         // do nothing
254         break;
255 
256     case GL_COMPRESSED_TEXTURE_FORMATS: {
257         GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
258         if (ctx->m_num_compressedTextureFormats > 0 &&
259                 compressedTextureFormats != NULL) {
260             memcpy(ptr, compressedTextureFormats,
261                     ctx->m_num_compressedTextureFormats * sizeof(GLint));
262         }
263         break;
264     }
265 
266     case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
267     case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
268     case GL_MAX_TEXTURE_IMAGE_UNITS:
269         ctx->m_glGetIntegerv_enc(self, param, ptr);
270         *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
271         break;
272 
273     case GL_TEXTURE_BINDING_2D:
274         *ptr = state->getBoundTexture(GL_TEXTURE_2D);
275         break;
276     case GL_TEXTURE_BINDING_EXTERNAL_OES:
277         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
278         break;
279 
280     case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
281         if (ctx->m_max_cubeMapTextureSize != 0) {
282             *ptr = ctx->m_max_cubeMapTextureSize;
283         } else {
284             ctx->m_glGetIntegerv_enc(self, param, ptr);
285             ctx->m_max_cubeMapTextureSize = *ptr;
286         }
287         break;
288     case GL_MAX_RENDERBUFFER_SIZE:
289         if (ctx->m_max_renderBufferSize != 0) {
290             *ptr = ctx->m_max_renderBufferSize;
291         } else {
292             ctx->m_glGetIntegerv_enc(self, param, ptr);
293             ctx->m_max_renderBufferSize = *ptr;
294         }
295         break;
296     case GL_MAX_TEXTURE_SIZE:
297         if (ctx->m_max_textureSize != 0) {
298             *ptr = ctx->m_max_textureSize;
299         } else {
300             ctx->m_glGetIntegerv_enc(self, param, ptr);
301             ctx->m_max_textureSize = *ptr;
302         }
303         break;
304     case GL_MAX_VERTEX_ATTRIBS:
305         if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
306             ctx->m_glGetIntegerv_enc(self, param, ptr);
307             ctx->m_state->setMaxVertexAttribs(*ptr);
308         }
309         break;
310     default:
311         if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
312             ctx->m_glGetIntegerv_enc(self, param, ptr);
313         }
314         break;
315     }
316 }
317 
318 
s_glGetFloatv(void * self,GLenum param,GLfloat * ptr)319 void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
320 {
321     GL2Encoder *ctx = (GL2Encoder *)self;
322     assert(ctx->m_state != NULL);
323     GLClientState* state = ctx->m_state;
324 
325     switch (param) {
326     case GL_NUM_SHADER_BINARY_FORMATS:
327         *ptr = 0;
328         break;
329     case GL_SHADER_BINARY_FORMATS:
330         // do nothing
331         break;
332 
333     case GL_COMPRESSED_TEXTURE_FORMATS: {
334         GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
335         if (ctx->m_num_compressedTextureFormats > 0 &&
336                 compressedTextureFormats != NULL) {
337             for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
338                 ptr[i] = (GLfloat) compressedTextureFormats[i];
339             }
340         }
341         break;
342     }
343 
344     case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
345     case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
346     case GL_MAX_TEXTURE_IMAGE_UNITS:
347         ctx->m_glGetFloatv_enc(self, param, ptr);
348         *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
349         break;
350 
351     case GL_TEXTURE_BINDING_2D:
352         *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
353         break;
354     case GL_TEXTURE_BINDING_EXTERNAL_OES:
355         *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
356         break;
357 
358     default:
359         if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
360             ctx->m_glGetFloatv_enc(self, param, ptr);
361         }
362         break;
363     }
364 }
365 
366 
s_glGetBooleanv(void * self,GLenum param,GLboolean * ptr)367 void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
368 {
369     GL2Encoder *ctx = (GL2Encoder *)self;
370     assert(ctx->m_state != NULL);
371     GLClientState* state = ctx->m_state;
372 
373     switch (param) {
374     case GL_NUM_SHADER_BINARY_FORMATS:
375         *ptr = GL_FALSE;
376         break;
377     case GL_SHADER_BINARY_FORMATS:
378         // do nothing
379         break;
380 
381     case GL_COMPRESSED_TEXTURE_FORMATS: {
382         GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
383         if (ctx->m_num_compressedTextureFormats > 0 &&
384                 compressedTextureFormats != NULL) {
385             for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
386                 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
387             }
388         }
389         break;
390     }
391 
392     case GL_TEXTURE_BINDING_2D:
393         *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
394         break;
395     case GL_TEXTURE_BINDING_EXTERNAL_OES:
396         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
397                 ? GL_TRUE : GL_FALSE;
398         break;
399 
400     default:
401         if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
402             ctx->m_glGetBooleanv_enc(self, param, ptr);
403         }
404         *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
405         break;
406     }
407 }
408 
409 
s_glEnableVertexAttribArray(void * self,GLuint index)410 void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
411 {
412     GL2Encoder *ctx = (GL2Encoder *)self;
413     assert(ctx->m_state);
414     GLint maxIndex;
415     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
416     SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
417     ctx->m_state->enable(index, 1);
418 }
419 
s_glDisableVertexAttribArray(void * self,GLuint index)420 void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
421 {
422     GL2Encoder *ctx = (GL2Encoder *)self;
423     assert(ctx->m_state);
424     GLint maxIndex;
425     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
426     SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
427     ctx->m_state->enable(index, 0);
428 }
429 
430 
s_glGetVertexAttribiv(void * self,GLuint index,GLenum pname,GLint * params)431 void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
432 {
433     GL2Encoder *ctx = (GL2Encoder *)self;
434     assert(ctx->m_state);
435     GLint maxIndex;
436     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
437     SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
438 
439     if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
440         ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
441     }
442 }
443 
s_glGetVertexAttribfv(void * self,GLuint index,GLenum pname,GLfloat * params)444 void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
445 {
446     GL2Encoder *ctx = (GL2Encoder *)self;
447     assert(ctx->m_state);
448     GLint maxIndex;
449     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
450     SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
451 
452     if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
453         ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
454     }
455 }
456 
s_glGetVertexAttribPointerv(void * self,GLuint index,GLenum pname,GLvoid ** pointer)457 void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
458 {
459     GL2Encoder *ctx = (GL2Encoder *)self;
460     if (ctx->m_state == NULL) return;
461     GLint maxIndex;
462     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
463     SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
464     SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
465 
466     (void)pname;
467 
468     const GLClientState::VertexAttribState *va_state = ctx->m_state->getState(index);
469     if (va_state != NULL) {
470         *pointer = va_state->data;
471     }
472 }
473 
474 
sendVertexAttributes(GLint first,GLsizei count)475 void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count)
476 {
477     assert(m_state);
478 
479     for (int i = 0; i < m_state->nLocations(); i++) {
480         bool enableDirty;
481         const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty);
482 
483         if (!state) {
484             continue;
485         }
486 
487         if (!enableDirty && !state->enabled) {
488             continue;
489         }
490 
491 
492         if (state->enabled) {
493             m_glEnableVertexAttribArray_enc(this, i);
494 
495             unsigned int datalen = state->elementSize * count;
496             int stride = state->stride == 0 ? state->elementSize : state->stride;
497             int firstIndex = stride * first;
498 
499             this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject);
500             if (state->bufferObject == 0) {
501                 this->glVertexAttribPointerData(this, i, state->size, state->type, state->normalized, state->stride,
502                                                 (unsigned char *)state->data + firstIndex, datalen);
503             } else {
504                 this->glVertexAttribPointerOffset(this, i, state->size, state->type, state->normalized, state->stride,
505                                                   (uintptr_t) state->data + firstIndex);
506             }
507             this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
508         } else {
509             this->m_glDisableVertexAttribArray_enc(this, i);
510         }
511     }
512 }
513 
isValidDrawMode(GLenum mode)514 static bool isValidDrawMode(GLenum mode) {
515     switch(mode) {
516     case GL_POINTS:
517     case GL_LINE_STRIP:
518     case GL_LINE_LOOP:
519     case GL_LINES:
520     case GL_TRIANGLE_STRIP:
521     case GL_TRIANGLE_FAN:
522     case GL_TRIANGLES:
523         return true;
524     }
525     return false;
526 }
527 
isValidDrawType(GLenum mode)528 static bool isValidDrawType(GLenum mode) {
529     return  mode == GL_UNSIGNED_BYTE ||
530             mode == GL_UNSIGNED_SHORT ||
531             mode == GL_UNSIGNED_INT;
532 }
533 
s_glDrawArrays(void * self,GLenum mode,GLint first,GLsizei count)534 void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
535 {
536     GL2Encoder *ctx = (GL2Encoder *)self;
537 
538     SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
539     SET_ERROR_IF(count<0, GL_INVALID_VALUE);
540 
541     bool has_arrays = false;
542     int nLocations = ctx->m_state->nLocations();
543     for (int i = 0; i < nLocations; i++) {
544         const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
545         if (state->enabled) {
546             if (state->bufferObject || state->data)  {
547                 has_arrays = true;
548             }
549             else {
550                 ALOGE("glDrawArrays: a vertex attribute array is enabled with no data bound\n");
551                 ctx->setError(GL_INVALID_OPERATION);
552                 return;
553             }
554         }
555     }
556     if (!has_arrays) {
557         ALOGE("glDrawArrays: no data bound to the command - ignoring\n");
558         return;
559     }
560 
561     ctx->sendVertexAttributes(first, count);
562     ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
563 }
564 
s_glDrawElements(void * self,GLenum mode,GLsizei count,GLenum type,const void * indices)565 void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
566 {
567 
568     GL2Encoder *ctx = (GL2Encoder *)self;
569     assert(ctx->m_state != NULL);
570     SET_ERROR_IF(!(isValidDrawMode(mode) && isValidDrawType(type)),GL_INVALID_ENUM);
571     SET_ERROR_IF(count<0, GL_INVALID_VALUE);
572 
573     bool has_immediate_arrays = false;
574     bool has_indirect_arrays = false;
575     int nLocations = ctx->m_state->nLocations();
576 
577     for (int i = 0; i < nLocations; i++) {
578         const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
579         if (state->enabled) {
580             if (state->bufferObject != 0) {
581                 has_indirect_arrays = true;
582             } else if (state->data) {
583                 has_immediate_arrays = true;
584             } else {
585                 ALOGW("glDrawElements: a vertex attribute array is enabled with no data bound\n");
586                 ctx->setError(GL_INVALID_OPERATION);
587                 return;
588             }
589         }
590     }
591 
592     if (!has_immediate_arrays && !has_indirect_arrays) {
593         ALOGE("glDrawElements: no data bound to the command - ignoring\n");
594         return;
595     }
596 
597     bool adjustIndices = true;
598     if (ctx->m_state->currentIndexVbo() != 0) {
599         if (!has_immediate_arrays) {
600             ctx->sendVertexAttributes(0, count);
601             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
602             ctx->glDrawElementsOffset(ctx, mode, count, type, (uintptr_t)indices);
603             adjustIndices = false;
604         } else {
605             BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
606             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
607             indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
608         }
609     }
610     if (adjustIndices) {
611         void *adjustedIndices = (void*)indices;
612         int minIndex = 0, maxIndex = 0;
613 
614         switch(type) {
615         case GL_BYTE:
616         case GL_UNSIGNED_BYTE:
617             GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex);
618             if (minIndex != 0) {
619                 adjustedIndices =  ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
620                 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices,
621                                                  (unsigned char *)adjustedIndices,
622                                                  count, -minIndex);
623             }
624             break;
625         case GL_SHORT:
626         case GL_UNSIGNED_SHORT:
627             GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex);
628             if (minIndex != 0) {
629                 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
630                 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices,
631                                                   (unsigned short *)adjustedIndices,
632                                                   count, -minIndex);
633             }
634             break;
635         case GL_INT:
636         case GL_UNSIGNED_INT:
637             GLUtils::minmax<unsigned int>((unsigned int *)indices, count, &minIndex, &maxIndex);
638             if (minIndex != 0) {
639                 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
640                 GLUtils::shiftIndices<unsigned int>((unsigned int *)indices,
641                                                  (unsigned int *)adjustedIndices,
642                                                  count, -minIndex);
643             }
644             break;
645         default:
646             ALOGE("unsupported index buffer type %d\n", type);
647         }
648         if (has_indirect_arrays || 1) {
649             ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1);
650             ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
651                                     count * glSizeof(type));
652             // XXX - OPTIMIZATION (see the other else branch) should be implemented
653             if(!has_indirect_arrays) {
654                 //ALOGD("unoptimized drawelements !!!\n");
655             }
656         } else {
657             // we are all direct arrays and immidate mode index array -
658             // rebuild the arrays and the index array;
659             ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
660         }
661     }
662 }
663 
664 
getCompressedTextureFormats()665 GLint * GL2Encoder::getCompressedTextureFormats()
666 {
667     if (m_compressedTextureFormats == NULL) {
668         this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
669                             &m_num_compressedTextureFormats);
670         if (m_num_compressedTextureFormats > 0) {
671             // get number of texture formats;
672             m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
673             this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
674         }
675     }
676     return m_compressedTextureFormats;
677 }
678 
679 // Replace uses of samplerExternalOES with sampler2D, recording the names of
680 // modified shaders in data. Also remove
681 //   #extension GL_OES_EGL_image_external : require
682 // statements.
683 //
684 // This implementation assumes the input has already been pre-processed. If not,
685 // a few cases will be mishandled:
686 //
687 // 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
688 //    the following code:
689 //      #if 1
690 //      uniform sampler2D mySampler;
691 //      #else
692 //      uniform samplerExternalOES mySampler;
693 //      #endif
694 //
695 // 2. Comments that look like sampler declarations will be incorrectly modified
696 //    and recorded:
697 //      // samplerExternalOES hahaFooledYou
698 //
699 // 3. However, GLSL ES does not have a concatentation operator, so things like
700 //    this (valid in C) are invalid and not a problem:
701 //      #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
702 //      SAMPLER(ExternalOES, mySampler);
703 //
replaceSamplerExternalWith2D(char * const str,ShaderData * const data)704 static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
705 {
706     static const char STR_HASH_EXTENSION[] = "#extension";
707     static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
708     static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
709     static const char STR_SAMPLER2D_SPACE[]      = "sampler2D         ";
710 
711     // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
712     char* c = str;
713     while ((c = strstr(c, STR_HASH_EXTENSION))) {
714         char* start = c;
715         c += sizeof(STR_HASH_EXTENSION)-1;
716         while (isspace(*c) && *c != '\0') {
717             c++;
718         }
719         if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
720                 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
721         {
722             // #extension statements are terminated by end of line
723             c = start;
724             while (*c != '\0' && *c != '\r' && *c != '\n') {
725                 *c++ = ' ';
726             }
727         }
728     }
729 
730     // -- replace "samplerExternalOES" with "sampler2D" and record name
731     c = str;
732     while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
733         // Make sure "samplerExternalOES" isn't a substring of a larger token
734         if (c == str || !isspace(*(c-1))) {
735             c++;
736             continue;
737         }
738         char* sampler_start = c;
739         c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
740         if (!isspace(*c) && *c != '\0') {
741             continue;
742         }
743 
744         // capture sampler name
745         while (isspace(*c) && *c != '\0') {
746             c++;
747         }
748         if (!isalpha(*c) && *c != '_') {
749             // not an identifier
750             return false;
751         }
752         char* name_start = c;
753         do {
754             c++;
755         } while (isalnum(*c) || *c == '_');
756         data->samplerExternalNames.push_back(
757                 android::String8(name_start, c - name_start));
758 
759         // memcpy instead of strcpy since we don't want the NUL terminator
760         memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
761     }
762 
763     return true;
764 }
765 
s_glShaderBinary(void * self,GLsizei n,const GLuint * shaders,GLenum binaryformat,const void * binary,GLsizei length)766 void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
767 {
768     GL2Encoder* ctx = (GL2Encoder*)self;
769     // Although it is not supported, need to set proper error code.
770     SET_ERROR_IF(1, GL_INVALID_ENUM);
771 }
772 
s_glShaderSource(void * self,GLuint shader,GLsizei count,const GLchar * const * string,const GLint * length)773 void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
774 {
775     GL2Encoder* ctx = (GL2Encoder*)self;
776     ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
777     SET_ERROR_IF(!ctx->m_shared->isObject(shader), GL_INVALID_VALUE);
778     SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
779     SET_ERROR_IF((count<0), GL_INVALID_VALUE);
780 
781     int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
782     char *str = new char[len + 1];
783     glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
784 
785     // TODO: pre-process str before calling replaceSamplerExternalWith2D().
786     // Perhaps we can borrow Mesa's pre-processor?
787 
788     if (!replaceSamplerExternalWith2D(str, shaderData)) {
789         delete str;
790         ctx->setError(GL_OUT_OF_MEMORY);
791         return;
792     }
793 
794     ctx->glShaderString(ctx, shader, str, len + 1);
795     delete str;
796 }
797 
s_glFinish(void * self)798 void GL2Encoder::s_glFinish(void *self)
799 {
800     GL2Encoder *ctx = (GL2Encoder *)self;
801     ctx->glFinishRoundTrip(self);
802 }
803 
s_glLinkProgram(void * self,GLuint program)804 void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
805 {
806     GL2Encoder *ctx = (GL2Encoder *)self;
807     ctx->m_glLinkProgram_enc(self, program);
808 
809     GLint linkStatus = 0;
810     ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
811     if (!linkStatus)
812         return;
813 
814     //get number of active uniforms in the program
815     GLint numUniforms=0;
816     ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
817     ctx->m_shared->initProgramData(program,numUniforms);
818 
819     //get the length of the longest uniform name
820     GLint maxLength=0;
821     ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
822 
823     GLint size;
824     GLenum type;
825     GLchar *name = new GLchar[maxLength+1];
826     GLint location;
827     //for each active uniform, get its size and starting location.
828     for (GLint i=0 ; i<numUniforms ; ++i)
829     {
830         ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
831         location = ctx->m_glGetUniformLocation_enc(self, program, name);
832         ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
833     }
834     ctx->m_shared->setupLocationShiftWAR(program);
835 
836     delete[] name;
837 }
838 
s_glDeleteProgram(void * self,GLuint program)839 void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
840 {
841     GL2Encoder *ctx = (GL2Encoder*)self;
842     ctx->m_glDeleteProgram_enc(self, program);
843 
844     ctx->m_shared->deleteProgramData(program);
845 }
846 
s_glGetUniformiv(void * self,GLuint program,GLint location,GLint * params)847 void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
848 {
849     GL2Encoder *ctx = (GL2Encoder*)self;
850     SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
851     SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
852     SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
853     GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
854     SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
855     ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
856 }
s_glGetUniformfv(void * self,GLuint program,GLint location,GLfloat * params)857 void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
858 {
859     GL2Encoder *ctx = (GL2Encoder*)self;
860     SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
861     SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
862     SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
863     GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
864     SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
865     ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
866 }
867 
s_glCreateProgram(void * self)868 GLuint GL2Encoder::s_glCreateProgram(void * self)
869 {
870     GL2Encoder *ctx = (GL2Encoder*)self;
871     GLuint program = ctx->m_glCreateProgram_enc(self);
872     if (program!=0)
873         ctx->m_shared->addProgramData(program);
874     return program;
875 }
876 
s_glCreateShader(void * self,GLenum shaderType)877 GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
878 {
879     GL2Encoder *ctx = (GL2Encoder*)self;
880     RET_AND_SET_ERROR_IF(((shaderType != GL_VERTEX_SHADER) && (shaderType != GL_FRAGMENT_SHADER)),
881         GL_INVALID_ENUM, 0);
882     GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
883     if (shader != 0) {
884         if (!ctx->m_shared->addShaderData(shader)) {
885             ctx->m_glDeleteShader_enc(self, shader);
886             return 0;
887         }
888     }
889     return shader;
890 }
891 
s_glGetAttachedShaders(void * self,GLuint program,GLsizei maxCount,GLsizei * count,GLuint * shaders)892 void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
893         GLsizei* count, GLuint* shaders)
894 {
895     GL2Encoder *ctx = (GL2Encoder*)self;
896     SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
897     ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
898 }
899 
s_glGetShaderSource(void * self,GLuint shader,GLsizei bufsize,GLsizei * length,GLchar * source)900 void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
901             GLsizei* length, GLchar* source)
902 {
903     GL2Encoder *ctx = (GL2Encoder*)self;
904     SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
905     ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
906 }
907 
s_glGetShaderInfoLog(void * self,GLuint shader,GLsizei bufsize,GLsizei * length,GLchar * infolog)908 void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
909         GLsizei* length, GLchar* infolog)
910 {
911     GL2Encoder *ctx = (GL2Encoder*)self;
912     SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
913     ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
914 }
915 
s_glGetProgramInfoLog(void * self,GLuint program,GLsizei bufsize,GLsizei * length,GLchar * infolog)916 void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
917         GLsizei* length, GLchar* infolog)
918 {
919     GL2Encoder *ctx = (GL2Encoder*)self;
920     SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
921     ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
922 }
923 
s_glDeleteShader(void * self,GLenum shader)924 void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
925 {
926     GL2Encoder *ctx = (GL2Encoder*)self;
927     ctx->m_glDeleteShader_enc(self,shader);
928     ctx->m_shared->unrefShaderData(shader);
929 }
930 
s_glAttachShader(void * self,GLuint program,GLuint shader)931 void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
932 {
933     GL2Encoder *ctx = (GL2Encoder*)self;
934     ctx->m_glAttachShader_enc(self, program, shader);
935     ctx->m_shared->attachShader(program, shader);
936 }
937 
s_glDetachShader(void * self,GLuint program,GLuint shader)938 void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
939 {
940     GL2Encoder *ctx = (GL2Encoder*)self;
941     ctx->m_glDetachShader_enc(self, program, shader);
942     ctx->m_shared->detachShader(program, shader);
943 }
944 
s_glGetUniformLocation(void * self,GLuint program,const GLchar * name)945 int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
946 {
947     if (!name) return -1;
948 
949     GL2Encoder *ctx = (GL2Encoder*)self;
950 
951     // if we need the uniform location WAR
952     // parse array index from the end of the name string
953     int arrIndex = 0;
954     bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
955     if (needLocationWAR) {
956         int namelen = strlen(name);
957         if (name[namelen-1] == ']') {
958             char *brace = strrchr(name,'[');
959             if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
960                 return -1;
961             }
962 
963         }
964     }
965 
966     int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
967     if (hostLoc >= 0 && needLocationWAR) {
968         return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
969     }
970     return hostLoc;
971 }
972 
updateHostTexture2DBinding(GLenum texUnit,GLenum newTarget)973 bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
974 {
975     if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
976         return false;
977 
978     m_state->setActiveTextureUnit(texUnit);
979 
980     GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
981     if (newTarget != oldTarget) {
982         if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
983             m_state->disableTextureTarget(GL_TEXTURE_2D);
984             m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
985         } else {
986             m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
987             m_state->enableTextureTarget(GL_TEXTURE_2D);
988         }
989         m_glActiveTexture_enc(this, texUnit);
990         m_glBindTexture_enc(this, GL_TEXTURE_2D,
991                 m_state->getBoundTexture(newTarget));
992         return true;
993     }
994 
995     return false;
996 }
997 
s_glUseProgram(void * self,GLuint program)998 void GL2Encoder::s_glUseProgram(void *self, GLuint program)
999 {
1000     GL2Encoder *ctx = (GL2Encoder*)self;
1001     GLClientState* state = ctx->m_state;
1002     GLSharedGroupPtr shared = ctx->m_shared;
1003 
1004     ctx->m_glUseProgram_enc(self, program);
1005     ctx->m_state->setCurrentProgram(program);
1006 
1007     GLenum origActiveTexture = state->getActiveTextureUnit();
1008     GLenum hostActiveTexture = origActiveTexture;
1009     GLint samplerIdx = -1;
1010     GLint samplerVal;
1011     GLenum samplerTarget;
1012     while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1013         if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1014             continue;
1015         if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
1016                 samplerTarget))
1017         {
1018             hostActiveTexture = GL_TEXTURE0 + samplerVal;
1019         }
1020     }
1021     state->setActiveTextureUnit(origActiveTexture);
1022     if (hostActiveTexture != origActiveTexture) {
1023         ctx->m_glActiveTexture_enc(self, origActiveTexture);
1024     }
1025 }
1026 
checkValidUniformParam(void * self,GLsizei count,GLboolean transpose)1027 void GL2Encoder::checkValidUniformParam(void *self, GLsizei count, GLboolean transpose)
1028 {
1029     GL2Encoder *ctx = (GL2Encoder*)self;
1030     GLuint program = ctx->m_state->currentProgram();
1031     SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
1032     SET_ERROR_IF((count < 0 || transpose == GL_TRUE), GL_INVALID_VALUE);
1033 }
1034 
getHostLocation(void * self,GLint location,GLint * hostLoc)1035 void GL2Encoder::getHostLocation(void *self, GLint location, GLint *hostLoc)
1036 {
1037     GL2Encoder *ctx = (GL2Encoder*)self;
1038     GLuint program = ctx->m_state->currentProgram();
1039     if (location == -1) {
1040         *hostLoc = location;
1041         return;
1042     }
1043     SET_ERROR_IF((location < 0), GL_INVALID_OPERATION);
1044     GLint curHostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1045     SET_ERROR_IF((ctx->m_shared->getProgramUniformType(program,curHostLoc) == 0 &&
1046             curHostLoc!=-1), GL_INVALID_OPERATION);
1047     *hostLoc = curHostLoc;
1048 }
1049 
s_glUniform1f(void * self,GLint location,GLfloat x)1050 void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1051 {
1052     GL2Encoder *ctx = (GL2Encoder*)self;
1053     GLint hostLoc;
1054 
1055     ctx->checkValidUniformParam(self, 0, GL_FALSE);
1056     ctx->getHostLocation(self, location, &hostLoc);
1057     ctx->m_glUniform1f_enc(self, hostLoc, x);
1058 }
1059 
s_glUniform1fv(void * self,GLint location,GLsizei count,const GLfloat * v)1060 void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1061 {
1062     GL2Encoder *ctx = (GL2Encoder*)self;
1063     GLint hostLoc;
1064 
1065     ctx->checkValidUniformParam(self, count, GL_FALSE);
1066     ctx->getHostLocation(self, location, &hostLoc);
1067     ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1068 }
1069 
s_glUniform1i(void * self,GLint location,GLint x)1070 void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1071 {
1072     GL2Encoder *ctx = (GL2Encoder*)self;
1073     GLClientState* state = ctx->m_state;
1074     GLSharedGroupPtr shared = ctx->m_shared;
1075     GLint hostLoc;
1076 
1077     ctx->checkValidUniformParam(self, 0, GL_FALSE);
1078     ctx->getHostLocation(self, location, &hostLoc);
1079     ctx->m_glUniform1i_enc(self, hostLoc, x);
1080 
1081     GLenum target;
1082     if (shared->setSamplerUniform(state->currentProgram(), location, x, &target)) {
1083         GLenum origActiveTexture = state->getActiveTextureUnit();
1084         if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1085             ctx->m_glActiveTexture_enc(self, origActiveTexture);
1086         }
1087         state->setActiveTextureUnit(origActiveTexture);
1088     }
1089 }
1090 
s_glUniform1iv(void * self,GLint location,GLsizei count,const GLint * v)1091 void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1092 {
1093     GL2Encoder *ctx = (GL2Encoder*)self;
1094     GLint hostLoc;
1095 
1096     ctx->checkValidUniformParam(self, count, GL_FALSE);
1097     ctx->getHostLocation(self, location, &hostLoc);
1098     ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1099 }
1100 
s_glUniform2f(void * self,GLint location,GLfloat x,GLfloat y)1101 void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1102 {
1103     GL2Encoder *ctx = (GL2Encoder*)self;
1104     GLint hostLoc;
1105 
1106     ctx->checkValidUniformParam(self, 0, GL_FALSE);
1107     ctx->getHostLocation(self, location, &hostLoc);
1108     ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1109 }
1110 
s_glUniform2fv(void * self,GLint location,GLsizei count,const GLfloat * v)1111 void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1112 {
1113     GL2Encoder *ctx = (GL2Encoder*)self;
1114     GLint hostLoc;
1115 
1116     ctx->checkValidUniformParam(self, count, GL_FALSE);
1117     ctx->getHostLocation(self, location, &hostLoc);
1118     ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1119 }
1120 
s_glUniform2i(void * self,GLint location,GLint x,GLint y)1121 void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1122 {
1123     GL2Encoder *ctx = (GL2Encoder*)self;
1124     GLint hostLoc;
1125 
1126     ctx->checkValidUniformParam(self, 0, GL_FALSE);
1127     ctx->getHostLocation(self, location, &hostLoc);
1128     ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1129 }
1130 
s_glUniform2iv(void * self,GLint location,GLsizei count,const GLint * v)1131 void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1132 {
1133     GL2Encoder *ctx = (GL2Encoder*)self;
1134     GLint hostLoc;
1135 
1136     ctx->checkValidUniformParam(self, count, GL_FALSE);
1137     ctx->getHostLocation(self, location, &hostLoc);
1138     ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1139 }
1140 
s_glUniform3f(void * self,GLint location,GLfloat x,GLfloat y,GLfloat z)1141 void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1142 {
1143     GL2Encoder *ctx = (GL2Encoder*)self;
1144     GLint hostLoc;
1145 
1146     ctx->checkValidUniformParam(self, 0, GL_FALSE);
1147     ctx->getHostLocation(self, location, &hostLoc);
1148     ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1149 }
1150 
s_glUniform3fv(void * self,GLint location,GLsizei count,const GLfloat * v)1151 void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1152 {
1153     GL2Encoder *ctx = (GL2Encoder*)self;
1154     GLint hostLoc;
1155 
1156     ctx->checkValidUniformParam(self, count, GL_FALSE);
1157     ctx->getHostLocation(self, location, &hostLoc);
1158     ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1159 }
1160 
s_glUniform3i(void * self,GLint location,GLint x,GLint y,GLint z)1161 void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1162 {
1163     GL2Encoder *ctx = (GL2Encoder*)self;
1164     GLint hostLoc;
1165 
1166     ctx->checkValidUniformParam(self, 0, GL_FALSE);
1167     ctx->getHostLocation(self, location, &hostLoc);
1168     ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1169 }
1170 
s_glUniform3iv(void * self,GLint location,GLsizei count,const GLint * v)1171 void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1172 {
1173     GL2Encoder *ctx = (GL2Encoder*)self;
1174     GLint hostLoc;
1175 
1176     ctx->checkValidUniformParam(self, count, GL_FALSE);
1177     ctx->getHostLocation(self, location, &hostLoc);
1178     ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1179 }
1180 
s_glUniform4f(void * self,GLint location,GLfloat x,GLfloat y,GLfloat z,GLfloat w)1181 void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1182 {
1183     GL2Encoder *ctx = (GL2Encoder*)self;
1184     GLint hostLoc;
1185 
1186     ctx->checkValidUniformParam(self, 0, GL_FALSE);
1187     ctx->getHostLocation(self, location, &hostLoc);
1188     ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1189 }
1190 
s_glUniform4fv(void * self,GLint location,GLsizei count,const GLfloat * v)1191 void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1192 {
1193     GL2Encoder *ctx = (GL2Encoder*)self;
1194     GLint hostLoc;
1195 
1196     ctx->checkValidUniformParam(self, count, GL_FALSE);
1197     ctx->getHostLocation(self, location, &hostLoc);
1198     ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1199 }
1200 
s_glUniform4i(void * self,GLint location,GLint x,GLint y,GLint z,GLint w)1201 void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1202 {
1203     GL2Encoder *ctx = (GL2Encoder*)self;
1204     GLint hostLoc;
1205 
1206     ctx->checkValidUniformParam(self, 0, GL_FALSE);
1207     ctx->getHostLocation(self, location, &hostLoc);
1208     ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1209 }
1210 
s_glUniform4iv(void * self,GLint location,GLsizei count,const GLint * v)1211 void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1212 {
1213     GL2Encoder *ctx = (GL2Encoder*)self;
1214     GLint hostLoc;
1215 
1216     ctx->checkValidUniformParam(self, count, GL_FALSE);
1217     ctx->getHostLocation(self, location, &hostLoc);
1218     ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1219 }
1220 
s_glUniformMatrix2fv(void * self,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1221 void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1222 {
1223     GL2Encoder *ctx = (GL2Encoder*)self;
1224     GLint hostLoc;
1225 
1226     ctx->checkValidUniformParam(self, count, transpose);
1227     ctx->getHostLocation(self, location, &hostLoc);
1228     ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1229 }
1230 
s_glUniformMatrix3fv(void * self,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1231 void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1232 {
1233     GL2Encoder *ctx = (GL2Encoder*)self;
1234     GLint hostLoc;
1235 
1236     ctx->checkValidUniformParam(self, count, transpose);
1237     ctx->getHostLocation(self, location, &hostLoc);
1238     ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1239 }
1240 
s_glUniformMatrix4fv(void * self,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1241 void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1242 {
1243     GL2Encoder *ctx = (GL2Encoder*)self;
1244     GLint hostLoc;
1245 
1246     ctx->checkValidUniformParam(self, count, transpose);
1247     ctx->getHostLocation(self, location, &hostLoc);
1248     ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1249 }
1250 
s_glActiveTexture(void * self,GLenum texture)1251 void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1252 {
1253     GL2Encoder* ctx = (GL2Encoder*)self;
1254     GLClientState* state = ctx->m_state;
1255     GLenum err;
1256 
1257     SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1258 
1259     ctx->m_glActiveTexture_enc(ctx, texture);
1260 }
1261 
s_glBindTexture(void * self,GLenum target,GLuint texture)1262 void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1263 {
1264     GL2Encoder* ctx = (GL2Encoder*)self;
1265     GLClientState* state = ctx->m_state;
1266     GLenum err;
1267     GLboolean firstUse;
1268 
1269     SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1270 
1271     if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1272         ctx->m_glBindTexture_enc(ctx, target, texture);
1273         return;
1274     }
1275 
1276     GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1277 
1278     if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1279         ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1280         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1281                 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1282         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1283                 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1284         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1285                 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1286 
1287         if (target != priorityTarget) {
1288             ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1289                     state->getBoundTexture(GL_TEXTURE_2D));
1290         }
1291     }
1292 
1293     if (target == priorityTarget) {
1294         ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1295     }
1296 }
1297 
s_glDeleteTextures(void * self,GLsizei n,const GLuint * textures)1298 void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1299 {
1300     GL2Encoder* ctx = (GL2Encoder*)self;
1301     GLClientState* state = ctx->m_state;
1302 
1303     state->deleteTextures(n, textures);
1304     ctx->m_glDeleteTextures_enc(ctx, n, textures);
1305 }
1306 
s_glGetTexParameterfv(void * self,GLenum target,GLenum pname,GLfloat * params)1307 void GL2Encoder::s_glGetTexParameterfv(void* self,
1308         GLenum target, GLenum pname, GLfloat* params)
1309 {
1310     GL2Encoder* ctx = (GL2Encoder*)self;
1311     const GLClientState* state = ctx->m_state;
1312 
1313     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1314         ctx->override2DTextureTarget(target);
1315         ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
1316         ctx->restore2DTextureTarget();
1317     } else {
1318         ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1319     }
1320 }
1321 
s_glGetTexParameteriv(void * self,GLenum target,GLenum pname,GLint * params)1322 void GL2Encoder::s_glGetTexParameteriv(void* self,
1323         GLenum target, GLenum pname, GLint* params)
1324 {
1325     GL2Encoder* ctx = (GL2Encoder*)self;
1326     const GLClientState* state = ctx->m_state;
1327 
1328     switch (pname) {
1329     case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1330         *params = 1;
1331         break;
1332 
1333     default:
1334         if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1335             ctx->override2DTextureTarget(target);
1336             ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
1337             ctx->restore2DTextureTarget();
1338         } else {
1339             ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1340         }
1341         break;
1342     }
1343 }
1344 
isValidTextureExternalParam(GLenum pname,GLenum param)1345 static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1346 {
1347     switch (pname) {
1348     case GL_TEXTURE_MIN_FILTER:
1349     case GL_TEXTURE_MAG_FILTER:
1350         return param == GL_NEAREST || param == GL_LINEAR;
1351 
1352     case GL_TEXTURE_WRAP_S:
1353     case GL_TEXTURE_WRAP_T:
1354         return param == GL_CLAMP_TO_EDGE;
1355 
1356     default:
1357         return true;
1358     }
1359 }
1360 
s_glTexParameterf(void * self,GLenum target,GLenum pname,GLfloat param)1361 void GL2Encoder::s_glTexParameterf(void* self,
1362         GLenum target, GLenum pname, GLfloat param)
1363 {
1364     GL2Encoder* ctx = (GL2Encoder*)self;
1365     const GLClientState* state = ctx->m_state;
1366 
1367     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1368             !isValidTextureExternalParam(pname, (GLenum)param)),
1369             GL_INVALID_ENUM);
1370 
1371     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1372         ctx->override2DTextureTarget(target);
1373         ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
1374         ctx->restore2DTextureTarget();
1375     } else {
1376         ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1377     }
1378 }
1379 
s_glTexParameterfv(void * self,GLenum target,GLenum pname,const GLfloat * params)1380 void GL2Encoder::s_glTexParameterfv(void* self,
1381         GLenum target, GLenum pname, const GLfloat* params)
1382 {
1383     GL2Encoder* ctx = (GL2Encoder*)self;
1384     const GLClientState* state = ctx->m_state;
1385 
1386     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1387             !isValidTextureExternalParam(pname, (GLenum)params[0])),
1388             GL_INVALID_ENUM);
1389 
1390     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1391         ctx->override2DTextureTarget(target);
1392         ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
1393         ctx->restore2DTextureTarget();
1394     } else {
1395         ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1396     }
1397 }
1398 
s_glTexParameteri(void * self,GLenum target,GLenum pname,GLint param)1399 void GL2Encoder::s_glTexParameteri(void* self,
1400         GLenum target, GLenum pname, GLint param)
1401 {
1402     GL2Encoder* ctx = (GL2Encoder*)self;
1403     const GLClientState* state = ctx->m_state;
1404 
1405     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1406             !isValidTextureExternalParam(pname, (GLenum)param)),
1407             GL_INVALID_ENUM);
1408 
1409     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1410         ctx->override2DTextureTarget(target);
1411         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
1412         ctx->restore2DTextureTarget();
1413     } else {
1414         ctx->m_glTexParameteri_enc(ctx, target, pname, param);
1415     }
1416 }
1417 
s_glTexImage2D(void * self,GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const GLvoid * pixels)1418 void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
1419         GLint internalformat, GLsizei width, GLsizei height, GLint border,
1420         GLenum format, GLenum type, const GLvoid* pixels)
1421 {
1422     GL2Encoder* ctx = (GL2Encoder*)self;
1423     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1424         ctx->override2DTextureTarget(target);
1425         ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1426                 height, border, format, type, pixels);
1427         ctx->restore2DTextureTarget();
1428     } else {
1429         ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1430                 height, border, format, type, pixels);
1431     }
1432 }
1433 
s_glTexSubImage2D(void * self,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)1434 void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
1435         GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
1436         GLenum type, const GLvoid* pixels)
1437 {
1438     GL2Encoder* ctx = (GL2Encoder*)self;
1439     GLint maxTextureSize;
1440     ctx->glGetIntegerv(self, GL_MAX_TEXTURE_SIZE, &maxTextureSize);
1441 
1442     SET_ERROR_IF((level < 0 || level > log2(maxTextureSize)), GL_INVALID_VALUE);
1443 
1444      if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1445         ctx->override2DTextureTarget(target);
1446         ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
1447                 height, format, type, pixels);
1448         ctx->restore2DTextureTarget();
1449      } else {
1450          ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
1451                  height, format, type, pixels);
1452      }
1453 }
1454 
s_glTexParameteriv(void * self,GLenum target,GLenum pname,const GLint * params)1455 void GL2Encoder::s_glTexParameteriv(void* self,
1456         GLenum target, GLenum pname, const GLint* params)
1457 {
1458     GL2Encoder* ctx = (GL2Encoder*)self;
1459     const GLClientState* state = ctx->m_state;
1460 
1461     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1462             !isValidTextureExternalParam(pname, (GLenum)params[0])),
1463             GL_INVALID_ENUM);
1464 
1465     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1466         ctx->override2DTextureTarget(target);
1467         ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
1468         ctx->restore2DTextureTarget();
1469     } else {
1470         ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
1471     }
1472 }
1473 
override2DTextureTarget(GLenum target)1474 void GL2Encoder::override2DTextureTarget(GLenum target)
1475 {
1476     if ((target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
1477         target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)) {
1478             m_glBindTexture_enc(this, GL_TEXTURE_2D,
1479                     m_state->getBoundTexture(target));
1480     }
1481 }
1482 
restore2DTextureTarget()1483 void GL2Encoder::restore2DTextureTarget()
1484 {
1485     GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1486     m_glBindTexture_enc(this, GL_TEXTURE_2D,
1487             m_state->getBoundTexture(priorityTarget));
1488 }
1489