blob: 80a2cda7368d2a5bbd25c051990fcc4c630a6513 [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);
659 SET_ERROR_IF(!shaderData, GL_INVALID_VALUE);
660
661 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
662 char *str = new char[len + 1];
663 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
664
665 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
666 // Perhaps we can borrow Mesa's pre-processor?
667
668 if (!replaceSamplerExternalWith2D(str, shaderData)) {
669 delete str;
670 ctx->setError(GL_OUT_OF_MEMORY);
671 return;
672 }
673
674 ctx->glShaderString(ctx, shader, str, len + 1);
675 delete str;
676}
677
678void GL2Encoder::s_glFinish(void *self)
679{
680 GL2Encoder *ctx = (GL2Encoder *)self;
681 ctx->glFinishRoundTrip(self);
682}
683
684void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
685{
686 GL2Encoder *ctx = (GL2Encoder *)self;
687 ctx->m_glLinkProgram_enc(self, program);
688
689 GLint linkStatus = 0;
690 ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
691 if (!linkStatus)
692 return;
693
694 //get number of active uniforms in the program
695 GLint numUniforms=0;
696 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
697 ctx->m_shared->initProgramData(program,numUniforms);
698
699 //get the length of the longest uniform name
700 GLint maxLength=0;
701 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
702
703 GLint size;
704 GLenum type;
705 GLchar *name = new GLchar[maxLength+1];
706 GLint location;
707 //for each active uniform, get its size and starting location.
708 for (GLint i=0 ; i<numUniforms ; ++i)
709 {
710 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
711 location = ctx->m_glGetUniformLocation_enc(self, program, name);
712 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
713 }
714 ctx->m_shared->setupLocationShiftWAR(program);
715
716 delete[] name;
717}
718
719void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
720{
721 GL2Encoder *ctx = (GL2Encoder*)self;
722 ctx->m_glDeleteProgram_enc(self, program);
723
724 ctx->m_shared->deleteProgramData(program);
725}
726
727void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
728{
729 GL2Encoder *ctx = (GL2Encoder*)self;
730 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
731 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
732 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
733 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
734 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
735}
736void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
737{
738 GL2Encoder *ctx = (GL2Encoder*)self;
739 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
740 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
741 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
742 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
743 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
744}
745
746GLuint GL2Encoder::s_glCreateProgram(void * self)
747{
748 GL2Encoder *ctx = (GL2Encoder*)self;
749 GLuint program = ctx->m_glCreateProgram_enc(self);
750 if (program!=0)
751 ctx->m_shared->addProgramData(program);
752 return program;
753}
754
755GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
756{
757 GL2Encoder *ctx = (GL2Encoder*)self;
758 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
759 if (shader != 0) {
760 if (!ctx->m_shared->addShaderData(shader)) {
761 ctx->m_glDeleteShader_enc(self, shader);
762 return 0;
763 }
764 }
765 return shader;
766}
767
bohu56bf82f2014-10-17 15:35:48 -0700768void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
769 GLsizei* count, GLuint* shaders)
770{
771 GL2Encoder *ctx = (GL2Encoder*)self;
772 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
773 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
774}
775
776void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
777 GLsizei* length, GLchar* source)
778{
779 GL2Encoder *ctx = (GL2Encoder*)self;
780 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
781 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
782}
783
784void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
785 GLsizei* length, GLchar* infolog)
786{
787 GL2Encoder *ctx = (GL2Encoder*)self;
788 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
789 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
790}
791
792void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
793 GLsizei* length, GLchar* infolog)
794{
795 GL2Encoder *ctx = (GL2Encoder*)self;
796 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
797 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
798}
799
keunyoungb85b2752013-03-08 12:28:03 -0800800void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
801{
802 GL2Encoder *ctx = (GL2Encoder*)self;
803 ctx->m_glDeleteShader_enc(self,shader);
804 ctx->m_shared->unrefShaderData(shader);
805}
806
807void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
808{
809 GL2Encoder *ctx = (GL2Encoder*)self;
810 ctx->m_glAttachShader_enc(self, program, shader);
811 ctx->m_shared->attachShader(program, shader);
812}
813
814void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
815{
816 GL2Encoder *ctx = (GL2Encoder*)self;
817 ctx->m_glDetachShader_enc(self, program, shader);
818 ctx->m_shared->detachShader(program, shader);
819}
820
821int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
822{
823 if (!name) return -1;
824
825 GL2Encoder *ctx = (GL2Encoder*)self;
826
827 // if we need the uniform location WAR
828 // parse array index from the end of the name string
829 int arrIndex = 0;
830 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
831 if (needLocationWAR) {
832 int namelen = strlen(name);
833 if (name[namelen-1] == ']') {
834 char *brace = strrchr(name,'[');
835 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
836 return -1;
837 }
838
839 }
840 }
841
842 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
843 if (hostLoc >= 0 && needLocationWAR) {
844 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
845 }
846 return hostLoc;
847}
848
849bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
850{
851 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
852 return false;
853
854 m_state->setActiveTextureUnit(texUnit);
855
856 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
857 if (newTarget != oldTarget) {
858 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
859 m_state->disableTextureTarget(GL_TEXTURE_2D);
860 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
861 } else {
862 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
863 m_state->enableTextureTarget(GL_TEXTURE_2D);
864 }
865 m_glActiveTexture_enc(this, texUnit);
866 m_glBindTexture_enc(this, GL_TEXTURE_2D,
867 m_state->getBoundTexture(newTarget));
868 return true;
869 }
870
871 return false;
872}
873
874void GL2Encoder::s_glUseProgram(void *self, GLuint program)
875{
876 GL2Encoder *ctx = (GL2Encoder*)self;
877 GLClientState* state = ctx->m_state;
878 GLSharedGroupPtr shared = ctx->m_shared;
879
880 ctx->m_glUseProgram_enc(self, program);
881 ctx->m_state->setCurrentProgram(program);
882
883 GLenum origActiveTexture = state->getActiveTextureUnit();
884 GLenum hostActiveTexture = origActiveTexture;
885 GLint samplerIdx = -1;
886 GLint samplerVal;
887 GLenum samplerTarget;
888 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
889 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
890 continue;
891 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
892 samplerTarget))
893 {
894 hostActiveTexture = GL_TEXTURE0 + samplerVal;
895 }
896 }
897 state->setActiveTextureUnit(origActiveTexture);
898 if (hostActiveTexture != origActiveTexture) {
899 ctx->m_glActiveTexture_enc(self, origActiveTexture);
900 }
901}
902
903void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
904{
905 GL2Encoder *ctx = (GL2Encoder*)self;
906 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
907 ctx->m_glUniform1f_enc(self, hostLoc, x);
908}
909
910void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
911{
912 GL2Encoder *ctx = (GL2Encoder*)self;
913 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
914 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
915}
916
917void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
918{
919 GL2Encoder *ctx = (GL2Encoder*)self;
920 GLClientState* state = ctx->m_state;
921 GLSharedGroupPtr shared = ctx->m_shared;
922
923 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
924 ctx->m_glUniform1i_enc(self, hostLoc, x);
925
926 GLenum target;
927 if (shared->setSamplerUniform(state->currentProgram(), location, x, &target)) {
928 GLenum origActiveTexture = state->getActiveTextureUnit();
929 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
930 ctx->m_glActiveTexture_enc(self, origActiveTexture);
931 }
932 state->setActiveTextureUnit(origActiveTexture);
933 }
934}
935
936void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
937{
938 GL2Encoder *ctx = (GL2Encoder*)self;
939 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
940 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
941}
942
943void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
944{
945 GL2Encoder *ctx = (GL2Encoder*)self;
946 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
947 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
948}
949
950void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
951{
952 GL2Encoder *ctx = (GL2Encoder*)self;
953 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
954 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
955}
956
957void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
958{
959 GL2Encoder *ctx = (GL2Encoder*)self;
960 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
961 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
962}
963
964void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
965{
966 GL2Encoder *ctx = (GL2Encoder*)self;
967 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
968 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
969}
970
971void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
972{
973 GL2Encoder *ctx = (GL2Encoder*)self;
974 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
975 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
976}
977
978void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
979{
980 GL2Encoder *ctx = (GL2Encoder*)self;
981 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
982 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
983}
984
985void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
986{
987 GL2Encoder *ctx = (GL2Encoder*)self;
988 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
989 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
990}
991
992void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
993{
994 GL2Encoder *ctx = (GL2Encoder*)self;
995 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
996 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
997}
998
999void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1000{
1001 GL2Encoder *ctx = (GL2Encoder*)self;
1002 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1003 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1004}
1005
1006void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1007{
1008 GL2Encoder *ctx = (GL2Encoder*)self;
1009 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1010 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1011}
1012
1013void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1014{
1015 GL2Encoder *ctx = (GL2Encoder*)self;
1016 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1017 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1018}
1019
1020void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1021{
1022 GL2Encoder *ctx = (GL2Encoder*)self;
1023 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1024 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1025}
1026
1027void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1028{
1029 GL2Encoder *ctx = (GL2Encoder*)self;
1030 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1031 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1032}
1033
1034void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1035{
1036 GL2Encoder *ctx = (GL2Encoder*)self;
1037 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1038 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1039}
1040
1041void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1042{
1043 GL2Encoder *ctx = (GL2Encoder*)self;
1044 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1045 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1046}
1047
1048void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1049{
1050 GL2Encoder* ctx = (GL2Encoder*)self;
1051 GLClientState* state = ctx->m_state;
1052 GLenum err;
1053
1054 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1055
1056 ctx->m_glActiveTexture_enc(ctx, texture);
1057}
1058
1059void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1060{
1061 GL2Encoder* ctx = (GL2Encoder*)self;
1062 GLClientState* state = ctx->m_state;
1063 GLenum err;
1064 GLboolean firstUse;
1065
1066 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1067
1068 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1069 ctx->m_glBindTexture_enc(ctx, target, texture);
1070 return;
1071 }
1072
1073 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1074
1075 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1076 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1077 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1078 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1079 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1080 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1081 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1082 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1083
1084 if (target != priorityTarget) {
1085 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1086 state->getBoundTexture(GL_TEXTURE_2D));
1087 }
1088 }
1089
1090 if (target == priorityTarget) {
1091 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1092 }
1093}
1094
1095void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1096{
1097 GL2Encoder* ctx = (GL2Encoder*)self;
1098 GLClientState* state = ctx->m_state;
1099
1100 state->deleteTextures(n, textures);
1101 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1102}
1103
1104void GL2Encoder::s_glGetTexParameterfv(void* self,
1105 GLenum target, GLenum pname, GLfloat* params)
1106{
1107 GL2Encoder* ctx = (GL2Encoder*)self;
1108 const GLClientState* state = ctx->m_state;
1109
1110 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1111 ctx->override2DTextureTarget(target);
1112 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
1113 ctx->restore2DTextureTarget();
1114 } else {
1115 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1116 }
1117}
1118
1119void GL2Encoder::s_glGetTexParameteriv(void* self,
1120 GLenum target, GLenum pname, GLint* params)
1121{
1122 GL2Encoder* ctx = (GL2Encoder*)self;
1123 const GLClientState* state = ctx->m_state;
1124
1125 switch (pname) {
1126 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1127 *params = 1;
1128 break;
1129
1130 default:
1131 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1132 ctx->override2DTextureTarget(target);
1133 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
1134 ctx->restore2DTextureTarget();
1135 } else {
1136 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1137 }
1138 break;
1139 }
1140}
1141
1142static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1143{
1144 switch (pname) {
1145 case GL_TEXTURE_MIN_FILTER:
1146 case GL_TEXTURE_MAG_FILTER:
1147 return param == GL_NEAREST || param == GL_LINEAR;
1148
1149 case GL_TEXTURE_WRAP_S:
1150 case GL_TEXTURE_WRAP_T:
1151 return param == GL_CLAMP_TO_EDGE;
1152
1153 default:
1154 return true;
1155 }
1156}
1157
1158void GL2Encoder::s_glTexParameterf(void* self,
1159 GLenum target, GLenum pname, GLfloat param)
1160{
1161 GL2Encoder* ctx = (GL2Encoder*)self;
1162 const GLClientState* state = ctx->m_state;
1163
1164 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1165 !isValidTextureExternalParam(pname, (GLenum)param)),
1166 GL_INVALID_ENUM);
1167
1168 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1169 ctx->override2DTextureTarget(target);
1170 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
1171 ctx->restore2DTextureTarget();
1172 } else {
1173 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1174 }
1175}
1176
1177void GL2Encoder::s_glTexParameterfv(void* self,
1178 GLenum target, GLenum pname, const GLfloat* params)
1179{
1180 GL2Encoder* ctx = (GL2Encoder*)self;
1181 const GLClientState* state = ctx->m_state;
1182
1183 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1184 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1185 GL_INVALID_ENUM);
1186
1187 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1188 ctx->override2DTextureTarget(target);
1189 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
1190 ctx->restore2DTextureTarget();
1191 } else {
1192 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1193 }
1194}
1195
1196void GL2Encoder::s_glTexParameteri(void* self,
1197 GLenum target, GLenum pname, GLint param)
1198{
1199 GL2Encoder* ctx = (GL2Encoder*)self;
1200 const GLClientState* state = ctx->m_state;
1201
1202 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1203 !isValidTextureExternalParam(pname, (GLenum)param)),
1204 GL_INVALID_ENUM);
1205
1206 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1207 ctx->override2DTextureTarget(target);
1208 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
1209 ctx->restore2DTextureTarget();
1210 } else {
1211 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
1212 }
1213}
1214
bohu26a92982014-11-25 16:50:37 -08001215void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
1216 GLint internalformat, GLsizei width, GLsizei height, GLint border,
1217 GLenum format, GLenum type, const GLvoid* pixels)
1218{
1219 GL2Encoder* ctx = (GL2Encoder*)self;
1220 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1221 ctx->override2DTextureTarget(target);
1222 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1223 height, border, format, type, pixels);
1224 ctx->restore2DTextureTarget();
1225 } else {
1226 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1227 height, border, format, type, pixels);
1228 }
1229}
1230
1231
keunyoungb85b2752013-03-08 12:28:03 -08001232void GL2Encoder::s_glTexParameteriv(void* self,
1233 GLenum target, GLenum pname, const GLint* params)
1234{
1235 GL2Encoder* ctx = (GL2Encoder*)self;
1236 const GLClientState* state = ctx->m_state;
1237
1238 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1239 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1240 GL_INVALID_ENUM);
1241
1242 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1243 ctx->override2DTextureTarget(target);
1244 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
1245 ctx->restore2DTextureTarget();
1246 } else {
1247 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
1248 }
1249}
1250
1251void GL2Encoder::override2DTextureTarget(GLenum target)
1252{
1253 if ((target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
1254 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)) {
1255 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1256 m_state->getBoundTexture(target));
1257 }
1258}
1259
1260void GL2Encoder::restore2DTextureTarget()
1261{
1262 GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1263 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1264 m_state->getBoundTexture(priorityTarget));
1265}