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