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