2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "GL2Encoder.h"
23 #define MIN(a, b) ((a) < (b) ? (a) : (b))
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 ";
31 #define SET_ERROR_IF(condition,err) if((condition)) { \
32 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
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); \
45 GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
46 : gl2_encoder_context_t(stream, protocol)
48 m_initialized = false;
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;
58 #define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name
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);
79 this->glShaderBinary = &s_glShaderBinary;
80 this->glShaderSource = &s_glShaderSource;
81 this->glFinish = &s_glFinish;
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);
98 OVERRIDE(glGetUniformLocation);
99 OVERRIDE(glUseProgram);
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);
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);
134 GL2Encoder::~GL2Encoder()
136 delete m_compressedTextureFormats;
139 GLenum GL2Encoder::s_glGetError(void * self)
141 GL2Encoder *ctx = (GL2Encoder *)self;
142 GLenum err = ctx->getError();
143 if(err != GL_NO_ERROR) {
144 ctx->setError(GL_NO_ERROR);
148 return ctx->m_glGetError_enc(self);
152 void GL2Encoder::s_glFlush(void *self)
154 GL2Encoder *ctx = (GL2Encoder *) self;
155 ctx->m_glFlush_enc(self);
156 ctx->m_stream->flush();
159 const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
163 GLubyte *retval = (GLubyte *) "";
166 retval = gVendorString;
169 retval = gRendererString;
172 retval = gVersionString;
175 retval = gExtensionsString;
181 void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
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);
190 void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
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);
199 void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
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);
207 ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
208 ctx->m_glBufferData_enc(self, target, size, data, usage);
211 void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
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);
218 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
219 SET_ERROR_IF(res, res);
221 ctx->m_glBufferSubData_enc(self, target, offset, size, data);
224 void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
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]);
235 void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
237 GL2Encoder *ctx = (GL2Encoder *)self;
238 assert(ctx->m_state != NULL);
239 ctx->m_state->setState(indx, size, type, normalized, stride, ptr);
242 void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
244 GL2Encoder *ctx = (GL2Encoder *) self;
245 assert(ctx->m_state != NULL);
246 GLClientState* state = ctx->m_state;
249 case GL_NUM_SHADER_BINARY_FORMATS:
252 case GL_SHADER_BINARY_FORMATS:
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));
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);
273 case GL_TEXTURE_BINDING_2D:
274 *ptr = state->getBoundTexture(GL_TEXTURE_2D);
276 case GL_TEXTURE_BINDING_EXTERNAL_OES:
277 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
280 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
281 if (ctx->m_max_cubeMapTextureSize != 0) {
282 *ptr = ctx->m_max_cubeMapTextureSize;
284 ctx->m_glGetIntegerv_enc(self, param, ptr);
285 ctx->m_max_cubeMapTextureSize = *ptr;
288 case GL_MAX_RENDERBUFFER_SIZE:
289 if (ctx->m_max_renderBufferSize != 0) {
290 *ptr = ctx->m_max_renderBufferSize;
292 ctx->m_glGetIntegerv_enc(self, param, ptr);
293 ctx->m_max_renderBufferSize = *ptr;
296 case GL_MAX_TEXTURE_SIZE:
297 if (ctx->m_max_textureSize != 0) {
298 *ptr = ctx->m_max_textureSize;
300 ctx->m_glGetIntegerv_enc(self, param, ptr);
301 ctx->m_max_textureSize = *ptr;
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);
311 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
312 ctx->m_glGetIntegerv_enc(self, param, ptr);
319 void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
321 GL2Encoder *ctx = (GL2Encoder *)self;
322 assert(ctx->m_state != NULL);
323 GLClientState* state = ctx->m_state;
326 case GL_NUM_SHADER_BINARY_FORMATS:
329 case GL_SHADER_BINARY_FORMATS:
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];
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);
351 case GL_TEXTURE_BINDING_2D:
352 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
354 case GL_TEXTURE_BINDING_EXTERNAL_OES:
355 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
359 if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
360 ctx->m_glGetFloatv_enc(self, param, ptr);
367 void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
369 GL2Encoder *ctx = (GL2Encoder *)self;
370 assert(ctx->m_state != NULL);
371 GLClientState* state = ctx->m_state;
374 case GL_NUM_SHADER_BINARY_FORMATS:
377 case GL_SHADER_BINARY_FORMATS:
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;
392 case GL_TEXTURE_BINDING_2D:
393 *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
395 case GL_TEXTURE_BINDING_EXTERNAL_OES:
396 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
397 ? GL_TRUE : GL_FALSE;
401 if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
402 ctx->m_glGetBooleanv_enc(self, param, ptr);
404 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
410 void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
412 GL2Encoder *ctx = (GL2Encoder *)self;
413 assert(ctx->m_state);
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);
420 void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
422 GL2Encoder *ctx = (GL2Encoder *)self;
423 assert(ctx->m_state);
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);
431 void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
433 GL2Encoder *ctx = (GL2Encoder *)self;
434 assert(ctx->m_state);
436 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
437 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
439 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
440 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
444 void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
446 GL2Encoder *ctx = (GL2Encoder *)self;
447 assert(ctx->m_state);
449 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
450 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
452 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
453 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
457 void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
459 GL2Encoder *ctx = (GL2Encoder *)self;
460 if (ctx->m_state == NULL) return;
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);
468 const GLClientState::VertexAttribState *va_state = ctx->m_state->getState(index);
469 if (va_state != NULL) {
470 *pointer = va_state->data;
475 void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count)
479 for (int i = 0; i < m_state->nLocations(); i++) {
481 const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty);
487 if (!enableDirty && !state->enabled) {
492 if (state->enabled) {
493 m_glEnableVertexAttribArray_enc(this, i);
495 unsigned int datalen = state->elementSize * count;
496 int stride = state->stride == 0 ? state->elementSize : state->stride;
497 int firstIndex = stride * first;
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);
504 this->glVertexAttribPointerOffset(this, i, state->size, state->type, state->normalized, state->stride,
505 (uintptr_t) state->data + firstIndex);
507 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
509 this->m_glDisableVertexAttribArray_enc(this, i);
514 static bool isValidDrawMode(GLenum mode) {
520 case GL_TRIANGLE_STRIP:
521 case GL_TRIANGLE_FAN:
528 static bool isValidDrawType(GLenum mode) {
529 return mode == GL_UNSIGNED_BYTE ||
530 mode == GL_UNSIGNED_SHORT ||
531 mode == GL_UNSIGNED_INT;
534 void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
536 GL2Encoder *ctx = (GL2Encoder *)self;
538 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
539 SET_ERROR_IF(count<0, GL_INVALID_VALUE);
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) {
550 ALOGE("glDrawArrays: a vertex attribute array is enabled with no data bound\n");
551 ctx->setError(GL_INVALID_OPERATION);
557 ALOGE("glDrawArrays: no data bound to the command - ignoring\n");
561 ctx->sendVertexAttributes(first, count);
562 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
565 void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
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);
573 bool has_immediate_arrays = false;
574 bool has_indirect_arrays = false;
575 int nLocations = ctx->m_state->nLocations();
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;
585 ALOGW("glDrawElements: a vertex attribute array is enabled with no data bound\n");
586 ctx->setError(GL_INVALID_OPERATION);
592 if (!has_immediate_arrays && !has_indirect_arrays) {
593 ALOGE("glDrawElements: no data bound to the command - ignoring\n");
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;
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);
611 void *adjustedIndices = (void*)indices;
612 int minIndex = 0, maxIndex = 0;
616 case GL_UNSIGNED_BYTE:
617 GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex);
619 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
620 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices,
621 (unsigned char *)adjustedIndices,
626 case GL_UNSIGNED_SHORT:
627 GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex);
629 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
630 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices,
631 (unsigned short *)adjustedIndices,
636 case GL_UNSIGNED_INT:
637 GLUtils::minmax<unsigned int>((unsigned int *)indices, count, &minIndex, &maxIndex);
639 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
640 GLUtils::shiftIndices<unsigned int>((unsigned int *)indices,
641 (unsigned int *)adjustedIndices,
646 ALOGE("unsupported index buffer type %d\n", type);
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");
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");
665 GLint * GL2Encoder::getCompressedTextureFormats()
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);
676 return m_compressedTextureFormats;
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
684 // This implementation assumes the input has already been pre-processed. If not,
685 // a few cases will be mishandled:
687 // 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
688 // the following code:
690 // uniform sampler2D mySampler;
692 // uniform samplerExternalOES mySampler;
695 // 2. Comments that look like sampler declarations will be incorrectly modified
697 // // samplerExternalOES hahaFooledYou
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);
704 static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
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 ";
711 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
713 while ((c = strstr(c, STR_HASH_EXTENSION))) {
715 c += sizeof(STR_HASH_EXTENSION)-1;
716 while (isspace(*c) && *c != '\0') {
719 if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
720 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
722 // #extension statements are terminated by end of line
724 while (*c != '\0' && *c != '\r' && *c != '\n') {
730 // -- replace "samplerExternalOES" with "sampler2D" and record name
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))) {
738 char* sampler_start = c;
739 c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
740 if (!isspace(*c) && *c != '\0') {
744 // capture sampler name
745 while (isspace(*c) && *c != '\0') {
748 if (!isalpha(*c) && *c != '_') {
752 char* name_start = c;
755 } while (isalnum(*c) || *c == '_');
756 data->samplerExternalNames.push_back(
757 android::String8(name_start, c - name_start));
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);
766 void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
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);
773 void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
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);
781 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
782 char *str = new char[len + 1];
783 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
785 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
786 // Perhaps we can borrow Mesa's pre-processor?
788 if (!replaceSamplerExternalWith2D(str, shaderData)) {
790 ctx->setError(GL_OUT_OF_MEMORY);
794 ctx->glShaderString(ctx, shader, str, len + 1);
798 void GL2Encoder::s_glFinish(void *self)
800 GL2Encoder *ctx = (GL2Encoder *)self;
801 ctx->glFinishRoundTrip(self);
804 void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
806 GL2Encoder *ctx = (GL2Encoder *)self;
807 ctx->m_glLinkProgram_enc(self, program);
809 GLint linkStatus = 0;
810 ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
814 //get number of active uniforms in the program
816 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
817 ctx->m_shared->initProgramData(program,numUniforms);
819 //get the length of the longest uniform name
821 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
825 GLchar *name = new GLchar[maxLength+1];
827 //for each active uniform, get its size and starting location.
828 for (GLint i=0 ; i<numUniforms ; ++i)
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);
834 ctx->m_shared->setupLocationShiftWAR(program);
839 void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
841 GL2Encoder *ctx = (GL2Encoder*)self;
842 ctx->m_glDeleteProgram_enc(self, program);
844 ctx->m_shared->deleteProgramData(program);
847 void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
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);
857 void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
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);
868 GLuint GL2Encoder::s_glCreateProgram(void * self)
870 GL2Encoder *ctx = (GL2Encoder*)self;
871 GLuint program = ctx->m_glCreateProgram_enc(self);
873 ctx->m_shared->addProgramData(program);
877 GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
879 GL2Encoder *ctx = (GL2Encoder*)self;
880 RET_AND_SET_ERROR_IF(((shaderType != GL_VERTEX_SHADER) && (shaderType != GL_FRAGMENT_SHADER)),
882 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
884 if (!ctx->m_shared->addShaderData(shader)) {
885 ctx->m_glDeleteShader_enc(self, shader);
892 void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
893 GLsizei* count, GLuint* shaders)
895 GL2Encoder *ctx = (GL2Encoder*)self;
896 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
897 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
900 void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
901 GLsizei* length, GLchar* source)
903 GL2Encoder *ctx = (GL2Encoder*)self;
904 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
905 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
908 void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
909 GLsizei* length, GLchar* infolog)
911 GL2Encoder *ctx = (GL2Encoder*)self;
912 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
913 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
916 void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
917 GLsizei* length, GLchar* infolog)
919 GL2Encoder *ctx = (GL2Encoder*)self;
920 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
921 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
924 void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
926 GL2Encoder *ctx = (GL2Encoder*)self;
927 ctx->m_glDeleteShader_enc(self,shader);
928 ctx->m_shared->unrefShaderData(shader);
931 void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
933 GL2Encoder *ctx = (GL2Encoder*)self;
934 ctx->m_glAttachShader_enc(self, program, shader);
935 ctx->m_shared->attachShader(program, shader);
938 void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
940 GL2Encoder *ctx = (GL2Encoder*)self;
941 ctx->m_glDetachShader_enc(self, program, shader);
942 ctx->m_shared->detachShader(program, shader);
945 int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
947 if (!name) return -1;
949 GL2Encoder *ctx = (GL2Encoder*)self;
951 // if we need the uniform location WAR
952 // parse array index from the end of the name string
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) {
966 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
967 if (hostLoc >= 0 && needLocationWAR) {
968 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
973 bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
975 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
978 m_state->setActiveTextureUnit(texUnit);
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);
986 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
987 m_state->enableTextureTarget(GL_TEXTURE_2D);
989 m_glActiveTexture_enc(this, texUnit);
990 m_glBindTexture_enc(this, GL_TEXTURE_2D,
991 m_state->getBoundTexture(newTarget));
998 void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1000 GL2Encoder *ctx = (GL2Encoder*)self;
1001 GLClientState* state = ctx->m_state;
1002 GLSharedGroupPtr shared = ctx->m_shared;
1004 ctx->m_glUseProgram_enc(self, program);
1005 ctx->m_state->setCurrentProgram(program);
1007 GLenum origActiveTexture = state->getActiveTextureUnit();
1008 GLenum hostActiveTexture = origActiveTexture;
1009 GLint samplerIdx = -1;
1011 GLenum samplerTarget;
1012 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1013 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1015 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
1018 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1021 state->setActiveTextureUnit(origActiveTexture);
1022 if (hostActiveTexture != origActiveTexture) {
1023 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1027 void GL2Encoder::checkValidUniformParam(void *self, GLsizei count, GLboolean transpose)
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);
1035 void GL2Encoder::getHostLocation(void *self, GLint location, GLint *hostLoc)
1037 GL2Encoder *ctx = (GL2Encoder*)self;
1038 GLuint program = ctx->m_state->currentProgram();
1039 if (location == -1) {
1040 *hostLoc = location;
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;
1050 void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1052 GL2Encoder *ctx = (GL2Encoder*)self;
1055 ctx->checkValidUniformParam(self, 0, GL_FALSE);
1056 ctx->getHostLocation(self, location, &hostLoc);
1057 ctx->m_glUniform1f_enc(self, hostLoc, x);
1060 void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1062 GL2Encoder *ctx = (GL2Encoder*)self;
1065 ctx->checkValidUniformParam(self, count, GL_FALSE);
1066 ctx->getHostLocation(self, location, &hostLoc);
1067 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1070 void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1072 GL2Encoder *ctx = (GL2Encoder*)self;
1073 GLClientState* state = ctx->m_state;
1074 GLSharedGroupPtr shared = ctx->m_shared;
1077 ctx->checkValidUniformParam(self, 0, GL_FALSE);
1078 ctx->getHostLocation(self, location, &hostLoc);
1079 ctx->m_glUniform1i_enc(self, hostLoc, x);
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);
1087 state->setActiveTextureUnit(origActiveTexture);
1091 void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1093 GL2Encoder *ctx = (GL2Encoder*)self;
1096 ctx->checkValidUniformParam(self, count, GL_FALSE);
1097 ctx->getHostLocation(self, location, &hostLoc);
1098 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1101 void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1103 GL2Encoder *ctx = (GL2Encoder*)self;
1106 ctx->checkValidUniformParam(self, 0, GL_FALSE);
1107 ctx->getHostLocation(self, location, &hostLoc);
1108 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1111 void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1113 GL2Encoder *ctx = (GL2Encoder*)self;
1116 ctx->checkValidUniformParam(self, count, GL_FALSE);
1117 ctx->getHostLocation(self, location, &hostLoc);
1118 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1121 void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1123 GL2Encoder *ctx = (GL2Encoder*)self;
1126 ctx->checkValidUniformParam(self, 0, GL_FALSE);
1127 ctx->getHostLocation(self, location, &hostLoc);
1128 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1131 void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1133 GL2Encoder *ctx = (GL2Encoder*)self;
1136 ctx->checkValidUniformParam(self, count, GL_FALSE);
1137 ctx->getHostLocation(self, location, &hostLoc);
1138 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1141 void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1143 GL2Encoder *ctx = (GL2Encoder*)self;
1146 ctx->checkValidUniformParam(self, 0, GL_FALSE);
1147 ctx->getHostLocation(self, location, &hostLoc);
1148 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1151 void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1153 GL2Encoder *ctx = (GL2Encoder*)self;
1156 ctx->checkValidUniformParam(self, count, GL_FALSE);
1157 ctx->getHostLocation(self, location, &hostLoc);
1158 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1161 void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1163 GL2Encoder *ctx = (GL2Encoder*)self;
1166 ctx->checkValidUniformParam(self, 0, GL_FALSE);
1167 ctx->getHostLocation(self, location, &hostLoc);
1168 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1171 void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1173 GL2Encoder *ctx = (GL2Encoder*)self;
1176 ctx->checkValidUniformParam(self, count, GL_FALSE);
1177 ctx->getHostLocation(self, location, &hostLoc);
1178 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1181 void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1183 GL2Encoder *ctx = (GL2Encoder*)self;
1186 ctx->checkValidUniformParam(self, 0, GL_FALSE);
1187 ctx->getHostLocation(self, location, &hostLoc);
1188 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1191 void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1193 GL2Encoder *ctx = (GL2Encoder*)self;
1196 ctx->checkValidUniformParam(self, count, GL_FALSE);
1197 ctx->getHostLocation(self, location, &hostLoc);
1198 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1201 void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1203 GL2Encoder *ctx = (GL2Encoder*)self;
1206 ctx->checkValidUniformParam(self, 0, GL_FALSE);
1207 ctx->getHostLocation(self, location, &hostLoc);
1208 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1211 void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1213 GL2Encoder *ctx = (GL2Encoder*)self;
1216 ctx->checkValidUniformParam(self, count, GL_FALSE);
1217 ctx->getHostLocation(self, location, &hostLoc);
1218 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1221 void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1223 GL2Encoder *ctx = (GL2Encoder*)self;
1226 ctx->checkValidUniformParam(self, count, transpose);
1227 ctx->getHostLocation(self, location, &hostLoc);
1228 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1231 void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1233 GL2Encoder *ctx = (GL2Encoder*)self;
1236 ctx->checkValidUniformParam(self, count, transpose);
1237 ctx->getHostLocation(self, location, &hostLoc);
1238 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1241 void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1243 GL2Encoder *ctx = (GL2Encoder*)self;
1246 ctx->checkValidUniformParam(self, count, transpose);
1247 ctx->getHostLocation(self, location, &hostLoc);
1248 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1251 void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1253 GL2Encoder* ctx = (GL2Encoder*)self;
1254 GLClientState* state = ctx->m_state;
1257 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1259 ctx->m_glActiveTexture_enc(ctx, texture);
1262 void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1264 GL2Encoder* ctx = (GL2Encoder*)self;
1265 GLClientState* state = ctx->m_state;
1269 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1271 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1272 ctx->m_glBindTexture_enc(ctx, target, texture);
1276 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
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);
1287 if (target != priorityTarget) {
1288 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1289 state->getBoundTexture(GL_TEXTURE_2D));
1293 if (target == priorityTarget) {
1294 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1298 void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1300 GL2Encoder* ctx = (GL2Encoder*)self;
1301 GLClientState* state = ctx->m_state;
1303 state->deleteTextures(n, textures);
1304 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1307 void GL2Encoder::s_glGetTexParameterfv(void* self,
1308 GLenum target, GLenum pname, GLfloat* params)
1310 GL2Encoder* ctx = (GL2Encoder*)self;
1311 const GLClientState* state = ctx->m_state;
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();
1318 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1322 void GL2Encoder::s_glGetTexParameteriv(void* self,
1323 GLenum target, GLenum pname, GLint* params)
1325 GL2Encoder* ctx = (GL2Encoder*)self;
1326 const GLClientState* state = ctx->m_state;
1329 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
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();
1339 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1345 static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1348 case GL_TEXTURE_MIN_FILTER:
1349 case GL_TEXTURE_MAG_FILTER:
1350 return param == GL_NEAREST || param == GL_LINEAR;
1352 case GL_TEXTURE_WRAP_S:
1353 case GL_TEXTURE_WRAP_T:
1354 return param == GL_CLAMP_TO_EDGE;
1361 void GL2Encoder::s_glTexParameterf(void* self,
1362 GLenum target, GLenum pname, GLfloat param)
1364 GL2Encoder* ctx = (GL2Encoder*)self;
1365 const GLClientState* state = ctx->m_state;
1367 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1368 !isValidTextureExternalParam(pname, (GLenum)param)),
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();
1376 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1380 void GL2Encoder::s_glTexParameterfv(void* self,
1381 GLenum target, GLenum pname, const GLfloat* params)
1383 GL2Encoder* ctx = (GL2Encoder*)self;
1384 const GLClientState* state = ctx->m_state;
1386 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1387 !isValidTextureExternalParam(pname, (GLenum)params[0])),
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();
1395 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1399 void GL2Encoder::s_glTexParameteri(void* self,
1400 GLenum target, GLenum pname, GLint param)
1402 GL2Encoder* ctx = (GL2Encoder*)self;
1403 const GLClientState* state = ctx->m_state;
1405 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1406 !isValidTextureExternalParam(pname, (GLenum)param)),
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();
1414 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
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)
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();
1429 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1430 height, border, format, type, 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)
1438 GL2Encoder* ctx = (GL2Encoder*)self;
1439 GLint maxTextureSize;
1440 ctx->glGetIntegerv(self, GL_MAX_TEXTURE_SIZE, &maxTextureSize);
1442 SET_ERROR_IF((level < 0 || level > log2(maxTextureSize)), GL_INVALID_VALUE);
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();
1450 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
1451 height, format, type, pixels);
1455 void GL2Encoder::s_glTexParameteriv(void* self,
1456 GLenum target, GLenum pname, const GLint* params)
1458 GL2Encoder* ctx = (GL2Encoder*)self;
1459 const GLClientState* state = ctx->m_state;
1461 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1462 !isValidTextureExternalParam(pname, (GLenum)params[0])),
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();
1470 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
1474 void GL2Encoder::override2DTextureTarget(GLenum target)
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));
1483 void GL2Encoder::restore2DTextureTarget()
1485 GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1486 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1487 m_state->getBoundTexture(priorityTarget));