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