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