blob: 78051d4f3f54d1219dc1cb7ec8ca4474eb85de1c [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
36#define SET_ERROR_IF(condition,err) if((condition)) { \
37 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
38 ctx->setError(err); \
39 return; \
40 }
41
42
43#define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) { \
44 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
45 ctx->setError(err); \
46 return ret; \
47 }
48
49
Yahan Zhoub7f09082016-03-10 11:45:02 -080050GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
51 : gl2_encoder_context_t(stream, protocol)
keunyoungb85b2752013-03-08 12:28:03 -080052{
53 m_initialized = false;
54 m_state = NULL;
55 m_error = GL_NO_ERROR;
56 m_num_compressedTextureFormats = 0;
Lizhe Liue41f4ef2015-05-27 11:13:23 +080057 m_max_cubeMapTextureSize = 0;
58 m_max_renderBufferSize = 0;
59 m_max_textureSize = 0;
keunyoungb85b2752013-03-08 12:28:03 -080060 m_compressedTextureFormats = NULL;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010061
Lingfeng Yangde51dfb2016-10-17 22:48:59 -070062 m_drawCallFlushCount = 0;
63 m_primitiveRestartEnabled = false;
64 m_primitiveRestartIndex = 0;
65
keunyoungb85b2752013-03-08 12:28:03 -080066 //overrides
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010067#define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name
bohu56bf82f2014-10-17 15:35:48 -070068
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010069 OVERRIDE(glFlush);
70 OVERRIDE(glPixelStorei);
71 OVERRIDE(glGetString);
72 OVERRIDE(glBindBuffer);
73 OVERRIDE(glBufferData);
74 OVERRIDE(glBufferSubData);
75 OVERRIDE(glDeleteBuffers);
76 OVERRIDE(glDrawArrays);
77 OVERRIDE(glDrawElements);
78 OVERRIDE(glGetIntegerv);
79 OVERRIDE(glGetFloatv);
80 OVERRIDE(glGetBooleanv);
81 OVERRIDE(glVertexAttribPointer);
82 OVERRIDE(glEnableVertexAttribArray);
83 OVERRIDE(glDisableVertexAttribArray);
84 OVERRIDE(glGetVertexAttribiv);
85 OVERRIDE(glGetVertexAttribfv);
86 OVERRIDE(glGetVertexAttribPointerv);
keunyoungb85b2752013-03-08 12:28:03 -080087
Bo Hu73568cd2015-01-20 16:29:50 -080088 this->glShaderBinary = &s_glShaderBinary;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010089 this->glShaderSource = &s_glShaderSource;
90 this->glFinish = &s_glFinish;
keunyoungb85b2752013-03-08 12:28:03 -080091
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010092 OVERRIDE(glGetError);
93 OVERRIDE(glLinkProgram);
94 OVERRIDE(glDeleteProgram);
95 OVERRIDE(glGetUniformiv);
96 OVERRIDE(glGetUniformfv);
97 OVERRIDE(glCreateProgram);
98 OVERRIDE(glCreateShader);
99 OVERRIDE(glDeleteShader);
100 OVERRIDE(glAttachShader);
101 OVERRIDE(glDetachShader);
102 OVERRIDE(glGetAttachedShaders);
103 OVERRIDE(glGetShaderSource);
104 OVERRIDE(glGetShaderInfoLog);
105 OVERRIDE(glGetProgramInfoLog);
106
107 OVERRIDE(glGetUniformLocation);
108 OVERRIDE(glUseProgram);
109
110 OVERRIDE(glUniform1f);
111 OVERRIDE(glUniform1fv);
112 OVERRIDE(glUniform1i);
113 OVERRIDE(glUniform1iv);
114 OVERRIDE(glUniform2f);
115 OVERRIDE(glUniform2fv);
116 OVERRIDE(glUniform2i);
117 OVERRIDE(glUniform2iv);
118 OVERRIDE(glUniform3f);
119 OVERRIDE(glUniform3fv);
120 OVERRIDE(glUniform3i);
121 OVERRIDE(glUniform3iv);
122 OVERRIDE(glUniform4f);
123 OVERRIDE(glUniform4fv);
124 OVERRIDE(glUniform4i);
125 OVERRIDE(glUniform4iv);
126 OVERRIDE(glUniformMatrix2fv);
127 OVERRIDE(glUniformMatrix3fv);
128 OVERRIDE(glUniformMatrix4fv);
129
130 OVERRIDE(glActiveTexture);
131 OVERRIDE(glBindTexture);
132 OVERRIDE(glDeleteTextures);
133 OVERRIDE(glGetTexParameterfv);
134 OVERRIDE(glGetTexParameteriv);
135 OVERRIDE(glTexParameterf);
136 OVERRIDE(glTexParameterfv);
137 OVERRIDE(glTexParameteri);
138 OVERRIDE(glTexParameteriv);
bohu26a92982014-11-25 16:50:37 -0800139 OVERRIDE(glTexImage2D);
Yahan Zhou2a208292016-06-22 15:36:04 -0700140 OVERRIDE(glTexSubImage2D);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -0700141 OVERRIDE(glCopyTexImage2D);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700142
143 OVERRIDE(glGenRenderbuffers);
144 OVERRIDE(glDeleteRenderbuffers);
145 OVERRIDE(glBindRenderbuffer);
Lingfeng Yang69066602016-04-12 09:29:11 -0700146 OVERRIDE(glRenderbufferStorage);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700147 OVERRIDE(glFramebufferRenderbuffer);
148
149 OVERRIDE(glGenFramebuffers);
150 OVERRIDE(glDeleteFramebuffers);
151 OVERRIDE(glBindFramebuffer);
152 OVERRIDE(glFramebufferTexture2D);
153 OVERRIDE(glFramebufferTexture3DOES);
154 OVERRIDE(glGetFramebufferAttachmentParameteriv);
Lingfeng Yang69066602016-04-12 09:29:11 -0700155
156 OVERRIDE(glCheckFramebufferStatus);
keunyoungb85b2752013-03-08 12:28:03 -0800157}
158
159GL2Encoder::~GL2Encoder()
160{
161 delete m_compressedTextureFormats;
162}
163
164GLenum GL2Encoder::s_glGetError(void * self)
165{
166 GL2Encoder *ctx = (GL2Encoder *)self;
167 GLenum err = ctx->getError();
168 if(err != GL_NO_ERROR) {
169 ctx->setError(GL_NO_ERROR);
170 return err;
171 }
172
173 return ctx->m_glGetError_enc(self);
Yahan Zhouae30fe82016-08-10 21:15:45 +0000174
keunyoungb85b2752013-03-08 12:28:03 -0800175}
176
177void GL2Encoder::s_glFlush(void *self)
178{
179 GL2Encoder *ctx = (GL2Encoder *) self;
180 ctx->m_glFlush_enc(self);
181 ctx->m_stream->flush();
182}
183
184const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
185{
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100186 (void)self;
187
keunyoungb85b2752013-03-08 12:28:03 -0800188 GLubyte *retval = (GLubyte *) "";
189 switch(name) {
190 case GL_VENDOR:
191 retval = gVendorString;
192 break;
193 case GL_RENDERER:
194 retval = gRendererString;
195 break;
196 case GL_VERSION:
197 retval = gVersionString;
198 break;
199 case GL_EXTENSIONS:
200 retval = gExtensionsString;
201 break;
202 }
203 return retval;
204}
205
206void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
207{
208 GL2Encoder *ctx = (GL2Encoder *)self;
209 ctx->m_glPixelStorei_enc(ctx, param, value);
210 assert(ctx->m_state != NULL);
211 ctx->m_state->setPixelStore(param, value);
212}
213
214
215void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
216{
217 GL2Encoder *ctx = (GL2Encoder *) self;
218 assert(ctx->m_state != NULL);
219 ctx->m_state->bindBuffer(target, id);
220 // TODO set error state if needed;
221 ctx->m_glBindBuffer_enc(self, target, id);
222}
223
224void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
225{
226 GL2Encoder *ctx = (GL2Encoder *) self;
bohub0f0cdf2014-11-06 18:08:07 -0800227 SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800228 GLuint bufferId = ctx->m_state->getBuffer(target);
229 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
230 SET_ERROR_IF(size<0, GL_INVALID_VALUE);
231
232 ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
233 ctx->m_glBufferData_enc(self, target, size, data, usage);
234}
235
236void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
237{
238 GL2Encoder *ctx = (GL2Encoder *) self;
bohub0f0cdf2014-11-06 18:08:07 -0800239 SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800240 GLuint bufferId = ctx->m_state->getBuffer(target);
241 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
242
243 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
244 SET_ERROR_IF(res, res);
245
246 ctx->m_glBufferSubData_enc(self, target, offset, size, data);
247}
248
249void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
250{
251 GL2Encoder *ctx = (GL2Encoder *) self;
252 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
253 for (int i=0; i<n; i++) {
254 ctx->m_shared->deleteBufferData(buffers[i]);
bohub0f0cdf2014-11-06 18:08:07 -0800255 ctx->m_state->unBindBuffer(buffers[i]);
keunyoungb85b2752013-03-08 12:28:03 -0800256 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
257 }
258}
259
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700260static bool isValidVertexAttribIndex(void *self, GLuint indx)
261{
262 GL2Encoder *ctx = (GL2Encoder *) self;
263 GLint maxIndex;
264 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
265 return indx < maxIndex;
266}
267
268static bool isValidVertexAttribType(GLenum type)
269{
270 bool retval = false;
271 switch (type) {
272 case GL_BYTE:
273 case GL_UNSIGNED_BYTE:
274 case GL_SHORT:
275 case GL_UNSIGNED_SHORT:
276 case GL_FIXED:
277 case GL_FLOAT:
278 // The following are technically only available if certain GLES2 extensions are.
279 // However, they are supported by desktop GL3, which is a reasonable requirement
280 // for the desktop GL version. Therefore, consider them valid.
281 case GL_INT:
282 case GL_UNSIGNED_INT:
283 case GL_HALF_FLOAT_OES:
284 retval = true;
285 break;
286 }
287 return retval;
288}
289
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100290void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
keunyoungb85b2752013-03-08 12:28:03 -0800291{
292 GL2Encoder *ctx = (GL2Encoder *)self;
293 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700294 SET_ERROR_IF(!isValidVertexAttribIndex(self, indx), GL_INVALID_VALUE);
295 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
296 SET_ERROR_IF(!isValidVertexAttribType(type), GL_INVALID_ENUM);
297 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800298 ctx->m_state->setState(indx, size, type, normalized, stride, ptr);
299}
300
301void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
302{
303 GL2Encoder *ctx = (GL2Encoder *) self;
304 assert(ctx->m_state != NULL);
305 GLClientState* state = ctx->m_state;
306
307 switch (param) {
308 case GL_NUM_SHADER_BINARY_FORMATS:
309 *ptr = 0;
310 break;
311 case GL_SHADER_BINARY_FORMATS:
312 // do nothing
313 break;
314
315 case GL_COMPRESSED_TEXTURE_FORMATS: {
316 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
317 if (ctx->m_num_compressedTextureFormats > 0 &&
318 compressedTextureFormats != NULL) {
319 memcpy(ptr, compressedTextureFormats,
320 ctx->m_num_compressedTextureFormats * sizeof(GLint));
321 }
322 break;
323 }
324
325 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
326 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
327 case GL_MAX_TEXTURE_IMAGE_UNITS:
328 ctx->m_glGetIntegerv_enc(self, param, ptr);
329 *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
330 break;
331
332 case GL_TEXTURE_BINDING_2D:
333 *ptr = state->getBoundTexture(GL_TEXTURE_2D);
334 break;
335 case GL_TEXTURE_BINDING_EXTERNAL_OES:
336 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
337 break;
338
Lingfeng Yangb0176982016-03-01 21:27:49 -0800339 case GL_MAX_VERTEX_ATTRIBS:
340 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
341 ctx->m_glGetIntegerv_enc(self, param, ptr);
342 ctx->m_state->setMaxVertexAttribs(*ptr);
Yahan Zhoua5c36842016-06-01 12:49:39 -0700343 }
344 break;
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800345 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
346 if (ctx->m_max_cubeMapTextureSize != 0) {
347 *ptr = ctx->m_max_cubeMapTextureSize;
348 } else {
349 ctx->m_glGetIntegerv_enc(self, param, ptr);
350 ctx->m_max_cubeMapTextureSize = *ptr;
351 }
352 break;
353 case GL_MAX_RENDERBUFFER_SIZE:
354 if (ctx->m_max_renderBufferSize != 0) {
355 *ptr = ctx->m_max_renderBufferSize;
356 } else {
357 ctx->m_glGetIntegerv_enc(self, param, ptr);
358 ctx->m_max_renderBufferSize = *ptr;
359 }
360 break;
361 case GL_MAX_TEXTURE_SIZE:
362 if (ctx->m_max_textureSize != 0) {
363 *ptr = ctx->m_max_textureSize;
364 } else {
365 ctx->m_glGetIntegerv_enc(self, param, ptr);
366 ctx->m_max_textureSize = *ptr;
Lingfeng Yangb0176982016-03-01 21:27:49 -0800367 }
368 break;
keunyoungb85b2752013-03-08 12:28:03 -0800369 default:
370 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
371 ctx->m_glGetIntegerv_enc(self, param, ptr);
372 }
373 break;
374 }
375}
376
377
378void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
379{
380 GL2Encoder *ctx = (GL2Encoder *)self;
381 assert(ctx->m_state != NULL);
382 GLClientState* state = ctx->m_state;
383
384 switch (param) {
385 case GL_NUM_SHADER_BINARY_FORMATS:
386 *ptr = 0;
387 break;
388 case GL_SHADER_BINARY_FORMATS:
389 // do nothing
390 break;
391
392 case GL_COMPRESSED_TEXTURE_FORMATS: {
393 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
394 if (ctx->m_num_compressedTextureFormats > 0 &&
395 compressedTextureFormats != NULL) {
396 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
397 ptr[i] = (GLfloat) compressedTextureFormats[i];
398 }
399 }
400 break;
401 }
402
403 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
404 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
405 case GL_MAX_TEXTURE_IMAGE_UNITS:
406 ctx->m_glGetFloatv_enc(self, param, ptr);
407 *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
408 break;
409
410 case GL_TEXTURE_BINDING_2D:
411 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
412 break;
413 case GL_TEXTURE_BINDING_EXTERNAL_OES:
414 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
415 break;
416
417 default:
418 if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
419 ctx->m_glGetFloatv_enc(self, param, ptr);
420 }
421 break;
422 }
423}
424
425
426void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
427{
428 GL2Encoder *ctx = (GL2Encoder *)self;
429 assert(ctx->m_state != NULL);
430 GLClientState* state = ctx->m_state;
431
432 switch (param) {
433 case GL_NUM_SHADER_BINARY_FORMATS:
434 *ptr = GL_FALSE;
435 break;
436 case GL_SHADER_BINARY_FORMATS:
437 // do nothing
438 break;
439
440 case GL_COMPRESSED_TEXTURE_FORMATS: {
441 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
442 if (ctx->m_num_compressedTextureFormats > 0 &&
443 compressedTextureFormats != NULL) {
444 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
445 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
446 }
447 }
448 break;
449 }
450
451 case GL_TEXTURE_BINDING_2D:
452 *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
453 break;
454 case GL_TEXTURE_BINDING_EXTERNAL_OES:
455 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
456 ? GL_TRUE : GL_FALSE;
457 break;
458
459 default:
460 if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
461 ctx->m_glGetBooleanv_enc(self, param, ptr);
462 }
bohu05101d22014-11-17 16:28:42 -0800463 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
keunyoungb85b2752013-03-08 12:28:03 -0800464 break;
465 }
466}
467
468
469void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
470{
471 GL2Encoder *ctx = (GL2Encoder *)self;
472 assert(ctx->m_state);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700473 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800474 ctx->m_state->enable(index, 1);
475}
476
477void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
478{
479 GL2Encoder *ctx = (GL2Encoder *)self;
480 assert(ctx->m_state);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700481 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800482 ctx->m_state->enable(index, 0);
483}
484
485
486void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
487{
488 GL2Encoder *ctx = (GL2Encoder *)self;
489 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700490 GLint maxIndex;
491 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
492 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800493
494 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
495 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
496 }
497}
498
499void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
500{
501 GL2Encoder *ctx = (GL2Encoder *)self;
502 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700503 GLint maxIndex;
504 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
505 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800506
507 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
508 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
509 }
510}
511
512void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
513{
514 GL2Encoder *ctx = (GL2Encoder *)self;
515 if (ctx->m_state == NULL) return;
Lingfeng Yang5e100432016-04-08 12:46:42 -0700516 GLint maxIndex;
517 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
518 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
519 SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100520 (void)pname;
521
keunyoungb85b2752013-03-08 12:28:03 -0800522 const GLClientState::VertexAttribState *va_state = ctx->m_state->getState(index);
523 if (va_state != NULL) {
524 *pointer = va_state->data;
525 }
526}
527
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700528void GL2Encoder::calcIndexRange(const void* indices,
529 GLenum type,
530 GLsizei count,
531 int* minIndex_out,
532 int* maxIndex_out) {
533 switch(type) {
534 case GL_BYTE:
535 case GL_UNSIGNED_BYTE:
536 GLUtils::minmaxExcept(
537 (unsigned char *)indices, count,
538 minIndex_out, maxIndex_out,
539 m_primitiveRestartEnabled, (unsigned char)m_primitiveRestartIndex);
540 break;
541 case GL_SHORT:
542 case GL_UNSIGNED_SHORT:
543 GLUtils::minmaxExcept(
544 (unsigned short *)indices, count,
545 minIndex_out, maxIndex_out,
546 m_primitiveRestartEnabled, (unsigned short)m_primitiveRestartIndex);
547 break;
548 case GL_INT:
549 case GL_UNSIGNED_INT:
550 GLUtils::minmaxExcept(
551 (unsigned int *)indices, count,
552 minIndex_out, maxIndex_out,
553 m_primitiveRestartEnabled, (unsigned int)m_primitiveRestartIndex);
554 break;
555 default:
556 ALOGE("unsupported index buffer type %d\n", type);
557 }
558}
559
560void* GL2Encoder::recenterIndices(const void* src,
561 GLenum type,
562 GLsizei count,
563 int minIndex) {
564
565 void* adjustedIndices = (void*)src;
566
567 if (minIndex != 0) {
568 adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count);
569 switch(type) {
570 case GL_BYTE:
571 case GL_UNSIGNED_BYTE:
572 GLUtils::shiftIndicesExcept(
573 (unsigned char *)src,
574 (unsigned char *)adjustedIndices,
575 count, -minIndex,
576 m_primitiveRestartEnabled,
577 (unsigned char)m_primitiveRestartIndex);
578 break;
579 case GL_SHORT:
580 case GL_UNSIGNED_SHORT:
581 GLUtils::shiftIndicesExcept(
582 (unsigned short *)src,
583 (unsigned short *)adjustedIndices,
584 count, -minIndex,
585 m_primitiveRestartEnabled,
586 (unsigned short)m_primitiveRestartIndex);
587 break;
588 case GL_INT:
589 case GL_UNSIGNED_INT:
590 GLUtils::shiftIndicesExcept(
591 (unsigned int *)src,
592 (unsigned int *)adjustedIndices,
593 count, -minIndex,
594 m_primitiveRestartEnabled,
595 (unsigned int)m_primitiveRestartIndex);
596 break;
597 default:
598 ALOGE("unsupported index buffer type %d\n", type);
599 }
600 }
601
602 return adjustedIndices;
603}
604
605void GL2Encoder::getBufferIndexRange(BufferData* buf,
606 const void* dataWithOffset,
607 GLenum type,
608 GLsizei count,
609 GLintptr offset,
610 int* minIndex_out,
611 int* maxIndex_out) {
612
613 if (buf->m_indexRangeCache.findRange(
614 type, (size_t)offset, count,
615 m_primitiveRestartEnabled,
616 minIndex_out,
617 maxIndex_out)) {
618 return;
619 }
620
621 calcIndexRange(dataWithOffset, type, count, minIndex_out, maxIndex_out);
622
623 buf->m_indexRangeCache.addRange(
624 type, (size_t)offset, count, m_primitiveRestartEnabled,
625 *minIndex_out, *maxIndex_out);
626}
keunyoungb85b2752013-03-08 12:28:03 -0800627
628void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count)
629{
630 assert(m_state);
631
Lingfeng Yang398162b2016-05-26 14:18:33 -0700632 GLuint lastBoundVbo = m_state->currentArrayVbo();
keunyoungb85b2752013-03-08 12:28:03 -0800633 for (int i = 0; i < m_state->nLocations(); i++) {
634 bool enableDirty;
635 const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty);
636
637 if (!state) {
638 continue;
639 }
640
641 if (!enableDirty && !state->enabled) {
642 continue;
643 }
644
keunyoungb85b2752013-03-08 12:28:03 -0800645 if (state->enabled) {
Lingfeng Yang398162b2016-05-26 14:18:33 -0700646 if (lastBoundVbo != state->bufferObject) {
647 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject);
648 lastBoundVbo = state->bufferObject;
649 }
keunyoungb85b2752013-03-08 12:28:03 -0800650
651 unsigned int datalen = state->elementSize * count;
652 int stride = state->stride == 0 ? state->elementSize : state->stride;
653 int firstIndex = stride * first;
654
655 if (state->bufferObject == 0) {
Yahan Zhou3f2f1b42016-12-01 13:49:44 -0800656 if (state->elementSize == 0) {
657 // The vertex attribute array is uninitialized. Abandon it.
658 ALOGE("a vertex attribute array is uninitialized. Skipping corresponding vertex attribute.");
659 this->m_glDisableVertexAttribArray_enc(this, i);
660 continue;
661 }
Yahan Zhou5507c042016-06-01 17:24:28 -0700662 m_glEnableVertexAttribArray_enc(this, i);
keunyoungb85b2752013-03-08 12:28:03 -0800663 this->glVertexAttribPointerData(this, i, state->size, state->type, state->normalized, state->stride,
664 (unsigned char *)state->data + firstIndex, datalen);
665 } else {
Yahan Zhou5507c042016-06-01 17:24:28 -0700666 const BufferData* buf = m_shared->getBufferData(state->bufferObject);
667 // The following expression actually means bufLen = stride*count;
668 // But the last element doesn't have to fill up the whole stride.
669 // So it becomes the current form.
670 unsigned int bufLen = stride * (count - 1) + state->elementSize;
671 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
672 m_glEnableVertexAttribArray_enc(this, i);
673 this->glVertexAttribPointerOffset(this, i, state->size, state->type, state->normalized, state->stride,
Tina Zhang163119f2014-03-21 08:14:41 +0800674 (uintptr_t) state->data + firstIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -0700675 } else {
676 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute.");
677 m_glDisableVertexAttribArray_enc(this, i);
678 }
keunyoungb85b2752013-03-08 12:28:03 -0800679 }
680 } else {
681 this->m_glDisableVertexAttribArray_enc(this, i);
682 }
683 }
Lingfeng Yang398162b2016-05-26 14:18:33 -0700684
685 if (lastBoundVbo != m_state->currentArrayVbo()) {
686 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
687 }
keunyoungb85b2752013-03-08 12:28:03 -0800688}
689
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700690void GL2Encoder::flushDrawCall() {
691 // The idea is that
692 // commitBuffer / write() to qemu pipe will
693 // take at least ~20-60us, and for cases like
694 // sendVertexAttributes / glDrawElementsOffset,
695 // which sends only around few hundred bytes,
696 // we can get away with sending
697 // two at a time in the same ~20-60us,
698 // reducing average latency and gaining ~1 fps
699 // in Antutu on Linux + Quadro K2200.
700 if (m_drawCallFlushCount % 2 == 0) {
701 m_stream->flush();
702 }
703 m_drawCallFlushCount++;
704}
705
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700706static bool isValidDrawMode(GLenum mode)
707{
708 bool retval = false;
709 switch (mode) {
710 case GL_POINTS:
711 case GL_LINE_STRIP:
712 case GL_LINE_LOOP:
713 case GL_LINES:
714 case GL_TRIANGLE_STRIP:
715 case GL_TRIANGLE_FAN:
716 case GL_TRIANGLES:
717 retval = true;
718 }
719 return retval;
720}
721
keunyoungb85b2752013-03-08 12:28:03 -0800722void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
723{
724 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700725 assert(ctx->m_state != NULL);
726 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
727 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhoud6217a52016-02-10 16:10:46 -0800728
keunyoungb85b2752013-03-08 12:28:03 -0800729 ctx->sendVertexAttributes(first, count);
730 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
Yahan Zhoue57bd752016-06-06 12:30:39 -0700731 ctx->m_stream->flush();
keunyoungb85b2752013-03-08 12:28:03 -0800732}
733
734
735void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
736{
737
738 GL2Encoder *ctx = (GL2Encoder *)self;
739 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700740 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
741 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -0700742 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800743
744 bool has_immediate_arrays = false;
745 bool has_indirect_arrays = false;
746 int nLocations = ctx->m_state->nLocations();
Yahan Zhou5507c042016-06-01 17:24:28 -0700747 GLintptr offset = 0;
keunyoungb85b2752013-03-08 12:28:03 -0800748
749 for (int i = 0; i < nLocations; i++) {
750 const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
751 if (state->enabled) {
752 if (state->bufferObject != 0) {
753 has_indirect_arrays = true;
Yahan Zhoud6217a52016-02-10 16:10:46 -0800754 } else if (state->data) {
keunyoungb85b2752013-03-08 12:28:03 -0800755 has_immediate_arrays = true;
756 }
757 }
758 }
759
760 if (!has_immediate_arrays && !has_indirect_arrays) {
Yahan Zhou3f2f1b42016-12-01 13:49:44 -0800761 ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -0700762 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
763 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800764 }
765
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700766 BufferData* buf = NULL;
Yahan Zhou5507c042016-06-01 17:24:28 -0700767 int minIndex = 0, maxIndex = 0;
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700768
769 // For validation/immediate index array purposes,
770 // we need the min/max vertex index of the index array.
771 // If the VBO != 0, this may not be the first time we have
772 // used this particular index buffer. getBufferIndexRange
773 // can more quickly get min/max vertex index by
774 // cachine previous results.
775 if (ctx->m_state->currentIndexVbo() != 0) {
776 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
777 offset = (GLintptr)indices;
778 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
779 ctx->getBufferIndexRange(buf,
780 indices,
781 type,
782 (GLsizei)count,
783 (GLintptr)indices, // offset, really
784 &minIndex, &maxIndex);
785 } else {
786 // In this case, the |indices| field holds a real
787 // array, so calculate the indices now. They will
788 // also be needed to know how much data to
789 // transfer to host.
790 ctx->calcIndexRange(indices,
791 type,
792 count,
793 &minIndex,
794 &maxIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -0700795 }
796
keunyoungb85b2752013-03-08 12:28:03 -0800797 bool adjustIndices = true;
798 if (ctx->m_state->currentIndexVbo() != 0) {
799 if (!has_immediate_arrays) {
Yahan Zhou5507c042016-06-01 17:24:28 -0700800 ctx->sendVertexAttributes(0, maxIndex + 1);
keunyoungb85b2752013-03-08 12:28:03 -0800801 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -0700802 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700803 ctx->flushDrawCall();
keunyoungb85b2752013-03-08 12:28:03 -0800804 adjustIndices = false;
805 } else {
806 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
807 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -0800808 }
809 }
810 if (adjustIndices) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700811 void *adjustedIndices =
812 ctx->recenterIndices(indices,
813 type,
814 count,
815 minIndex);
keunyoungb85b2752013-03-08 12:28:03 -0800816
keunyoungb85b2752013-03-08 12:28:03 -0800817 if (has_indirect_arrays || 1) {
818 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1);
819 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
820 count * glSizeof(type));
Yahan Zhoue57bd752016-06-06 12:30:39 -0700821 ctx->m_stream->flush();
keunyoungb85b2752013-03-08 12:28:03 -0800822 // XXX - OPTIMIZATION (see the other else branch) should be implemented
823 if(!has_indirect_arrays) {
824 //ALOGD("unoptimized drawelements !!!\n");
825 }
826 } else {
827 // we are all direct arrays and immidate mode index array -
828 // rebuild the arrays and the index array;
829 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
830 }
831 }
832}
833
834
835GLint * GL2Encoder::getCompressedTextureFormats()
836{
837 if (m_compressedTextureFormats == NULL) {
838 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
839 &m_num_compressedTextureFormats);
840 if (m_num_compressedTextureFormats > 0) {
841 // get number of texture formats;
842 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
843 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
844 }
845 }
846 return m_compressedTextureFormats;
847}
848
849// Replace uses of samplerExternalOES with sampler2D, recording the names of
850// modified shaders in data. Also remove
851// #extension GL_OES_EGL_image_external : require
852// statements.
853//
854// This implementation assumes the input has already been pre-processed. If not,
855// a few cases will be mishandled:
856//
857// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
858// the following code:
859// #if 1
860// uniform sampler2D mySampler;
861// #else
862// uniform samplerExternalOES mySampler;
863// #endif
864//
865// 2. Comments that look like sampler declarations will be incorrectly modified
866// and recorded:
867// // samplerExternalOES hahaFooledYou
868//
869// 3. However, GLSL ES does not have a concatentation operator, so things like
870// this (valid in C) are invalid and not a problem:
871// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
872// SAMPLER(ExternalOES, mySampler);
873//
874static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
875{
876 static const char STR_HASH_EXTENSION[] = "#extension";
877 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
878 static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
879 static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
880
881 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
882 char* c = str;
883 while ((c = strstr(c, STR_HASH_EXTENSION))) {
884 char* start = c;
885 c += sizeof(STR_HASH_EXTENSION)-1;
886 while (isspace(*c) && *c != '\0') {
887 c++;
888 }
889 if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
890 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
891 {
892 // #extension statements are terminated by end of line
893 c = start;
894 while (*c != '\0' && *c != '\r' && *c != '\n') {
895 *c++ = ' ';
896 }
897 }
898 }
899
900 // -- replace "samplerExternalOES" with "sampler2D" and record name
901 c = str;
902 while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
903 // Make sure "samplerExternalOES" isn't a substring of a larger token
904 if (c == str || !isspace(*(c-1))) {
905 c++;
906 continue;
907 }
908 char* sampler_start = c;
909 c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
910 if (!isspace(*c) && *c != '\0') {
911 continue;
912 }
913
914 // capture sampler name
915 while (isspace(*c) && *c != '\0') {
916 c++;
917 }
918 if (!isalpha(*c) && *c != '_') {
919 // not an identifier
920 return false;
921 }
922 char* name_start = c;
923 do {
924 c++;
925 } while (isalnum(*c) || *c == '_');
926 data->samplerExternalNames.push_back(
927 android::String8(name_start, c - name_start));
928
929 // memcpy instead of strcpy since we don't want the NUL terminator
930 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
931 }
932
933 return true;
934}
935
Bo Hu73568cd2015-01-20 16:29:50 -0800936void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
937{
938 GL2Encoder* ctx = (GL2Encoder*)self;
939 // Although it is not supported, need to set proper error code.
940 SET_ERROR_IF(1, GL_INVALID_ENUM);
941}
942
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100943void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -0800944{
945 GL2Encoder* ctx = (GL2Encoder*)self;
946 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Tina Zhang7a84f652014-12-04 12:37:30 +0800947 SET_ERROR_IF(!ctx->m_shared->isObject(shader), GL_INVALID_VALUE);
948 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
949 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800950
951 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
952 char *str = new char[len + 1];
953 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
954
955 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
956 // Perhaps we can borrow Mesa's pre-processor?
957
958 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -0700959 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -0800960 ctx->setError(GL_OUT_OF_MEMORY);
961 return;
962 }
963
964 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -0700965 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -0800966}
967
968void GL2Encoder::s_glFinish(void *self)
969{
970 GL2Encoder *ctx = (GL2Encoder *)self;
971 ctx->glFinishRoundTrip(self);
972}
973
974void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
975{
976 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -0800977 bool isProgram = ctx->m_shared->isProgram(program);
978 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
979 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
980
keunyoungb85b2752013-03-08 12:28:03 -0800981 ctx->m_glLinkProgram_enc(self, program);
982
983 GLint linkStatus = 0;
984 ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
985 if (!linkStatus)
986 return;
987
988 //get number of active uniforms in the program
989 GLint numUniforms=0;
990 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
991 ctx->m_shared->initProgramData(program,numUniforms);
992
993 //get the length of the longest uniform name
994 GLint maxLength=0;
995 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
996
997 GLint size;
998 GLenum type;
999 GLchar *name = new GLchar[maxLength+1];
1000 GLint location;
1001 //for each active uniform, get its size and starting location.
1002 for (GLint i=0 ; i<numUniforms ; ++i)
1003 {
1004 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1005 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1006 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1007 }
1008 ctx->m_shared->setupLocationShiftWAR(program);
1009
1010 delete[] name;
1011}
1012
1013void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1014{
1015 GL2Encoder *ctx = (GL2Encoder*)self;
1016 ctx->m_glDeleteProgram_enc(self, program);
1017
1018 ctx->m_shared->deleteProgramData(program);
1019}
1020
1021void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1022{
1023 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001024 SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
1025 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001026 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1027 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1028 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1029 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1030}
1031void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1032{
1033 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001034 SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
1035 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001036 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1037 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1038 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1039 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1040}
1041
1042GLuint GL2Encoder::s_glCreateProgram(void * self)
1043{
1044 GL2Encoder *ctx = (GL2Encoder*)self;
1045 GLuint program = ctx->m_glCreateProgram_enc(self);
1046 if (program!=0)
1047 ctx->m_shared->addProgramData(program);
1048 return program;
1049}
1050
1051GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1052{
1053 GL2Encoder *ctx = (GL2Encoder*)self;
Tina Zhanga45cd9a2015-03-26 14:45:29 +08001054 RET_AND_SET_ERROR_IF(((shaderType != GL_VERTEX_SHADER) && (shaderType != GL_FRAGMENT_SHADER)),
1055 GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001056 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1057 if (shader != 0) {
1058 if (!ctx->m_shared->addShaderData(shader)) {
1059 ctx->m_glDeleteShader_enc(self, shader);
1060 return 0;
1061 }
1062 }
1063 return shader;
1064}
1065
bohu56bf82f2014-10-17 15:35:48 -07001066void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1067 GLsizei* count, GLuint* shaders)
1068{
1069 GL2Encoder *ctx = (GL2Encoder*)self;
1070 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1071 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1072}
1073
1074void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1075 GLsizei* length, GLchar* source)
1076{
1077 GL2Encoder *ctx = (GL2Encoder*)self;
1078 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1079 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
1080}
1081
1082void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1083 GLsizei* length, GLchar* infolog)
1084{
1085 GL2Encoder *ctx = (GL2Encoder*)self;
1086 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1087 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1088}
1089
1090void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1091 GLsizei* length, GLchar* infolog)
1092{
1093 GL2Encoder *ctx = (GL2Encoder*)self;
1094 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1095 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1096}
1097
keunyoungb85b2752013-03-08 12:28:03 -08001098void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1099{
1100 GL2Encoder *ctx = (GL2Encoder*)self;
1101 ctx->m_glDeleteShader_enc(self,shader);
1102 ctx->m_shared->unrefShaderData(shader);
1103}
1104
1105void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1106{
1107 GL2Encoder *ctx = (GL2Encoder*)self;
1108 ctx->m_glAttachShader_enc(self, program, shader);
1109 ctx->m_shared->attachShader(program, shader);
1110}
1111
1112void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1113{
1114 GL2Encoder *ctx = (GL2Encoder*)self;
1115 ctx->m_glDetachShader_enc(self, program, shader);
1116 ctx->m_shared->detachShader(program, shader);
1117}
1118
1119int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1120{
1121 if (!name) return -1;
1122
1123 GL2Encoder *ctx = (GL2Encoder*)self;
1124
1125 // if we need the uniform location WAR
1126 // parse array index from the end of the name string
1127 int arrIndex = 0;
1128 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1129 if (needLocationWAR) {
1130 int namelen = strlen(name);
1131 if (name[namelen-1] == ']') {
Yahan Zhou70fce1a2016-07-18 12:20:04 -07001132 const char *brace = strrchr(name,'[');
keunyoungb85b2752013-03-08 12:28:03 -08001133 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1134 return -1;
1135 }
1136
1137 }
1138 }
1139
1140 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1141 if (hostLoc >= 0 && needLocationWAR) {
1142 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1143 }
1144 return hostLoc;
1145}
1146
1147bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1148{
1149 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1150 return false;
1151
1152 m_state->setActiveTextureUnit(texUnit);
1153
1154 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1155 if (newTarget != oldTarget) {
1156 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1157 m_state->disableTextureTarget(GL_TEXTURE_2D);
1158 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1159 } else {
1160 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1161 m_state->enableTextureTarget(GL_TEXTURE_2D);
1162 }
1163 m_glActiveTexture_enc(this, texUnit);
1164 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1165 m_state->getBoundTexture(newTarget));
1166 return true;
1167 }
1168
1169 return false;
1170}
1171
1172void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1173{
1174 GL2Encoder *ctx = (GL2Encoder*)self;
1175 GLClientState* state = ctx->m_state;
1176 GLSharedGroupPtr shared = ctx->m_shared;
1177
Yahan Zhou431643a2016-08-04 16:14:20 -07001178 SET_ERROR_IF(program && !shared->isObject(program), GL_INVALID_VALUE);
1179 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1180
keunyoungb85b2752013-03-08 12:28:03 -08001181 ctx->m_glUseProgram_enc(self, program);
1182 ctx->m_state->setCurrentProgram(program);
1183
1184 GLenum origActiveTexture = state->getActiveTextureUnit();
1185 GLenum hostActiveTexture = origActiveTexture;
1186 GLint samplerIdx = -1;
1187 GLint samplerVal;
1188 GLenum samplerTarget;
1189 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1190 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1191 continue;
1192 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
1193 samplerTarget))
1194 {
1195 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1196 }
1197 }
1198 state->setActiveTextureUnit(origActiveTexture);
1199 if (hostActiveTexture != origActiveTexture) {
1200 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1201 }
1202}
1203
1204void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1205{
1206 GL2Encoder *ctx = (GL2Encoder*)self;
1207 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1208 ctx->m_glUniform1f_enc(self, hostLoc, x);
1209}
1210
1211void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1212{
1213 GL2Encoder *ctx = (GL2Encoder*)self;
1214 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1215 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1216}
1217
1218void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1219{
1220 GL2Encoder *ctx = (GL2Encoder*)self;
1221 GLClientState* state = ctx->m_state;
1222 GLSharedGroupPtr shared = ctx->m_shared;
1223
1224 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1225 ctx->m_glUniform1i_enc(self, hostLoc, x);
1226
1227 GLenum target;
1228 if (shared->setSamplerUniform(state->currentProgram(), location, x, &target)) {
1229 GLenum origActiveTexture = state->getActiveTextureUnit();
1230 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1231 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1232 }
1233 state->setActiveTextureUnit(origActiveTexture);
1234 }
1235}
1236
1237void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1238{
1239 GL2Encoder *ctx = (GL2Encoder*)self;
1240 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1241 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1242}
1243
1244void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1245{
1246 GL2Encoder *ctx = (GL2Encoder*)self;
1247 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1248 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1249}
1250
1251void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1252{
1253 GL2Encoder *ctx = (GL2Encoder*)self;
1254 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1255 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1256}
1257
1258void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1259{
1260 GL2Encoder *ctx = (GL2Encoder*)self;
1261 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1262 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1263}
1264
1265void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1266{
1267 GL2Encoder *ctx = (GL2Encoder*)self;
1268 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1269 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1270}
1271
1272void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1273{
1274 GL2Encoder *ctx = (GL2Encoder*)self;
1275 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1276 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1277}
1278
1279void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1280{
1281 GL2Encoder *ctx = (GL2Encoder*)self;
1282 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1283 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1284}
1285
1286void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1287{
1288 GL2Encoder *ctx = (GL2Encoder*)self;
1289 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1290 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1291}
1292
1293void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1294{
1295 GL2Encoder *ctx = (GL2Encoder*)self;
1296 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1297 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1298}
1299
1300void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1301{
1302 GL2Encoder *ctx = (GL2Encoder*)self;
1303 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1304 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1305}
1306
1307void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1308{
1309 GL2Encoder *ctx = (GL2Encoder*)self;
1310 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1311 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1312}
1313
1314void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1315{
1316 GL2Encoder *ctx = (GL2Encoder*)self;
1317 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1318 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1319}
1320
1321void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1322{
1323 GL2Encoder *ctx = (GL2Encoder*)self;
1324 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1325 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1326}
1327
1328void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1329{
1330 GL2Encoder *ctx = (GL2Encoder*)self;
1331 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1332 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1333}
1334
1335void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1336{
1337 GL2Encoder *ctx = (GL2Encoder*)self;
1338 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1339 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1340}
1341
1342void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1343{
1344 GL2Encoder *ctx = (GL2Encoder*)self;
1345 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1346 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1347}
1348
1349void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1350{
1351 GL2Encoder* ctx = (GL2Encoder*)self;
1352 GLClientState* state = ctx->m_state;
1353 GLenum err;
1354
1355 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1356
1357 ctx->m_glActiveTexture_enc(ctx, texture);
1358}
1359
1360void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1361{
1362 GL2Encoder* ctx = (GL2Encoder*)self;
1363 GLClientState* state = ctx->m_state;
1364 GLenum err;
1365 GLboolean firstUse;
1366
1367 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1368
1369 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1370 ctx->m_glBindTexture_enc(ctx, target, texture);
1371 return;
1372 }
1373
1374 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1375
1376 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1377 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1378 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1379 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1380 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1381 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1382 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1383 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1384
1385 if (target != priorityTarget) {
1386 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1387 state->getBoundTexture(GL_TEXTURE_2D));
1388 }
1389 }
1390
1391 if (target == priorityTarget) {
1392 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1393 }
1394}
1395
1396void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1397{
1398 GL2Encoder* ctx = (GL2Encoder*)self;
1399 GLClientState* state = ctx->m_state;
1400
1401 state->deleteTextures(n, textures);
1402 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1403}
1404
1405void GL2Encoder::s_glGetTexParameterfv(void* self,
1406 GLenum target, GLenum pname, GLfloat* params)
1407{
1408 GL2Encoder* ctx = (GL2Encoder*)self;
1409 const GLClientState* state = ctx->m_state;
1410
1411 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1412 ctx->override2DTextureTarget(target);
1413 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001414 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001415 } else {
1416 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1417 }
1418}
1419
1420void GL2Encoder::s_glGetTexParameteriv(void* self,
1421 GLenum target, GLenum pname, GLint* params)
1422{
1423 GL2Encoder* ctx = (GL2Encoder*)self;
1424 const GLClientState* state = ctx->m_state;
1425
1426 switch (pname) {
1427 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1428 *params = 1;
1429 break;
1430
1431 default:
1432 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1433 ctx->override2DTextureTarget(target);
1434 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001435 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001436 } else {
1437 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1438 }
1439 break;
1440 }
1441}
1442
1443static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1444{
1445 switch (pname) {
1446 case GL_TEXTURE_MIN_FILTER:
1447 case GL_TEXTURE_MAG_FILTER:
1448 return param == GL_NEAREST || param == GL_LINEAR;
1449
1450 case GL_TEXTURE_WRAP_S:
1451 case GL_TEXTURE_WRAP_T:
1452 return param == GL_CLAMP_TO_EDGE;
1453
1454 default:
1455 return true;
1456 }
1457}
1458
1459void GL2Encoder::s_glTexParameterf(void* self,
1460 GLenum target, GLenum pname, GLfloat param)
1461{
1462 GL2Encoder* ctx = (GL2Encoder*)self;
1463 const GLClientState* state = ctx->m_state;
1464
1465 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1466 !isValidTextureExternalParam(pname, (GLenum)param)),
1467 GL_INVALID_ENUM);
1468
1469 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1470 ctx->override2DTextureTarget(target);
1471 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001472 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001473 } else {
1474 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1475 }
1476}
1477
1478void GL2Encoder::s_glTexParameterfv(void* self,
1479 GLenum target, GLenum pname, const GLfloat* params)
1480{
1481 GL2Encoder* ctx = (GL2Encoder*)self;
1482 const GLClientState* state = ctx->m_state;
1483
1484 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1485 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1486 GL_INVALID_ENUM);
1487
1488 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1489 ctx->override2DTextureTarget(target);
1490 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001491 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001492 } else {
1493 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1494 }
1495}
1496
1497void GL2Encoder::s_glTexParameteri(void* self,
1498 GLenum target, GLenum pname, GLint param)
1499{
1500 GL2Encoder* ctx = (GL2Encoder*)self;
1501 const GLClientState* state = ctx->m_state;
1502
1503 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1504 !isValidTextureExternalParam(pname, (GLenum)param)),
1505 GL_INVALID_ENUM);
1506
1507 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1508 ctx->override2DTextureTarget(target);
1509 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001510 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001511 } else {
1512 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
1513 }
1514}
1515
bohu26a92982014-11-25 16:50:37 -08001516void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
1517 GLint internalformat, GLsizei width, GLsizei height, GLint border,
1518 GLenum format, GLenum type, const GLvoid* pixels)
1519{
1520 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07001521 GLClientState* state = ctx->m_state;
bohu26a92982014-11-25 16:50:37 -08001522 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1523 ctx->override2DTextureTarget(target);
Lingfeng Yang69066602016-04-12 09:29:11 -07001524 state->setBoundTextureInternalFormat(target, internalformat);
1525 state->setBoundTextureFormat(target, format);
1526 state->setBoundTextureType(target, type);
1527
bohu26a92982014-11-25 16:50:37 -08001528 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1529 height, border, format, type, pixels);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001530 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08001531 } else {
1532 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1533 height, border, format, type, pixels);
1534 }
1535}
1536
Yahan Zhou2a208292016-06-22 15:36:04 -07001537void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
1538 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
1539 GLenum type, const GLvoid* pixels)
1540{
1541 GL2Encoder* ctx = (GL2Encoder*)self;
1542
1543 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1544 ctx->override2DTextureTarget(target);
1545 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
1546 height, format, type, pixels);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001547 ctx->restore2DTextureTarget(target);
Yahan Zhou2a208292016-06-22 15:36:04 -07001548 } else {
1549 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
1550 height, format, type, pixels);
1551 }
1552}
bohu26a92982014-11-25 16:50:37 -08001553
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07001554void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
1555 GLenum internalformat, GLint x, GLint y,
1556 GLsizei width, GLsizei height, GLint border)
1557{
1558 GL2Encoder* ctx = (GL2Encoder*)self;
1559 GLClientState* state = ctx->m_state;
1560
1561 // This is needed to work around underlying OpenGL drivers
1562 // (such as those feeding some some AMD GPUs) that expect
1563 // positive components of cube maps to be defined _before_
1564 // the negative components (otherwise a segfault occurs).
1565 GLenum extraTarget =
1566 state->copyTexImageLuminanceCubeMapAMDWorkaround
1567 (target, level, internalformat);
1568
1569 if (extraTarget) {
1570 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
1571 x, y, width, height, border);
1572 }
1573
1574 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
1575 x, y, width, height, border);
1576}
1577
keunyoungb85b2752013-03-08 12:28:03 -08001578void GL2Encoder::s_glTexParameteriv(void* self,
1579 GLenum target, GLenum pname, const GLint* params)
1580{
1581 GL2Encoder* ctx = (GL2Encoder*)self;
1582 const GLClientState* state = ctx->m_state;
1583
1584 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1585 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1586 GL_INVALID_ENUM);
1587
1588 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1589 ctx->override2DTextureTarget(target);
1590 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001591 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001592 } else {
1593 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
1594 }
1595}
1596
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001597bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
1598 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
1599 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1600}
1601
keunyoungb85b2752013-03-08 12:28:03 -08001602void GL2Encoder::override2DTextureTarget(GLenum target)
1603{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001604 if (texture2DNeedsOverride(target)) {
1605 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1606 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08001607 }
1608}
1609
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001610void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08001611{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001612 if (texture2DNeedsOverride(target)) {
1613 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1614 m_state->getBoundTexture(
1615 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)));
1616 }
keunyoungb85b2752013-03-08 12:28:03 -08001617}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07001618
1619void GL2Encoder::s_glGenRenderbuffers(void* self,
1620 GLsizei n, GLuint* renderbuffers) {
1621 GL2Encoder* ctx = (GL2Encoder*)self;
1622 GLClientState* state = ctx->m_state;
1623
1624 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1625
1626 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
1627 state->addRenderbuffers(n, renderbuffers);
1628}
1629
1630void GL2Encoder::s_glDeleteRenderbuffers(void* self,
1631 GLsizei n, const GLuint* renderbuffers) {
1632 GL2Encoder* ctx = (GL2Encoder*)self;
1633 GLClientState* state = ctx->m_state;
1634
1635 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1636
1637 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
1638 state->removeRenderbuffers(n, renderbuffers);
1639}
1640
1641void GL2Encoder::s_glBindRenderbuffer(void* self,
1642 GLenum target, GLuint renderbuffer) {
1643 GL2Encoder* ctx = (GL2Encoder*)self;
1644 GLClientState* state = ctx->m_state;
1645
1646 SET_ERROR_IF((target != GL_RENDERBUFFER),
1647 GL_INVALID_ENUM);
1648
1649 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
1650 state->bindRenderbuffer(target, renderbuffer);
1651}
1652
Lingfeng Yang69066602016-04-12 09:29:11 -07001653void GL2Encoder::s_glRenderbufferStorage(void* self,
1654 GLenum target, GLenum internalformat,
1655 GLsizei width, GLsizei height) {
1656 GL2Encoder* ctx = (GL2Encoder*) self;
1657 GLClientState* state = ctx->m_state;
1658
1659 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
1660 switch (internalformat) {
1661 // Funny internal formats
1662 // that will cause an incomplete framebuffer
1663 // attachment error. For dEQP,
1664 // we can also just abort early here in
1665 // RenderbufferStorage with a GL_INVALID_ENUM.
1666 case GL_DEPTH_COMPONENT32F:
1667 case GL_R8:
1668 case GL_R8UI:
1669 case GL_R8I:
1670 case GL_R16UI:
1671 case GL_R16I:
1672 case GL_R32UI:
1673 case GL_R32I:
1674 case GL_RG8:
1675 case GL_RG8UI:
1676 case GL_RG8I:
1677 case GL_RG16UI:
1678 case GL_RG16I:
1679 case GL_RG32UI:
1680 case GL_RG32I:
1681 case GL_SRGB8_ALPHA8:
Lingfeng Yang69066602016-04-12 09:29:11 -07001682 case GL_RGBA8UI:
1683 case GL_RGBA8I:
1684 case GL_RGB10_A2UI:
1685 case GL_RGBA16UI:
1686 case GL_RGBA16I:
1687 case GL_RGBA32I:
1688 case GL_RGBA32UI:
1689 case GL_R11F_G11F_B10F:
1690 case GL_R32F:
1691 case GL_RG32F:
1692 case GL_RGB32F:
1693 case GL_RGBA32F:
1694 SET_ERROR_IF(true, GL_INVALID_ENUM);
1695 break;
1696 // These 4 formats are still not OK,
1697 // but dEQP expects GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT or
1698 // GL_FRAMEBUFFER_UNSUPPORTED,
1699 // not a GL_INVALID_ENUM from earlier on.
1700 // So let's forward these to the rest of
1701 // FBO initialization
1702 case GL_R16F:
1703 case GL_RG16F:
1704 case GL_RGB16F:
1705 case GL_RGBA16F:
Yahan Zhouafbb4f82016-05-11 10:45:31 -07001706 // dEQP expects GL_FRAMEBUFFER_UNSUPPORTED or GL_FRAMEBUFFER_COMPLETE
1707 // for this format
1708 case GL_RGB10_A2:
Lingfeng Yang69066602016-04-12 09:29:11 -07001709 // These formats are OK
1710 case GL_DEPTH_COMPONENT16:
1711 case GL_DEPTH_COMPONENT24:
1712 case GL_DEPTH_COMPONENT32_OES:
1713 case GL_RGBA4:
1714 case GL_RGB5_A1:
1715 case GL_RGB565:
1716 case GL_RGB8_OES:
1717 case GL_RGBA8_OES:
1718 case GL_STENCIL_INDEX8:
1719 case GL_DEPTH32F_STENCIL8:
1720 case GL_DEPTH24_STENCIL8_OES:
1721 break;
1722 // Everything else: still not OK,
1723 // and they need the GL_INVALID_ENUM
1724 default:
1725 SET_ERROR_IF(true, GL_INVALID_ENUM);
1726 }
1727
1728 state->setBoundRenderbufferFormat(internalformat);
1729 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
1730 width, height);
1731}
1732
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07001733void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
1734 GLenum target, GLenum attachment,
1735 GLenum renderbuffertarget, GLuint renderbuffer) {
1736 GL2Encoder* ctx = (GL2Encoder*)self;
1737 GLClientState* state = ctx->m_state;
1738
1739 state->attachRbo(attachment, renderbuffer);
1740
1741 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
1742}
1743
1744void GL2Encoder::s_glGenFramebuffers(void* self,
1745 GLsizei n, GLuint* framebuffers) {
1746 GL2Encoder* ctx = (GL2Encoder*)self;
1747 GLClientState* state = ctx->m_state;
1748
1749 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1750
1751 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
1752 state->addFramebuffers(n, framebuffers);
1753}
1754
1755void GL2Encoder::s_glDeleteFramebuffers(void* self,
1756 GLsizei n, const GLuint* framebuffers) {
1757 GL2Encoder* ctx = (GL2Encoder*)self;
1758 GLClientState* state = ctx->m_state;
1759
1760 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1761
1762 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
1763 state->removeFramebuffers(n, framebuffers);
1764}
1765
1766void GL2Encoder::s_glBindFramebuffer(void* self,
1767 GLenum target, GLuint framebuffer) {
1768 GL2Encoder* ctx = (GL2Encoder*)self;
1769 GLClientState* state = ctx->m_state;
1770
1771 SET_ERROR_IF((target != GL_FRAMEBUFFER),
1772 GL_INVALID_ENUM);
1773
1774 state->bindFramebuffer(target, framebuffer);
1775
1776 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
1777}
1778
1779void GL2Encoder::s_glFramebufferTexture2D(void* self,
1780 GLenum target, GLenum attachment,
1781 GLenum textarget, GLuint texture, GLint level) {
1782 GL2Encoder* ctx = (GL2Encoder*)self;
1783 GLClientState* state = ctx->m_state;
1784
1785 state->attachTextureObject(attachment, texture);
1786
1787 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
1788}
1789
1790void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
1791 GLenum target, GLenum attachment,
1792 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
1793 GL2Encoder* ctx = (GL2Encoder*)self;
1794 GLClientState* state = ctx->m_state;
1795
1796 state->attachTextureObject(attachment, texture);
1797
1798 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
1799}
1800
1801void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
1802 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
1803 GL2Encoder* ctx = (GL2Encoder*)self;
1804 const GLClientState* state = ctx->m_state;
1805
1806 SET_ERROR_IF(state->boundFramebuffer() == 0,
1807 GL_INVALID_OPERATION);
1808 SET_ERROR_IF((pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) &&
1809 (!state->attachmentHasObject(attachment)),
1810 GL_INVALID_ENUM);
1811
1812 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
1813}
Lingfeng Yang69066602016-04-12 09:29:11 -07001814
1815bool GL2Encoder::isCompleteFbo(const GLClientState* state,
1816 GLenum attachment) const {
1817 FboFormatInfo fbo_format_info;
1818 state->getBoundFramebufferFormat(attachment, &fbo_format_info);
1819
1820 bool res;
1821 switch (fbo_format_info.type) {
1822 case FBO_ATTACHMENT_RENDERBUFFER:
1823 switch (fbo_format_info.rb_format) {
1824 case GL_R16F:
1825 case GL_RG16F:
1826 case GL_RGB16F:
1827 case GL_RGBA16F:
1828 res = false;
1829 break;
1830 case GL_STENCIL_INDEX8:
1831 if (attachment == GL_STENCIL_ATTACHMENT) {
1832 res = true;
1833 } else {
1834 res = false;
1835 }
1836 break;
1837 default:
1838 res = true;
1839 }
1840 break;
1841 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001842 switch (fbo_format_info.tex_internalformat) {
1843 case GL_RED:
1844 case GL_RG:
1845 case GL_R16F:
1846 case GL_RG16F:
1847 case GL_RGBA16F:
1848 case GL_RGB16F:
1849 case GL_R11F_G11F_B10F:
1850 res = false;
1851 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07001852 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001853 case GL_RGB:
1854 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07001855 switch (fbo_format_info.tex_type) {
1856 case GL_FLOAT:
1857 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001858 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07001859 res = false;
1860 break;
1861 default:
1862 res = true;
1863 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001864 break;
1865 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07001866 res = true;
1867 }
1868 break;
1869 case FBO_ATTACHMENT_NONE:
1870 res = true;
1871 break;
1872 default:
1873 res = true;
1874 }
1875 return res;
1876}
1877
1878GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
1879 GL2Encoder* ctx = (GL2Encoder*)self;
1880 GLClientState* state = ctx->m_state;
1881
1882 bool complete = ctx->isCompleteFbo(state, GL_COLOR_ATTACHMENT0) &&
1883 ctx->isCompleteFbo(state, GL_DEPTH_ATTACHMENT) &&
1884 ctx->isCompleteFbo(state, GL_STENCIL_ATTACHMENT);
1885 if (!complete) {
1886 state->setCheckFramebufferStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
1887 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1888 } else {
1889 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
1890 state->setCheckFramebufferStatus(host_checkstatus);
1891 return host_checkstatus;
1892 }
1893}