blob: f502df97a9fdefef92265c66b9aac44d13809fc8 [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
Lingfeng Yang69066602016-04-12 09:29:11 -070021#include <GLES2/gl2.h>
22#include <GLES2/gl2ext.h>
23#include <GLES2/gl2platform.h>
24
25#include <GLES3/gl3.h>
26
keunyoungb85b2752013-03-08 12:28:03 -080027#ifndef MIN
28#define MIN(a, b) ((a) < (b) ? (a) : (b))
29#endif
30
31static GLubyte *gVendorString= (GLubyte *) "Android";
32static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 2.0";
33static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 2.0";
Nicolas Capensfe2d51a2015-11-20 15:10:09 -050034static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external ";
keunyoungb85b2752013-03-08 12:28:03 -080035
Yu Ningdadc6b12016-05-31 16:40:54 +080036#define SET_ERROR(err) { \
keunyoungb85b2752013-03-08 12:28:03 -080037 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
38 ctx->setError(err); \
39 return; \
40 }
41
Yu Ningdadc6b12016-05-31 16:40:54 +080042#define SET_ERROR_IF(condition,err) if((condition)) { \
43 SET_ERROR(err) \
44 }
45
keunyoungb85b2752013-03-08 12:28:03 -080046
47#define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) { \
48 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
49 ctx->setError(err); \
50 return ret; \
51 }
52
53
Yahan Zhoub7f09082016-03-10 11:45:02 -080054GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
55 : gl2_encoder_context_t(stream, protocol)
keunyoungb85b2752013-03-08 12:28:03 -080056{
57 m_initialized = false;
58 m_state = NULL;
59 m_error = GL_NO_ERROR;
60 m_num_compressedTextureFormats = 0;
Lizhe Liue41f4ef2015-05-27 11:13:23 +080061 m_max_cubeMapTextureSize = 0;
62 m_max_renderBufferSize = 0;
63 m_max_textureSize = 0;
keunyoungb85b2752013-03-08 12:28:03 -080064 m_compressedTextureFormats = NULL;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010065
Lingfeng Yangde51dfb2016-10-17 22:48:59 -070066 m_drawCallFlushCount = 0;
67 m_primitiveRestartEnabled = false;
68 m_primitiveRestartIndex = 0;
69
keunyoungb85b2752013-03-08 12:28:03 -080070 //overrides
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010071#define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name
bohu56bf82f2014-10-17 15:35:48 -070072
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010073 OVERRIDE(glFlush);
74 OVERRIDE(glPixelStorei);
75 OVERRIDE(glGetString);
76 OVERRIDE(glBindBuffer);
77 OVERRIDE(glBufferData);
78 OVERRIDE(glBufferSubData);
79 OVERRIDE(glDeleteBuffers);
80 OVERRIDE(glDrawArrays);
81 OVERRIDE(glDrawElements);
82 OVERRIDE(glGetIntegerv);
83 OVERRIDE(glGetFloatv);
84 OVERRIDE(glGetBooleanv);
85 OVERRIDE(glVertexAttribPointer);
86 OVERRIDE(glEnableVertexAttribArray);
87 OVERRIDE(glDisableVertexAttribArray);
88 OVERRIDE(glGetVertexAttribiv);
89 OVERRIDE(glGetVertexAttribfv);
90 OVERRIDE(glGetVertexAttribPointerv);
keunyoungb85b2752013-03-08 12:28:03 -080091
Bo Hu73568cd2015-01-20 16:29:50 -080092 this->glShaderBinary = &s_glShaderBinary;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010093 this->glShaderSource = &s_glShaderSource;
94 this->glFinish = &s_glFinish;
keunyoungb85b2752013-03-08 12:28:03 -080095
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010096 OVERRIDE(glGetError);
97 OVERRIDE(glLinkProgram);
98 OVERRIDE(glDeleteProgram);
99 OVERRIDE(glGetUniformiv);
100 OVERRIDE(glGetUniformfv);
101 OVERRIDE(glCreateProgram);
102 OVERRIDE(glCreateShader);
103 OVERRIDE(glDeleteShader);
104 OVERRIDE(glAttachShader);
105 OVERRIDE(glDetachShader);
106 OVERRIDE(glGetAttachedShaders);
107 OVERRIDE(glGetShaderSource);
108 OVERRIDE(glGetShaderInfoLog);
109 OVERRIDE(glGetProgramInfoLog);
110
111 OVERRIDE(glGetUniformLocation);
112 OVERRIDE(glUseProgram);
113
114 OVERRIDE(glUniform1f);
115 OVERRIDE(glUniform1fv);
116 OVERRIDE(glUniform1i);
117 OVERRIDE(glUniform1iv);
118 OVERRIDE(glUniform2f);
119 OVERRIDE(glUniform2fv);
120 OVERRIDE(glUniform2i);
121 OVERRIDE(glUniform2iv);
122 OVERRIDE(glUniform3f);
123 OVERRIDE(glUniform3fv);
124 OVERRIDE(glUniform3i);
125 OVERRIDE(glUniform3iv);
126 OVERRIDE(glUniform4f);
127 OVERRIDE(glUniform4fv);
128 OVERRIDE(glUniform4i);
129 OVERRIDE(glUniform4iv);
130 OVERRIDE(glUniformMatrix2fv);
131 OVERRIDE(glUniformMatrix3fv);
132 OVERRIDE(glUniformMatrix4fv);
133
134 OVERRIDE(glActiveTexture);
135 OVERRIDE(glBindTexture);
136 OVERRIDE(glDeleteTextures);
137 OVERRIDE(glGetTexParameterfv);
138 OVERRIDE(glGetTexParameteriv);
139 OVERRIDE(glTexParameterf);
140 OVERRIDE(glTexParameterfv);
141 OVERRIDE(glTexParameteri);
142 OVERRIDE(glTexParameteriv);
bohu26a92982014-11-25 16:50:37 -0800143 OVERRIDE(glTexImage2D);
Yahan Zhou2a208292016-06-22 15:36:04 -0700144 OVERRIDE(glTexSubImage2D);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -0700145 OVERRIDE(glCopyTexImage2D);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700146
147 OVERRIDE(glGenRenderbuffers);
148 OVERRIDE(glDeleteRenderbuffers);
149 OVERRIDE(glBindRenderbuffer);
Lingfeng Yang69066602016-04-12 09:29:11 -0700150 OVERRIDE(glRenderbufferStorage);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700151 OVERRIDE(glFramebufferRenderbuffer);
152
153 OVERRIDE(glGenFramebuffers);
154 OVERRIDE(glDeleteFramebuffers);
155 OVERRIDE(glBindFramebuffer);
156 OVERRIDE(glFramebufferTexture2D);
157 OVERRIDE(glFramebufferTexture3DOES);
158 OVERRIDE(glGetFramebufferAttachmentParameteriv);
Lingfeng Yang69066602016-04-12 09:29:11 -0700159
160 OVERRIDE(glCheckFramebufferStatus);
keunyoungb85b2752013-03-08 12:28:03 -0800161}
162
163GL2Encoder::~GL2Encoder()
164{
165 delete m_compressedTextureFormats;
166}
167
168GLenum GL2Encoder::s_glGetError(void * self)
169{
170 GL2Encoder *ctx = (GL2Encoder *)self;
171 GLenum err = ctx->getError();
172 if(err != GL_NO_ERROR) {
173 ctx->setError(GL_NO_ERROR);
174 return err;
175 }
176
177 return ctx->m_glGetError_enc(self);
Yahan Zhouae30fe82016-08-10 21:15:45 +0000178
keunyoungb85b2752013-03-08 12:28:03 -0800179}
180
181void GL2Encoder::s_glFlush(void *self)
182{
183 GL2Encoder *ctx = (GL2Encoder *) self;
184 ctx->m_glFlush_enc(self);
185 ctx->m_stream->flush();
186}
187
188const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
189{
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100190 (void)self;
191
keunyoungb85b2752013-03-08 12:28:03 -0800192 GLubyte *retval = (GLubyte *) "";
193 switch(name) {
194 case GL_VENDOR:
195 retval = gVendorString;
196 break;
197 case GL_RENDERER:
198 retval = gRendererString;
199 break;
200 case GL_VERSION:
201 retval = gVersionString;
202 break;
203 case GL_EXTENSIONS:
204 retval = gExtensionsString;
205 break;
206 }
207 return retval;
208}
209
210void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
211{
212 GL2Encoder *ctx = (GL2Encoder *)self;
213 ctx->m_glPixelStorei_enc(ctx, param, value);
214 assert(ctx->m_state != NULL);
215 ctx->m_state->setPixelStore(param, value);
216}
217
218
219void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
220{
221 GL2Encoder *ctx = (GL2Encoder *) self;
222 assert(ctx->m_state != NULL);
223 ctx->m_state->bindBuffer(target, id);
224 // TODO set error state if needed;
225 ctx->m_glBindBuffer_enc(self, target, id);
226}
227
228void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
229{
230 GL2Encoder *ctx = (GL2Encoder *) self;
bohub0f0cdf2014-11-06 18:08:07 -0800231 SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800232 GLuint bufferId = ctx->m_state->getBuffer(target);
233 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
234 SET_ERROR_IF(size<0, GL_INVALID_VALUE);
235
236 ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
237 ctx->m_glBufferData_enc(self, target, size, data, usage);
238}
239
240void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
241{
242 GL2Encoder *ctx = (GL2Encoder *) self;
bohub0f0cdf2014-11-06 18:08:07 -0800243 SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800244 GLuint bufferId = ctx->m_state->getBuffer(target);
245 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
246
247 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
248 SET_ERROR_IF(res, res);
249
250 ctx->m_glBufferSubData_enc(self, target, offset, size, data);
251}
252
253void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
254{
255 GL2Encoder *ctx = (GL2Encoder *) self;
256 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
257 for (int i=0; i<n; i++) {
258 ctx->m_shared->deleteBufferData(buffers[i]);
bohub0f0cdf2014-11-06 18:08:07 -0800259 ctx->m_state->unBindBuffer(buffers[i]);
keunyoungb85b2752013-03-08 12:28:03 -0800260 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
261 }
262}
263
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700264static bool isValidVertexAttribIndex(void *self, GLuint indx)
265{
266 GL2Encoder *ctx = (GL2Encoder *) self;
267 GLint maxIndex;
268 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
269 return indx < maxIndex;
270}
271
272static bool isValidVertexAttribType(GLenum type)
273{
274 bool retval = false;
275 switch (type) {
276 case GL_BYTE:
277 case GL_UNSIGNED_BYTE:
278 case GL_SHORT:
279 case GL_UNSIGNED_SHORT:
280 case GL_FIXED:
281 case GL_FLOAT:
282 // The following are technically only available if certain GLES2 extensions are.
283 // However, they are supported by desktop GL3, which is a reasonable requirement
284 // for the desktop GL version. Therefore, consider them valid.
285 case GL_INT:
286 case GL_UNSIGNED_INT:
287 case GL_HALF_FLOAT_OES:
288 retval = true;
289 break;
290 }
291 return retval;
292}
293
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100294void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
keunyoungb85b2752013-03-08 12:28:03 -0800295{
296 GL2Encoder *ctx = (GL2Encoder *)self;
297 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700298 SET_ERROR_IF(!isValidVertexAttribIndex(self, indx), GL_INVALID_VALUE);
299 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
300 SET_ERROR_IF(!isValidVertexAttribType(type), GL_INVALID_ENUM);
301 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800302 ctx->m_state->setState(indx, size, type, normalized, stride, ptr);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800303 if (ctx->m_state->currentArrayVbo() != 0) {
304 ctx->glVertexAttribPointerOffset(ctx, indx, size, type, normalized, stride, (uintptr_t)ptr);
305 } else {
306 // TODO: if a nonzero VAO is bound, issue GL_INVALID_OPERATION.
307 }
keunyoungb85b2752013-03-08 12:28:03 -0800308}
309
310void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
311{
312 GL2Encoder *ctx = (GL2Encoder *) self;
313 assert(ctx->m_state != NULL);
314 GLClientState* state = ctx->m_state;
315
316 switch (param) {
Yu Ningdadc6b12016-05-31 16:40:54 +0800317 case GL_MAJOR_VERSION:
318 case GL_MINOR_VERSION:
319 // These two parameters are not supported by GLESv2
320 // TODO: Set *ptr appropriately when GLESv3 support is ready
321 SET_ERROR(GL_INVALID_ENUM);
322
keunyoungb85b2752013-03-08 12:28:03 -0800323 case GL_NUM_SHADER_BINARY_FORMATS:
324 *ptr = 0;
325 break;
326 case GL_SHADER_BINARY_FORMATS:
327 // do nothing
328 break;
329
330 case GL_COMPRESSED_TEXTURE_FORMATS: {
331 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
332 if (ctx->m_num_compressedTextureFormats > 0 &&
333 compressedTextureFormats != NULL) {
334 memcpy(ptr, compressedTextureFormats,
335 ctx->m_num_compressedTextureFormats * sizeof(GLint));
336 }
337 break;
338 }
339
340 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
341 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
342 case GL_MAX_TEXTURE_IMAGE_UNITS:
343 ctx->m_glGetIntegerv_enc(self, param, ptr);
344 *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
345 break;
346
347 case GL_TEXTURE_BINDING_2D:
348 *ptr = state->getBoundTexture(GL_TEXTURE_2D);
349 break;
350 case GL_TEXTURE_BINDING_EXTERNAL_OES:
351 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
352 break;
353
Lingfeng Yangb0176982016-03-01 21:27:49 -0800354 case GL_MAX_VERTEX_ATTRIBS:
355 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
356 ctx->m_glGetIntegerv_enc(self, param, ptr);
357 ctx->m_state->setMaxVertexAttribs(*ptr);
Yahan Zhoua5c36842016-06-01 12:49:39 -0700358 }
359 break;
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800360 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
361 if (ctx->m_max_cubeMapTextureSize != 0) {
362 *ptr = ctx->m_max_cubeMapTextureSize;
363 } else {
364 ctx->m_glGetIntegerv_enc(self, param, ptr);
365 ctx->m_max_cubeMapTextureSize = *ptr;
366 }
367 break;
368 case GL_MAX_RENDERBUFFER_SIZE:
369 if (ctx->m_max_renderBufferSize != 0) {
370 *ptr = ctx->m_max_renderBufferSize;
371 } else {
372 ctx->m_glGetIntegerv_enc(self, param, ptr);
373 ctx->m_max_renderBufferSize = *ptr;
374 }
375 break;
376 case GL_MAX_TEXTURE_SIZE:
377 if (ctx->m_max_textureSize != 0) {
378 *ptr = ctx->m_max_textureSize;
379 } else {
380 ctx->m_glGetIntegerv_enc(self, param, ptr);
381 ctx->m_max_textureSize = *ptr;
Lingfeng Yangb0176982016-03-01 21:27:49 -0800382 }
383 break;
keunyoungb85b2752013-03-08 12:28:03 -0800384 default:
385 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
386 ctx->m_glGetIntegerv_enc(self, param, ptr);
387 }
388 break;
389 }
390}
391
392
393void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
394{
395 GL2Encoder *ctx = (GL2Encoder *)self;
396 assert(ctx->m_state != NULL);
397 GLClientState* state = ctx->m_state;
398
399 switch (param) {
400 case GL_NUM_SHADER_BINARY_FORMATS:
401 *ptr = 0;
402 break;
403 case GL_SHADER_BINARY_FORMATS:
404 // do nothing
405 break;
406
407 case GL_COMPRESSED_TEXTURE_FORMATS: {
408 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
409 if (ctx->m_num_compressedTextureFormats > 0 &&
410 compressedTextureFormats != NULL) {
411 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
412 ptr[i] = (GLfloat) compressedTextureFormats[i];
413 }
414 }
415 break;
416 }
417
418 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
419 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
420 case GL_MAX_TEXTURE_IMAGE_UNITS:
421 ctx->m_glGetFloatv_enc(self, param, ptr);
422 *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
423 break;
424
425 case GL_TEXTURE_BINDING_2D:
426 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
427 break;
428 case GL_TEXTURE_BINDING_EXTERNAL_OES:
429 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
430 break;
431
432 default:
433 if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
434 ctx->m_glGetFloatv_enc(self, param, ptr);
435 }
436 break;
437 }
438}
439
440
441void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
442{
443 GL2Encoder *ctx = (GL2Encoder *)self;
444 assert(ctx->m_state != NULL);
445 GLClientState* state = ctx->m_state;
446
447 switch (param) {
448 case GL_NUM_SHADER_BINARY_FORMATS:
449 *ptr = GL_FALSE;
450 break;
451 case GL_SHADER_BINARY_FORMATS:
452 // do nothing
453 break;
454
455 case GL_COMPRESSED_TEXTURE_FORMATS: {
456 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
457 if (ctx->m_num_compressedTextureFormats > 0 &&
458 compressedTextureFormats != NULL) {
459 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
460 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
461 }
462 }
463 break;
464 }
465
466 case GL_TEXTURE_BINDING_2D:
467 *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
468 break;
469 case GL_TEXTURE_BINDING_EXTERNAL_OES:
470 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
471 ? GL_TRUE : GL_FALSE;
472 break;
473
474 default:
475 if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
476 ctx->m_glGetBooleanv_enc(self, param, ptr);
477 }
bohu05101d22014-11-17 16:28:42 -0800478 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
keunyoungb85b2752013-03-08 12:28:03 -0800479 break;
480 }
481}
482
483
484void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
485{
486 GL2Encoder *ctx = (GL2Encoder *)self;
487 assert(ctx->m_state);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700488 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800489 ctx->m_glEnableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800490 ctx->m_state->enable(index, 1);
491}
492
493void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
494{
495 GL2Encoder *ctx = (GL2Encoder *)self;
496 assert(ctx->m_state);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700497 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800498 ctx->m_glDisableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800499 ctx->m_state->enable(index, 0);
500}
501
502
503void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
504{
505 GL2Encoder *ctx = (GL2Encoder *)self;
506 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700507 GLint maxIndex;
508 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
509 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800510
511 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
512 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
513 }
514}
515
516void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
517{
518 GL2Encoder *ctx = (GL2Encoder *)self;
519 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700520 GLint maxIndex;
521 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
522 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800523
524 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
525 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
526 }
527}
528
529void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
530{
531 GL2Encoder *ctx = (GL2Encoder *)self;
532 if (ctx->m_state == NULL) return;
Lingfeng Yang5e100432016-04-08 12:46:42 -0700533 GLint maxIndex;
534 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
535 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
536 SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100537 (void)pname;
538
keunyoungb85b2752013-03-08 12:28:03 -0800539 const GLClientState::VertexAttribState *va_state = ctx->m_state->getState(index);
540 if (va_state != NULL) {
541 *pointer = va_state->data;
542 }
543}
544
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700545void GL2Encoder::calcIndexRange(const void* indices,
546 GLenum type,
547 GLsizei count,
548 int* minIndex_out,
549 int* maxIndex_out) {
550 switch(type) {
551 case GL_BYTE:
552 case GL_UNSIGNED_BYTE:
553 GLUtils::minmaxExcept(
554 (unsigned char *)indices, count,
555 minIndex_out, maxIndex_out,
556 m_primitiveRestartEnabled, (unsigned char)m_primitiveRestartIndex);
557 break;
558 case GL_SHORT:
559 case GL_UNSIGNED_SHORT:
560 GLUtils::minmaxExcept(
561 (unsigned short *)indices, count,
562 minIndex_out, maxIndex_out,
563 m_primitiveRestartEnabled, (unsigned short)m_primitiveRestartIndex);
564 break;
565 case GL_INT:
566 case GL_UNSIGNED_INT:
567 GLUtils::minmaxExcept(
568 (unsigned int *)indices, count,
569 minIndex_out, maxIndex_out,
570 m_primitiveRestartEnabled, (unsigned int)m_primitiveRestartIndex);
571 break;
572 default:
573 ALOGE("unsupported index buffer type %d\n", type);
574 }
575}
576
577void* GL2Encoder::recenterIndices(const void* src,
578 GLenum type,
579 GLsizei count,
580 int minIndex) {
581
582 void* adjustedIndices = (void*)src;
583
584 if (minIndex != 0) {
585 adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count);
586 switch(type) {
587 case GL_BYTE:
588 case GL_UNSIGNED_BYTE:
589 GLUtils::shiftIndicesExcept(
590 (unsigned char *)src,
591 (unsigned char *)adjustedIndices,
592 count, -minIndex,
593 m_primitiveRestartEnabled,
594 (unsigned char)m_primitiveRestartIndex);
595 break;
596 case GL_SHORT:
597 case GL_UNSIGNED_SHORT:
598 GLUtils::shiftIndicesExcept(
599 (unsigned short *)src,
600 (unsigned short *)adjustedIndices,
601 count, -minIndex,
602 m_primitiveRestartEnabled,
603 (unsigned short)m_primitiveRestartIndex);
604 break;
605 case GL_INT:
606 case GL_UNSIGNED_INT:
607 GLUtils::shiftIndicesExcept(
608 (unsigned int *)src,
609 (unsigned int *)adjustedIndices,
610 count, -minIndex,
611 m_primitiveRestartEnabled,
612 (unsigned int)m_primitiveRestartIndex);
613 break;
614 default:
615 ALOGE("unsupported index buffer type %d\n", type);
616 }
617 }
618
619 return adjustedIndices;
620}
621
622void GL2Encoder::getBufferIndexRange(BufferData* buf,
623 const void* dataWithOffset,
624 GLenum type,
625 GLsizei count,
626 GLintptr offset,
627 int* minIndex_out,
628 int* maxIndex_out) {
629
630 if (buf->m_indexRangeCache.findRange(
631 type, (size_t)offset, count,
632 m_primitiveRestartEnabled,
633 minIndex_out,
634 maxIndex_out)) {
635 return;
636 }
637
638 calcIndexRange(dataWithOffset, type, count, minIndex_out, maxIndex_out);
639
640 buf->m_indexRangeCache.addRange(
641 type, (size_t)offset, count, m_primitiveRestartEnabled,
642 *minIndex_out, *maxIndex_out);
643}
keunyoungb85b2752013-03-08 12:28:03 -0800644
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800645// For detecting legacy usage of glVertexAttribPointer
646void GL2Encoder::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) const {
647 if (hasClientArrays) *hasClientArrays = false;
648 if (hasVBOs) *hasVBOs = false;
649
650 for (int i = 0; i < m_state->nLocations(); i++) {
651 const GLClientState::VertexAttribState *state = m_state->getState(i);
652 if (state->enabled) {
653 if (state->bufferObject == 0 && state->data && hasClientArrays) {
654 *hasClientArrays = true;
655 }
656 if (state->bufferObject != 0 && hasVBOs) {
657 *hasVBOs = true;
658 }
659 }
660 }
661}
662
663void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count, bool hasClientArrays)
keunyoungb85b2752013-03-08 12:28:03 -0800664{
665 assert(m_state);
666
Lingfeng Yang398162b2016-05-26 14:18:33 -0700667 GLuint lastBoundVbo = m_state->currentArrayVbo();
keunyoungb85b2752013-03-08 12:28:03 -0800668 for (int i = 0; i < m_state->nLocations(); i++) {
669 bool enableDirty;
670 const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty);
671
672 if (!state) {
673 continue;
674 }
675
676 if (!enableDirty && !state->enabled) {
677 continue;
678 }
679
keunyoungb85b2752013-03-08 12:28:03 -0800680 if (state->enabled) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800681 if (hasClientArrays && lastBoundVbo != state->bufferObject) {
Lingfeng Yang398162b2016-05-26 14:18:33 -0700682 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject);
683 lastBoundVbo = state->bufferObject;
684 }
keunyoungb85b2752013-03-08 12:28:03 -0800685
686 unsigned int datalen = state->elementSize * count;
687 int stride = state->stride == 0 ? state->elementSize : state->stride;
688 int firstIndex = stride * first;
689
690 if (state->bufferObject == 0) {
Yahan Zhou3f2f1b42016-12-01 13:49:44 -0800691 if (state->elementSize == 0) {
692 // The vertex attribute array is uninitialized. Abandon it.
693 ALOGE("a vertex attribute array is uninitialized. Skipping corresponding vertex attribute.");
694 this->m_glDisableVertexAttribArray_enc(this, i);
695 continue;
696 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700697 m_glEnableVertexAttribArray_enc(this, i);
keunyoungb85b2752013-03-08 12:28:03 -0800698 this->glVertexAttribPointerData(this, i, state->size, state->type, state->normalized, state->stride,
699 (unsigned char *)state->data + firstIndex, datalen);
700 } else {
Yahan Zhou5507c042016-06-01 17:24:28 -0700701 const BufferData* buf = m_shared->getBufferData(state->bufferObject);
702 // The following expression actually means bufLen = stride*count;
703 // But the last element doesn't have to fill up the whole stride.
704 // So it becomes the current form.
705 unsigned int bufLen = stride * (count - 1) + state->elementSize;
706 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800707 if (hasClientArrays) {
708 m_glEnableVertexAttribArray_enc(this, i);
709 this->glVertexAttribPointerOffset(this, i, state->size, state->type, state->normalized, state->stride,
710 (uintptr_t) state->data + firstIndex);
711 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700712 } else {
713 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute.");
714 m_glDisableVertexAttribArray_enc(this, i);
715 }
keunyoungb85b2752013-03-08 12:28:03 -0800716 }
717 } else {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800718 if (hasClientArrays) {
719 this->m_glDisableVertexAttribArray_enc(this, i);
720 }
keunyoungb85b2752013-03-08 12:28:03 -0800721 }
722 }
Lingfeng Yang398162b2016-05-26 14:18:33 -0700723
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800724 if (hasClientArrays && lastBoundVbo != m_state->currentArrayVbo()) {
Lingfeng Yang398162b2016-05-26 14:18:33 -0700725 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
726 }
keunyoungb85b2752013-03-08 12:28:03 -0800727}
728
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700729void GL2Encoder::flushDrawCall() {
730 // The idea is that
731 // commitBuffer / write() to qemu pipe will
732 // take at least ~20-60us, and for cases like
733 // sendVertexAttributes / glDrawElementsOffset,
734 // which sends only around few hundred bytes,
735 // we can get away with sending
736 // two at a time in the same ~20-60us,
737 // reducing average latency and gaining ~1 fps
738 // in Antutu on Linux + Quadro K2200.
739 if (m_drawCallFlushCount % 2 == 0) {
740 m_stream->flush();
741 }
742 m_drawCallFlushCount++;
743}
744
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700745static bool isValidDrawMode(GLenum mode)
746{
747 bool retval = false;
748 switch (mode) {
749 case GL_POINTS:
750 case GL_LINE_STRIP:
751 case GL_LINE_LOOP:
752 case GL_LINES:
753 case GL_TRIANGLE_STRIP:
754 case GL_TRIANGLE_FAN:
755 case GL_TRIANGLES:
756 retval = true;
757 }
758 return retval;
759}
760
keunyoungb85b2752013-03-08 12:28:03 -0800761void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
762{
763 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700764 assert(ctx->m_state != NULL);
765 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
766 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhoud6217a52016-02-10 16:10:46 -0800767
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800768 bool has_client_vertex_arrays = false;
769 bool has_indirect_arrays = false;
770 ctx->getVBOUsage(&has_client_vertex_arrays,
771 &has_indirect_arrays);
772
773 if (has_client_vertex_arrays ||
774 (!has_client_vertex_arrays &&
775 !has_indirect_arrays)) {
776 ctx->sendVertexAttributes(first, count, true);
777 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
778 } else {
779 ctx->sendVertexAttributes(0, count, false);
780 ctx->m_glDrawArrays_enc(ctx, mode, first, count);
781 }
Yahan Zhoue57bd752016-06-06 12:30:39 -0700782 ctx->m_stream->flush();
keunyoungb85b2752013-03-08 12:28:03 -0800783}
784
785
786void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
787{
788
789 GL2Encoder *ctx = (GL2Encoder *)self;
790 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700791 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
792 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -0700793 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800794
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800795 bool has_client_vertex_arrays = false;
keunyoungb85b2752013-03-08 12:28:03 -0800796 bool has_indirect_arrays = false;
797 int nLocations = ctx->m_state->nLocations();
Yahan Zhou5507c042016-06-01 17:24:28 -0700798 GLintptr offset = 0;
keunyoungb85b2752013-03-08 12:28:03 -0800799
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800800 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
keunyoungb85b2752013-03-08 12:28:03 -0800801
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800802 if (!has_client_vertex_arrays && !has_indirect_arrays) {
Yahan Zhou3f2f1b42016-12-01 13:49:44 -0800803 ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -0700804 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
805 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800806 }
807
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700808 BufferData* buf = NULL;
Yahan Zhou5507c042016-06-01 17:24:28 -0700809 int minIndex = 0, maxIndex = 0;
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700810
811 // For validation/immediate index array purposes,
812 // we need the min/max vertex index of the index array.
813 // If the VBO != 0, this may not be the first time we have
814 // used this particular index buffer. getBufferIndexRange
815 // can more quickly get min/max vertex index by
816 // cachine previous results.
817 if (ctx->m_state->currentIndexVbo() != 0) {
818 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
819 offset = (GLintptr)indices;
820 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
821 ctx->getBufferIndexRange(buf,
822 indices,
823 type,
824 (GLsizei)count,
825 (GLintptr)indices, // offset, really
826 &minIndex, &maxIndex);
827 } else {
828 // In this case, the |indices| field holds a real
829 // array, so calculate the indices now. They will
830 // also be needed to know how much data to
831 // transfer to host.
832 ctx->calcIndexRange(indices,
833 type,
834 count,
835 &minIndex,
836 &maxIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -0700837 }
838
keunyoungb85b2752013-03-08 12:28:03 -0800839 bool adjustIndices = true;
840 if (ctx->m_state->currentIndexVbo() != 0) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800841 if (!has_client_vertex_arrays) {
842 ctx->sendVertexAttributes(0, maxIndex + 1, false);
keunyoungb85b2752013-03-08 12:28:03 -0800843 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -0700844 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700845 ctx->flushDrawCall();
keunyoungb85b2752013-03-08 12:28:03 -0800846 adjustIndices = false;
847 } else {
848 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
849 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -0800850 }
851 }
852 if (adjustIndices) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700853 void *adjustedIndices =
854 ctx->recenterIndices(indices,
855 type,
856 count,
857 minIndex);
keunyoungb85b2752013-03-08 12:28:03 -0800858
keunyoungb85b2752013-03-08 12:28:03 -0800859 if (has_indirect_arrays || 1) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800860 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
keunyoungb85b2752013-03-08 12:28:03 -0800861 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
862 count * glSizeof(type));
Yahan Zhoue57bd752016-06-06 12:30:39 -0700863 ctx->m_stream->flush();
keunyoungb85b2752013-03-08 12:28:03 -0800864 // XXX - OPTIMIZATION (see the other else branch) should be implemented
865 if(!has_indirect_arrays) {
866 //ALOGD("unoptimized drawelements !!!\n");
867 }
868 } else {
869 // we are all direct arrays and immidate mode index array -
870 // rebuild the arrays and the index array;
871 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
872 }
873 }
874}
875
876
877GLint * GL2Encoder::getCompressedTextureFormats()
878{
879 if (m_compressedTextureFormats == NULL) {
880 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
881 &m_num_compressedTextureFormats);
882 if (m_num_compressedTextureFormats > 0) {
883 // get number of texture formats;
884 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
885 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
886 }
887 }
888 return m_compressedTextureFormats;
889}
890
891// Replace uses of samplerExternalOES with sampler2D, recording the names of
892// modified shaders in data. Also remove
893// #extension GL_OES_EGL_image_external : require
894// statements.
895//
896// This implementation assumes the input has already been pre-processed. If not,
897// a few cases will be mishandled:
898//
899// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
900// the following code:
901// #if 1
902// uniform sampler2D mySampler;
903// #else
904// uniform samplerExternalOES mySampler;
905// #endif
906//
907// 2. Comments that look like sampler declarations will be incorrectly modified
908// and recorded:
909// // samplerExternalOES hahaFooledYou
910//
911// 3. However, GLSL ES does not have a concatentation operator, so things like
912// this (valid in C) are invalid and not a problem:
913// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
914// SAMPLER(ExternalOES, mySampler);
915//
916static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
917{
918 static const char STR_HASH_EXTENSION[] = "#extension";
919 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
920 static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
921 static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
922
923 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
924 char* c = str;
925 while ((c = strstr(c, STR_HASH_EXTENSION))) {
926 char* start = c;
927 c += sizeof(STR_HASH_EXTENSION)-1;
928 while (isspace(*c) && *c != '\0') {
929 c++;
930 }
931 if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
932 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
933 {
934 // #extension statements are terminated by end of line
935 c = start;
936 while (*c != '\0' && *c != '\r' && *c != '\n') {
937 *c++ = ' ';
938 }
939 }
940 }
941
942 // -- replace "samplerExternalOES" with "sampler2D" and record name
943 c = str;
944 while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
945 // Make sure "samplerExternalOES" isn't a substring of a larger token
946 if (c == str || !isspace(*(c-1))) {
947 c++;
948 continue;
949 }
950 char* sampler_start = c;
951 c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
952 if (!isspace(*c) && *c != '\0') {
953 continue;
954 }
955
956 // capture sampler name
957 while (isspace(*c) && *c != '\0') {
958 c++;
959 }
960 if (!isalpha(*c) && *c != '_') {
961 // not an identifier
962 return false;
963 }
964 char* name_start = c;
965 do {
966 c++;
967 } while (isalnum(*c) || *c == '_');
968 data->samplerExternalNames.push_back(
969 android::String8(name_start, c - name_start));
970
971 // memcpy instead of strcpy since we don't want the NUL terminator
972 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
973 }
974
975 return true;
976}
977
Bo Hu73568cd2015-01-20 16:29:50 -0800978void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
979{
980 GL2Encoder* ctx = (GL2Encoder*)self;
981 // Although it is not supported, need to set proper error code.
982 SET_ERROR_IF(1, GL_INVALID_ENUM);
983}
984
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100985void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -0800986{
987 GL2Encoder* ctx = (GL2Encoder*)self;
988 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Tina Zhang7a84f652014-12-04 12:37:30 +0800989 SET_ERROR_IF(!ctx->m_shared->isObject(shader), GL_INVALID_VALUE);
990 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
991 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800992
993 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
994 char *str = new char[len + 1];
995 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
996
997 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
998 // Perhaps we can borrow Mesa's pre-processor?
999
1000 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001001 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001002 ctx->setError(GL_OUT_OF_MEMORY);
1003 return;
1004 }
1005
1006 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001007 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001008}
1009
1010void GL2Encoder::s_glFinish(void *self)
1011{
1012 GL2Encoder *ctx = (GL2Encoder *)self;
1013 ctx->glFinishRoundTrip(self);
1014}
1015
1016void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1017{
1018 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -08001019 bool isProgram = ctx->m_shared->isProgram(program);
1020 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
1021 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
1022
keunyoungb85b2752013-03-08 12:28:03 -08001023 ctx->m_glLinkProgram_enc(self, program);
1024
1025 GLint linkStatus = 0;
1026 ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
1027 if (!linkStatus)
1028 return;
1029
1030 //get number of active uniforms in the program
1031 GLint numUniforms=0;
1032 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
1033 ctx->m_shared->initProgramData(program,numUniforms);
1034
1035 //get the length of the longest uniform name
1036 GLint maxLength=0;
1037 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
1038
1039 GLint size;
1040 GLenum type;
1041 GLchar *name = new GLchar[maxLength+1];
1042 GLint location;
1043 //for each active uniform, get its size and starting location.
1044 for (GLint i=0 ; i<numUniforms ; ++i)
1045 {
1046 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1047 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1048 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1049 }
1050 ctx->m_shared->setupLocationShiftWAR(program);
1051
1052 delete[] name;
1053}
1054
1055void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1056{
1057 GL2Encoder *ctx = (GL2Encoder*)self;
1058 ctx->m_glDeleteProgram_enc(self, program);
1059
1060 ctx->m_shared->deleteProgramData(program);
1061}
1062
1063void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1064{
1065 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001066 SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
1067 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001068 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1069 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1070 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1071 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1072}
1073void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1074{
1075 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001076 SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
1077 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001078 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1079 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1080 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1081 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1082}
1083
1084GLuint GL2Encoder::s_glCreateProgram(void * self)
1085{
1086 GL2Encoder *ctx = (GL2Encoder*)self;
1087 GLuint program = ctx->m_glCreateProgram_enc(self);
1088 if (program!=0)
1089 ctx->m_shared->addProgramData(program);
1090 return program;
1091}
1092
1093GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1094{
1095 GL2Encoder *ctx = (GL2Encoder*)self;
Tina Zhanga45cd9a2015-03-26 14:45:29 +08001096 RET_AND_SET_ERROR_IF(((shaderType != GL_VERTEX_SHADER) && (shaderType != GL_FRAGMENT_SHADER)),
1097 GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001098 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1099 if (shader != 0) {
1100 if (!ctx->m_shared->addShaderData(shader)) {
1101 ctx->m_glDeleteShader_enc(self, shader);
1102 return 0;
1103 }
1104 }
1105 return shader;
1106}
1107
bohu56bf82f2014-10-17 15:35:48 -07001108void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1109 GLsizei* count, GLuint* shaders)
1110{
1111 GL2Encoder *ctx = (GL2Encoder*)self;
1112 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1113 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1114}
1115
1116void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1117 GLsizei* length, GLchar* source)
1118{
1119 GL2Encoder *ctx = (GL2Encoder*)self;
1120 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1121 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
1122}
1123
1124void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1125 GLsizei* length, GLchar* infolog)
1126{
1127 GL2Encoder *ctx = (GL2Encoder*)self;
1128 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1129 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1130}
1131
1132void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1133 GLsizei* length, GLchar* infolog)
1134{
1135 GL2Encoder *ctx = (GL2Encoder*)self;
1136 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1137 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1138}
1139
keunyoungb85b2752013-03-08 12:28:03 -08001140void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1141{
1142 GL2Encoder *ctx = (GL2Encoder*)self;
1143 ctx->m_glDeleteShader_enc(self,shader);
1144 ctx->m_shared->unrefShaderData(shader);
1145}
1146
1147void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1148{
1149 GL2Encoder *ctx = (GL2Encoder*)self;
1150 ctx->m_glAttachShader_enc(self, program, shader);
1151 ctx->m_shared->attachShader(program, shader);
1152}
1153
1154void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1155{
1156 GL2Encoder *ctx = (GL2Encoder*)self;
1157 ctx->m_glDetachShader_enc(self, program, shader);
1158 ctx->m_shared->detachShader(program, shader);
1159}
1160
1161int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1162{
1163 if (!name) return -1;
1164
1165 GL2Encoder *ctx = (GL2Encoder*)self;
1166
1167 // if we need the uniform location WAR
1168 // parse array index from the end of the name string
1169 int arrIndex = 0;
1170 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1171 if (needLocationWAR) {
1172 int namelen = strlen(name);
1173 if (name[namelen-1] == ']') {
Yahan Zhou70fce1a2016-07-18 12:20:04 -07001174 const char *brace = strrchr(name,'[');
keunyoungb85b2752013-03-08 12:28:03 -08001175 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1176 return -1;
1177 }
1178
1179 }
1180 }
1181
1182 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1183 if (hostLoc >= 0 && needLocationWAR) {
1184 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1185 }
1186 return hostLoc;
1187}
1188
1189bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1190{
1191 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1192 return false;
1193
1194 m_state->setActiveTextureUnit(texUnit);
1195
1196 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1197 if (newTarget != oldTarget) {
1198 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1199 m_state->disableTextureTarget(GL_TEXTURE_2D);
1200 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1201 } else {
1202 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1203 m_state->enableTextureTarget(GL_TEXTURE_2D);
1204 }
1205 m_glActiveTexture_enc(this, texUnit);
1206 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1207 m_state->getBoundTexture(newTarget));
1208 return true;
1209 }
1210
1211 return false;
1212}
1213
1214void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1215{
1216 GL2Encoder *ctx = (GL2Encoder*)self;
1217 GLClientState* state = ctx->m_state;
1218 GLSharedGroupPtr shared = ctx->m_shared;
1219
Yahan Zhou431643a2016-08-04 16:14:20 -07001220 SET_ERROR_IF(program && !shared->isObject(program), GL_INVALID_VALUE);
1221 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1222
keunyoungb85b2752013-03-08 12:28:03 -08001223 ctx->m_glUseProgram_enc(self, program);
1224 ctx->m_state->setCurrentProgram(program);
1225
1226 GLenum origActiveTexture = state->getActiveTextureUnit();
1227 GLenum hostActiveTexture = origActiveTexture;
1228 GLint samplerIdx = -1;
1229 GLint samplerVal;
1230 GLenum samplerTarget;
1231 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1232 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1233 continue;
1234 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
1235 samplerTarget))
1236 {
1237 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1238 }
1239 }
1240 state->setActiveTextureUnit(origActiveTexture);
1241 if (hostActiveTexture != origActiveTexture) {
1242 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1243 }
1244}
1245
1246void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1247{
1248 GL2Encoder *ctx = (GL2Encoder*)self;
1249 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1250 ctx->m_glUniform1f_enc(self, hostLoc, x);
1251}
1252
1253void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1254{
1255 GL2Encoder *ctx = (GL2Encoder*)self;
1256 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1257 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1258}
1259
1260void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1261{
1262 GL2Encoder *ctx = (GL2Encoder*)self;
1263 GLClientState* state = ctx->m_state;
1264 GLSharedGroupPtr shared = ctx->m_shared;
1265
1266 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1267 ctx->m_glUniform1i_enc(self, hostLoc, x);
1268
1269 GLenum target;
1270 if (shared->setSamplerUniform(state->currentProgram(), location, x, &target)) {
1271 GLenum origActiveTexture = state->getActiveTextureUnit();
1272 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1273 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1274 }
1275 state->setActiveTextureUnit(origActiveTexture);
1276 }
1277}
1278
1279void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1280{
1281 GL2Encoder *ctx = (GL2Encoder*)self;
1282 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1283 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1284}
1285
1286void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1287{
1288 GL2Encoder *ctx = (GL2Encoder*)self;
1289 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1290 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1291}
1292
1293void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1294{
1295 GL2Encoder *ctx = (GL2Encoder*)self;
1296 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1297 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1298}
1299
1300void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1301{
1302 GL2Encoder *ctx = (GL2Encoder*)self;
1303 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1304 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1305}
1306
1307void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1308{
1309 GL2Encoder *ctx = (GL2Encoder*)self;
1310 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1311 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1312}
1313
1314void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1315{
1316 GL2Encoder *ctx = (GL2Encoder*)self;
1317 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1318 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1319}
1320
1321void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1322{
1323 GL2Encoder *ctx = (GL2Encoder*)self;
1324 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1325 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1326}
1327
1328void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1329{
1330 GL2Encoder *ctx = (GL2Encoder*)self;
1331 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1332 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1333}
1334
1335void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1336{
1337 GL2Encoder *ctx = (GL2Encoder*)self;
1338 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1339 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1340}
1341
1342void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1343{
1344 GL2Encoder *ctx = (GL2Encoder*)self;
1345 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1346 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1347}
1348
1349void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1350{
1351 GL2Encoder *ctx = (GL2Encoder*)self;
1352 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1353 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1354}
1355
1356void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1357{
1358 GL2Encoder *ctx = (GL2Encoder*)self;
1359 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1360 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1361}
1362
1363void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1364{
1365 GL2Encoder *ctx = (GL2Encoder*)self;
1366 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1367 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1368}
1369
1370void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1371{
1372 GL2Encoder *ctx = (GL2Encoder*)self;
1373 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1374 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1375}
1376
1377void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1378{
1379 GL2Encoder *ctx = (GL2Encoder*)self;
1380 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1381 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1382}
1383
1384void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1385{
1386 GL2Encoder *ctx = (GL2Encoder*)self;
1387 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1388 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1389}
1390
1391void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1392{
1393 GL2Encoder* ctx = (GL2Encoder*)self;
1394 GLClientState* state = ctx->m_state;
1395 GLenum err;
1396
1397 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1398
1399 ctx->m_glActiveTexture_enc(ctx, texture);
1400}
1401
1402void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1403{
1404 GL2Encoder* ctx = (GL2Encoder*)self;
1405 GLClientState* state = ctx->m_state;
1406 GLenum err;
1407 GLboolean firstUse;
1408
1409 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1410
1411 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1412 ctx->m_glBindTexture_enc(ctx, target, texture);
1413 return;
1414 }
1415
1416 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1417
1418 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1419 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1420 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1421 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1422 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1423 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1424 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1425 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1426
1427 if (target != priorityTarget) {
1428 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1429 state->getBoundTexture(GL_TEXTURE_2D));
1430 }
1431 }
1432
1433 if (target == priorityTarget) {
1434 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1435 }
1436}
1437
1438void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1439{
1440 GL2Encoder* ctx = (GL2Encoder*)self;
1441 GLClientState* state = ctx->m_state;
1442
1443 state->deleteTextures(n, textures);
1444 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1445}
1446
1447void GL2Encoder::s_glGetTexParameterfv(void* self,
1448 GLenum target, GLenum pname, GLfloat* params)
1449{
1450 GL2Encoder* ctx = (GL2Encoder*)self;
1451 const GLClientState* state = ctx->m_state;
1452
1453 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1454 ctx->override2DTextureTarget(target);
1455 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001456 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001457 } else {
1458 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1459 }
1460}
1461
1462void GL2Encoder::s_glGetTexParameteriv(void* self,
1463 GLenum target, GLenum pname, GLint* params)
1464{
1465 GL2Encoder* ctx = (GL2Encoder*)self;
1466 const GLClientState* state = ctx->m_state;
1467
1468 switch (pname) {
1469 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1470 *params = 1;
1471 break;
1472
1473 default:
1474 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1475 ctx->override2DTextureTarget(target);
1476 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001477 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001478 } else {
1479 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1480 }
1481 break;
1482 }
1483}
1484
1485static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1486{
1487 switch (pname) {
1488 case GL_TEXTURE_MIN_FILTER:
1489 case GL_TEXTURE_MAG_FILTER:
1490 return param == GL_NEAREST || param == GL_LINEAR;
1491
1492 case GL_TEXTURE_WRAP_S:
1493 case GL_TEXTURE_WRAP_T:
1494 return param == GL_CLAMP_TO_EDGE;
1495
1496 default:
1497 return true;
1498 }
1499}
1500
1501void GL2Encoder::s_glTexParameterf(void* self,
1502 GLenum target, GLenum pname, GLfloat param)
1503{
1504 GL2Encoder* ctx = (GL2Encoder*)self;
1505 const GLClientState* state = ctx->m_state;
1506
1507 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1508 !isValidTextureExternalParam(pname, (GLenum)param)),
1509 GL_INVALID_ENUM);
1510
1511 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1512 ctx->override2DTextureTarget(target);
1513 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001514 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001515 } else {
1516 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1517 }
1518}
1519
1520void GL2Encoder::s_glTexParameterfv(void* self,
1521 GLenum target, GLenum pname, const GLfloat* params)
1522{
1523 GL2Encoder* ctx = (GL2Encoder*)self;
1524 const GLClientState* state = ctx->m_state;
1525
1526 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1527 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1528 GL_INVALID_ENUM);
1529
1530 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1531 ctx->override2DTextureTarget(target);
1532 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001533 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001534 } else {
1535 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1536 }
1537}
1538
1539void GL2Encoder::s_glTexParameteri(void* self,
1540 GLenum target, GLenum pname, GLint param)
1541{
1542 GL2Encoder* ctx = (GL2Encoder*)self;
1543 const GLClientState* state = ctx->m_state;
1544
1545 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1546 !isValidTextureExternalParam(pname, (GLenum)param)),
1547 GL_INVALID_ENUM);
1548
1549 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1550 ctx->override2DTextureTarget(target);
1551 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001552 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001553 } else {
1554 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
1555 }
1556}
1557
bohu26a92982014-11-25 16:50:37 -08001558void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
1559 GLint internalformat, GLsizei width, GLsizei height, GLint border,
1560 GLenum format, GLenum type, const GLvoid* pixels)
1561{
1562 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07001563 GLClientState* state = ctx->m_state;
bohu26a92982014-11-25 16:50:37 -08001564 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1565 ctx->override2DTextureTarget(target);
Lingfeng Yang69066602016-04-12 09:29:11 -07001566 state->setBoundTextureInternalFormat(target, internalformat);
1567 state->setBoundTextureFormat(target, format);
1568 state->setBoundTextureType(target, type);
1569
bohu26a92982014-11-25 16:50:37 -08001570 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1571 height, border, format, type, pixels);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001572 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08001573 } else {
1574 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1575 height, border, format, type, pixels);
1576 }
1577}
1578
Yahan Zhou2a208292016-06-22 15:36:04 -07001579void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
1580 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
1581 GLenum type, const GLvoid* pixels)
1582{
1583 GL2Encoder* ctx = (GL2Encoder*)self;
1584
1585 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1586 ctx->override2DTextureTarget(target);
1587 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
1588 height, format, type, pixels);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001589 ctx->restore2DTextureTarget(target);
Yahan Zhou2a208292016-06-22 15:36:04 -07001590 } else {
1591 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
1592 height, format, type, pixels);
1593 }
1594}
bohu26a92982014-11-25 16:50:37 -08001595
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07001596void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
1597 GLenum internalformat, GLint x, GLint y,
1598 GLsizei width, GLsizei height, GLint border)
1599{
1600 GL2Encoder* ctx = (GL2Encoder*)self;
1601 GLClientState* state = ctx->m_state;
1602
1603 // This is needed to work around underlying OpenGL drivers
1604 // (such as those feeding some some AMD GPUs) that expect
1605 // positive components of cube maps to be defined _before_
1606 // the negative components (otherwise a segfault occurs).
1607 GLenum extraTarget =
1608 state->copyTexImageLuminanceCubeMapAMDWorkaround
1609 (target, level, internalformat);
1610
1611 if (extraTarget) {
1612 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
1613 x, y, width, height, border);
1614 }
1615
1616 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
1617 x, y, width, height, border);
1618}
1619
keunyoungb85b2752013-03-08 12:28:03 -08001620void GL2Encoder::s_glTexParameteriv(void* self,
1621 GLenum target, GLenum pname, const GLint* params)
1622{
1623 GL2Encoder* ctx = (GL2Encoder*)self;
1624 const GLClientState* state = ctx->m_state;
1625
1626 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1627 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1628 GL_INVALID_ENUM);
1629
1630 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1631 ctx->override2DTextureTarget(target);
1632 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001633 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001634 } else {
1635 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
1636 }
1637}
1638
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001639bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
1640 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
1641 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1642}
1643
keunyoungb85b2752013-03-08 12:28:03 -08001644void GL2Encoder::override2DTextureTarget(GLenum target)
1645{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001646 if (texture2DNeedsOverride(target)) {
1647 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1648 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08001649 }
1650}
1651
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001652void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08001653{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001654 if (texture2DNeedsOverride(target)) {
1655 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1656 m_state->getBoundTexture(
1657 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)));
1658 }
keunyoungb85b2752013-03-08 12:28:03 -08001659}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07001660
1661void GL2Encoder::s_glGenRenderbuffers(void* self,
1662 GLsizei n, GLuint* renderbuffers) {
1663 GL2Encoder* ctx = (GL2Encoder*)self;
1664 GLClientState* state = ctx->m_state;
1665
1666 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1667
1668 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
1669 state->addRenderbuffers(n, renderbuffers);
1670}
1671
1672void GL2Encoder::s_glDeleteRenderbuffers(void* self,
1673 GLsizei n, const GLuint* renderbuffers) {
1674 GL2Encoder* ctx = (GL2Encoder*)self;
1675 GLClientState* state = ctx->m_state;
1676
1677 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1678
1679 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
1680 state->removeRenderbuffers(n, renderbuffers);
1681}
1682
1683void GL2Encoder::s_glBindRenderbuffer(void* self,
1684 GLenum target, GLuint renderbuffer) {
1685 GL2Encoder* ctx = (GL2Encoder*)self;
1686 GLClientState* state = ctx->m_state;
1687
1688 SET_ERROR_IF((target != GL_RENDERBUFFER),
1689 GL_INVALID_ENUM);
1690
1691 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
1692 state->bindRenderbuffer(target, renderbuffer);
1693}
1694
Lingfeng Yang69066602016-04-12 09:29:11 -07001695void GL2Encoder::s_glRenderbufferStorage(void* self,
1696 GLenum target, GLenum internalformat,
1697 GLsizei width, GLsizei height) {
1698 GL2Encoder* ctx = (GL2Encoder*) self;
1699 GLClientState* state = ctx->m_state;
1700
1701 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
1702 switch (internalformat) {
1703 // Funny internal formats
1704 // that will cause an incomplete framebuffer
1705 // attachment error. For dEQP,
1706 // we can also just abort early here in
1707 // RenderbufferStorage with a GL_INVALID_ENUM.
1708 case GL_DEPTH_COMPONENT32F:
1709 case GL_R8:
1710 case GL_R8UI:
1711 case GL_R8I:
1712 case GL_R16UI:
1713 case GL_R16I:
1714 case GL_R32UI:
1715 case GL_R32I:
1716 case GL_RG8:
1717 case GL_RG8UI:
1718 case GL_RG8I:
1719 case GL_RG16UI:
1720 case GL_RG16I:
1721 case GL_RG32UI:
1722 case GL_RG32I:
1723 case GL_SRGB8_ALPHA8:
Lingfeng Yang69066602016-04-12 09:29:11 -07001724 case GL_RGBA8UI:
1725 case GL_RGBA8I:
1726 case GL_RGB10_A2UI:
1727 case GL_RGBA16UI:
1728 case GL_RGBA16I:
1729 case GL_RGBA32I:
1730 case GL_RGBA32UI:
1731 case GL_R11F_G11F_B10F:
1732 case GL_R32F:
1733 case GL_RG32F:
1734 case GL_RGB32F:
1735 case GL_RGBA32F:
1736 SET_ERROR_IF(true, GL_INVALID_ENUM);
1737 break;
1738 // These 4 formats are still not OK,
1739 // but dEQP expects GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT or
1740 // GL_FRAMEBUFFER_UNSUPPORTED,
1741 // not a GL_INVALID_ENUM from earlier on.
1742 // So let's forward these to the rest of
1743 // FBO initialization
1744 case GL_R16F:
1745 case GL_RG16F:
1746 case GL_RGB16F:
1747 case GL_RGBA16F:
Yahan Zhouafbb4f82016-05-11 10:45:31 -07001748 // dEQP expects GL_FRAMEBUFFER_UNSUPPORTED or GL_FRAMEBUFFER_COMPLETE
1749 // for this format
1750 case GL_RGB10_A2:
Lingfeng Yang69066602016-04-12 09:29:11 -07001751 // These formats are OK
1752 case GL_DEPTH_COMPONENT16:
1753 case GL_DEPTH_COMPONENT24:
1754 case GL_DEPTH_COMPONENT32_OES:
1755 case GL_RGBA4:
1756 case GL_RGB5_A1:
1757 case GL_RGB565:
1758 case GL_RGB8_OES:
1759 case GL_RGBA8_OES:
1760 case GL_STENCIL_INDEX8:
1761 case GL_DEPTH32F_STENCIL8:
1762 case GL_DEPTH24_STENCIL8_OES:
1763 break;
1764 // Everything else: still not OK,
1765 // and they need the GL_INVALID_ENUM
1766 default:
1767 SET_ERROR_IF(true, GL_INVALID_ENUM);
1768 }
1769
1770 state->setBoundRenderbufferFormat(internalformat);
1771 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
1772 width, height);
1773}
1774
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07001775void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
1776 GLenum target, GLenum attachment,
1777 GLenum renderbuffertarget, GLuint renderbuffer) {
1778 GL2Encoder* ctx = (GL2Encoder*)self;
1779 GLClientState* state = ctx->m_state;
1780
1781 state->attachRbo(attachment, renderbuffer);
1782
1783 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
1784}
1785
1786void GL2Encoder::s_glGenFramebuffers(void* self,
1787 GLsizei n, GLuint* framebuffers) {
1788 GL2Encoder* ctx = (GL2Encoder*)self;
1789 GLClientState* state = ctx->m_state;
1790
1791 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1792
1793 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
1794 state->addFramebuffers(n, framebuffers);
1795}
1796
1797void GL2Encoder::s_glDeleteFramebuffers(void* self,
1798 GLsizei n, const GLuint* framebuffers) {
1799 GL2Encoder* ctx = (GL2Encoder*)self;
1800 GLClientState* state = ctx->m_state;
1801
1802 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1803
1804 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
1805 state->removeFramebuffers(n, framebuffers);
1806}
1807
1808void GL2Encoder::s_glBindFramebuffer(void* self,
1809 GLenum target, GLuint framebuffer) {
1810 GL2Encoder* ctx = (GL2Encoder*)self;
1811 GLClientState* state = ctx->m_state;
1812
1813 SET_ERROR_IF((target != GL_FRAMEBUFFER),
1814 GL_INVALID_ENUM);
1815
1816 state->bindFramebuffer(target, framebuffer);
1817
1818 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
1819}
1820
1821void GL2Encoder::s_glFramebufferTexture2D(void* self,
1822 GLenum target, GLenum attachment,
1823 GLenum textarget, GLuint texture, GLint level) {
1824 GL2Encoder* ctx = (GL2Encoder*)self;
1825 GLClientState* state = ctx->m_state;
1826
1827 state->attachTextureObject(attachment, texture);
1828
1829 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
1830}
1831
1832void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
1833 GLenum target, GLenum attachment,
1834 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
1835 GL2Encoder* ctx = (GL2Encoder*)self;
1836 GLClientState* state = ctx->m_state;
1837
1838 state->attachTextureObject(attachment, texture);
1839
1840 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
1841}
1842
1843void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
1844 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
1845 GL2Encoder* ctx = (GL2Encoder*)self;
1846 const GLClientState* state = ctx->m_state;
1847
1848 SET_ERROR_IF(state->boundFramebuffer() == 0,
1849 GL_INVALID_OPERATION);
1850 SET_ERROR_IF((pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) &&
1851 (!state->attachmentHasObject(attachment)),
1852 GL_INVALID_ENUM);
1853
1854 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
1855}
Lingfeng Yang69066602016-04-12 09:29:11 -07001856
1857bool GL2Encoder::isCompleteFbo(const GLClientState* state,
1858 GLenum attachment) const {
1859 FboFormatInfo fbo_format_info;
1860 state->getBoundFramebufferFormat(attachment, &fbo_format_info);
1861
1862 bool res;
1863 switch (fbo_format_info.type) {
1864 case FBO_ATTACHMENT_RENDERBUFFER:
1865 switch (fbo_format_info.rb_format) {
1866 case GL_R16F:
1867 case GL_RG16F:
1868 case GL_RGB16F:
1869 case GL_RGBA16F:
1870 res = false;
1871 break;
1872 case GL_STENCIL_INDEX8:
1873 if (attachment == GL_STENCIL_ATTACHMENT) {
1874 res = true;
1875 } else {
1876 res = false;
1877 }
1878 break;
1879 default:
1880 res = true;
1881 }
1882 break;
1883 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001884 switch (fbo_format_info.tex_internalformat) {
1885 case GL_RED:
1886 case GL_RG:
1887 case GL_R16F:
1888 case GL_RG16F:
1889 case GL_RGBA16F:
1890 case GL_RGB16F:
1891 case GL_R11F_G11F_B10F:
1892 res = false;
1893 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07001894 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001895 case GL_RGB:
1896 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07001897 switch (fbo_format_info.tex_type) {
1898 case GL_FLOAT:
1899 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001900 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07001901 res = false;
1902 break;
1903 default:
1904 res = true;
1905 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001906 break;
1907 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07001908 res = true;
1909 }
1910 break;
1911 case FBO_ATTACHMENT_NONE:
1912 res = true;
1913 break;
1914 default:
1915 res = true;
1916 }
1917 return res;
1918}
1919
1920GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
1921 GL2Encoder* ctx = (GL2Encoder*)self;
1922 GLClientState* state = ctx->m_state;
1923
1924 bool complete = ctx->isCompleteFbo(state, GL_COLOR_ATTACHMENT0) &&
1925 ctx->isCompleteFbo(state, GL_DEPTH_ATTACHMENT) &&
1926 ctx->isCompleteFbo(state, GL_STENCIL_ATTACHMENT);
1927 if (!complete) {
1928 state->setCheckFramebufferStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
1929 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1930 } else {
1931 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
1932 state->setCheckFramebufferStatus(host_checkstatus);
1933 return host_checkstatus;
1934 }
1935}