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