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