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