blob: 7e5ccebbec97e69cdf706e6e62c606bb3dbded58 [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
keunyoungb85b2752013-03-08 12:28:03 -080062 //overrides
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010063#define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name
bohu56bf82f2014-10-17 15:35:48 -070064
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010065 OVERRIDE(glFlush);
66 OVERRIDE(glPixelStorei);
67 OVERRIDE(glGetString);
68 OVERRIDE(glBindBuffer);
69 OVERRIDE(glBufferData);
70 OVERRIDE(glBufferSubData);
71 OVERRIDE(glDeleteBuffers);
72 OVERRIDE(glDrawArrays);
73 OVERRIDE(glDrawElements);
74 OVERRIDE(glGetIntegerv);
75 OVERRIDE(glGetFloatv);
76 OVERRIDE(glGetBooleanv);
77 OVERRIDE(glVertexAttribPointer);
78 OVERRIDE(glEnableVertexAttribArray);
79 OVERRIDE(glDisableVertexAttribArray);
80 OVERRIDE(glGetVertexAttribiv);
81 OVERRIDE(glGetVertexAttribfv);
82 OVERRIDE(glGetVertexAttribPointerv);
keunyoungb85b2752013-03-08 12:28:03 -080083
Bo Hu73568cd2015-01-20 16:29:50 -080084 this->glShaderBinary = &s_glShaderBinary;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010085 this->glShaderSource = &s_glShaderSource;
86 this->glFinish = &s_glFinish;
keunyoungb85b2752013-03-08 12:28:03 -080087
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010088 OVERRIDE(glGetError);
89 OVERRIDE(glLinkProgram);
90 OVERRIDE(glDeleteProgram);
91 OVERRIDE(glGetUniformiv);
92 OVERRIDE(glGetUniformfv);
93 OVERRIDE(glCreateProgram);
94 OVERRIDE(glCreateShader);
95 OVERRIDE(glDeleteShader);
96 OVERRIDE(glAttachShader);
97 OVERRIDE(glDetachShader);
98 OVERRIDE(glGetAttachedShaders);
99 OVERRIDE(glGetShaderSource);
100 OVERRIDE(glGetShaderInfoLog);
101 OVERRIDE(glGetProgramInfoLog);
102
103 OVERRIDE(glGetUniformLocation);
104 OVERRIDE(glUseProgram);
105
106 OVERRIDE(glUniform1f);
107 OVERRIDE(glUniform1fv);
108 OVERRIDE(glUniform1i);
109 OVERRIDE(glUniform1iv);
110 OVERRIDE(glUniform2f);
111 OVERRIDE(glUniform2fv);
112 OVERRIDE(glUniform2i);
113 OVERRIDE(glUniform2iv);
114 OVERRIDE(glUniform3f);
115 OVERRIDE(glUniform3fv);
116 OVERRIDE(glUniform3i);
117 OVERRIDE(glUniform3iv);
118 OVERRIDE(glUniform4f);
119 OVERRIDE(glUniform4fv);
120 OVERRIDE(glUniform4i);
121 OVERRIDE(glUniform4iv);
122 OVERRIDE(glUniformMatrix2fv);
123 OVERRIDE(glUniformMatrix3fv);
124 OVERRIDE(glUniformMatrix4fv);
125
126 OVERRIDE(glActiveTexture);
127 OVERRIDE(glBindTexture);
128 OVERRIDE(glDeleteTextures);
129 OVERRIDE(glGetTexParameterfv);
130 OVERRIDE(glGetTexParameteriv);
131 OVERRIDE(glTexParameterf);
132 OVERRIDE(glTexParameterfv);
133 OVERRIDE(glTexParameteri);
134 OVERRIDE(glTexParameteriv);
bohu26a92982014-11-25 16:50:37 -0800135 OVERRIDE(glTexImage2D);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700136
137 OVERRIDE(glGenRenderbuffers);
138 OVERRIDE(glDeleteRenderbuffers);
139 OVERRIDE(glBindRenderbuffer);
Lingfeng Yang69066602016-04-12 09:29:11 -0700140 OVERRIDE(glRenderbufferStorage);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700141 OVERRIDE(glFramebufferRenderbuffer);
142
143 OVERRIDE(glGenFramebuffers);
144 OVERRIDE(glDeleteFramebuffers);
145 OVERRIDE(glBindFramebuffer);
146 OVERRIDE(glFramebufferTexture2D);
147 OVERRIDE(glFramebufferTexture3DOES);
148 OVERRIDE(glGetFramebufferAttachmentParameteriv);
Lingfeng Yang69066602016-04-12 09:29:11 -0700149
150 OVERRIDE(glCheckFramebufferStatus);
keunyoungb85b2752013-03-08 12:28:03 -0800151}
152
153GL2Encoder::~GL2Encoder()
154{
155 delete m_compressedTextureFormats;
156}
157
158GLenum GL2Encoder::s_glGetError(void * self)
159{
160 GL2Encoder *ctx = (GL2Encoder *)self;
161 GLenum err = ctx->getError();
162 if(err != GL_NO_ERROR) {
163 ctx->setError(GL_NO_ERROR);
164 return err;
165 }
166
167 return ctx->m_glGetError_enc(self);
168
169}
170
171void GL2Encoder::s_glFlush(void *self)
172{
173 GL2Encoder *ctx = (GL2Encoder *) self;
174 ctx->m_glFlush_enc(self);
175 ctx->m_stream->flush();
176}
177
178const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
179{
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100180 (void)self;
181
keunyoungb85b2752013-03-08 12:28:03 -0800182 GLubyte *retval = (GLubyte *) "";
183 switch(name) {
184 case GL_VENDOR:
185 retval = gVendorString;
186 break;
187 case GL_RENDERER:
188 retval = gRendererString;
189 break;
190 case GL_VERSION:
191 retval = gVersionString;
192 break;
193 case GL_EXTENSIONS:
194 retval = gExtensionsString;
195 break;
196 }
197 return retval;
198}
199
200void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
201{
202 GL2Encoder *ctx = (GL2Encoder *)self;
203 ctx->m_glPixelStorei_enc(ctx, param, value);
204 assert(ctx->m_state != NULL);
205 ctx->m_state->setPixelStore(param, value);
206}
207
208
209void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
210{
211 GL2Encoder *ctx = (GL2Encoder *) self;
212 assert(ctx->m_state != NULL);
213 ctx->m_state->bindBuffer(target, id);
214 // TODO set error state if needed;
215 ctx->m_glBindBuffer_enc(self, target, id);
216}
217
218void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
219{
220 GL2Encoder *ctx = (GL2Encoder *) self;
bohub0f0cdf2014-11-06 18:08:07 -0800221 SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800222 GLuint bufferId = ctx->m_state->getBuffer(target);
223 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
224 SET_ERROR_IF(size<0, GL_INVALID_VALUE);
225
226 ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
227 ctx->m_glBufferData_enc(self, target, size, data, usage);
228}
229
230void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
231{
232 GL2Encoder *ctx = (GL2Encoder *) self;
bohub0f0cdf2014-11-06 18:08:07 -0800233 SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800234 GLuint bufferId = ctx->m_state->getBuffer(target);
235 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
236
237 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
238 SET_ERROR_IF(res, res);
239
240 ctx->m_glBufferSubData_enc(self, target, offset, size, data);
241}
242
243void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
244{
245 GL2Encoder *ctx = (GL2Encoder *) self;
246 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
247 for (int i=0; i<n; i++) {
248 ctx->m_shared->deleteBufferData(buffers[i]);
bohub0f0cdf2014-11-06 18:08:07 -0800249 ctx->m_state->unBindBuffer(buffers[i]);
keunyoungb85b2752013-03-08 12:28:03 -0800250 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
251 }
252}
253
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700254static bool isValidVertexAttribIndex(void *self, GLuint indx)
255{
256 GL2Encoder *ctx = (GL2Encoder *) self;
257 GLint maxIndex;
258 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
259 return indx < maxIndex;
260}
261
262static bool isValidVertexAttribType(GLenum type)
263{
264 bool retval = false;
265 switch (type) {
266 case GL_BYTE:
267 case GL_UNSIGNED_BYTE:
268 case GL_SHORT:
269 case GL_UNSIGNED_SHORT:
270 case GL_FIXED:
271 case GL_FLOAT:
272 // The following are technically only available if certain GLES2 extensions are.
273 // However, they are supported by desktop GL3, which is a reasonable requirement
274 // for the desktop GL version. Therefore, consider them valid.
275 case GL_INT:
276 case GL_UNSIGNED_INT:
277 case GL_HALF_FLOAT_OES:
278 retval = true;
279 break;
280 }
281 return retval;
282}
283
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100284void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
keunyoungb85b2752013-03-08 12:28:03 -0800285{
286 GL2Encoder *ctx = (GL2Encoder *)self;
287 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700288 SET_ERROR_IF(!isValidVertexAttribIndex(self, indx), GL_INVALID_VALUE);
289 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
290 SET_ERROR_IF(!isValidVertexAttribType(type), GL_INVALID_ENUM);
291 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800292 ctx->m_state->setState(indx, size, type, normalized, stride, ptr);
293}
294
295void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
296{
297 GL2Encoder *ctx = (GL2Encoder *) self;
298 assert(ctx->m_state != NULL);
299 GLClientState* state = ctx->m_state;
300
301 switch (param) {
302 case GL_NUM_SHADER_BINARY_FORMATS:
303 *ptr = 0;
304 break;
305 case GL_SHADER_BINARY_FORMATS:
306 // do nothing
307 break;
308
309 case GL_COMPRESSED_TEXTURE_FORMATS: {
310 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
311 if (ctx->m_num_compressedTextureFormats > 0 &&
312 compressedTextureFormats != NULL) {
313 memcpy(ptr, compressedTextureFormats,
314 ctx->m_num_compressedTextureFormats * sizeof(GLint));
315 }
316 break;
317 }
318
319 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
320 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
321 case GL_MAX_TEXTURE_IMAGE_UNITS:
322 ctx->m_glGetIntegerv_enc(self, param, ptr);
323 *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
324 break;
325
326 case GL_TEXTURE_BINDING_2D:
327 *ptr = state->getBoundTexture(GL_TEXTURE_2D);
328 break;
329 case GL_TEXTURE_BINDING_EXTERNAL_OES:
330 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
331 break;
332
Lingfeng Yangb0176982016-03-01 21:27:49 -0800333 case GL_MAX_VERTEX_ATTRIBS:
334 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
335 ctx->m_glGetIntegerv_enc(self, param, ptr);
336 ctx->m_state->setMaxVertexAttribs(*ptr);
Yahan Zhoua5c36842016-06-01 12:49:39 -0700337 }
338 break;
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800339 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
340 if (ctx->m_max_cubeMapTextureSize != 0) {
341 *ptr = ctx->m_max_cubeMapTextureSize;
342 } else {
343 ctx->m_glGetIntegerv_enc(self, param, ptr);
344 ctx->m_max_cubeMapTextureSize = *ptr;
345 }
346 break;
347 case GL_MAX_RENDERBUFFER_SIZE:
348 if (ctx->m_max_renderBufferSize != 0) {
349 *ptr = ctx->m_max_renderBufferSize;
350 } else {
351 ctx->m_glGetIntegerv_enc(self, param, ptr);
352 ctx->m_max_renderBufferSize = *ptr;
353 }
354 break;
355 case GL_MAX_TEXTURE_SIZE:
356 if (ctx->m_max_textureSize != 0) {
357 *ptr = ctx->m_max_textureSize;
358 } else {
359 ctx->m_glGetIntegerv_enc(self, param, ptr);
360 ctx->m_max_textureSize = *ptr;
Lingfeng Yangb0176982016-03-01 21:27:49 -0800361 }
362 break;
keunyoungb85b2752013-03-08 12:28:03 -0800363 default:
364 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
365 ctx->m_glGetIntegerv_enc(self, param, ptr);
366 }
367 break;
368 }
369}
370
371
372void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
373{
374 GL2Encoder *ctx = (GL2Encoder *)self;
375 assert(ctx->m_state != NULL);
376 GLClientState* state = ctx->m_state;
377
378 switch (param) {
379 case GL_NUM_SHADER_BINARY_FORMATS:
380 *ptr = 0;
381 break;
382 case GL_SHADER_BINARY_FORMATS:
383 // do nothing
384 break;
385
386 case GL_COMPRESSED_TEXTURE_FORMATS: {
387 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
388 if (ctx->m_num_compressedTextureFormats > 0 &&
389 compressedTextureFormats != NULL) {
390 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
391 ptr[i] = (GLfloat) compressedTextureFormats[i];
392 }
393 }
394 break;
395 }
396
397 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
398 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
399 case GL_MAX_TEXTURE_IMAGE_UNITS:
400 ctx->m_glGetFloatv_enc(self, param, ptr);
401 *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
402 break;
403
404 case GL_TEXTURE_BINDING_2D:
405 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
406 break;
407 case GL_TEXTURE_BINDING_EXTERNAL_OES:
408 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
409 break;
410
411 default:
412 if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
413 ctx->m_glGetFloatv_enc(self, param, ptr);
414 }
415 break;
416 }
417}
418
419
420void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
421{
422 GL2Encoder *ctx = (GL2Encoder *)self;
423 assert(ctx->m_state != NULL);
424 GLClientState* state = ctx->m_state;
425
426 switch (param) {
427 case GL_NUM_SHADER_BINARY_FORMATS:
428 *ptr = GL_FALSE;
429 break;
430 case GL_SHADER_BINARY_FORMATS:
431 // do nothing
432 break;
433
434 case GL_COMPRESSED_TEXTURE_FORMATS: {
435 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
436 if (ctx->m_num_compressedTextureFormats > 0 &&
437 compressedTextureFormats != NULL) {
438 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
439 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
440 }
441 }
442 break;
443 }
444
445 case GL_TEXTURE_BINDING_2D:
446 *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
447 break;
448 case GL_TEXTURE_BINDING_EXTERNAL_OES:
449 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
450 ? GL_TRUE : GL_FALSE;
451 break;
452
453 default:
454 if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
455 ctx->m_glGetBooleanv_enc(self, param, ptr);
456 }
bohu05101d22014-11-17 16:28:42 -0800457 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
keunyoungb85b2752013-03-08 12:28:03 -0800458 break;
459 }
460}
461
462
463void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
464{
465 GL2Encoder *ctx = (GL2Encoder *)self;
466 assert(ctx->m_state);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700467 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800468 ctx->m_state->enable(index, 1);
469}
470
471void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
472{
473 GL2Encoder *ctx = (GL2Encoder *)self;
474 assert(ctx->m_state);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700475 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800476 ctx->m_state->enable(index, 0);
477}
478
479
480void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
481{
482 GL2Encoder *ctx = (GL2Encoder *)self;
483 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700484 GLint maxIndex;
485 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
486 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800487
488 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
489 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
490 }
491}
492
493void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
494{
495 GL2Encoder *ctx = (GL2Encoder *)self;
496 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700497 GLint maxIndex;
498 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
499 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800500
501 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
502 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
503 }
504}
505
506void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
507{
508 GL2Encoder *ctx = (GL2Encoder *)self;
509 if (ctx->m_state == NULL) return;
Lingfeng Yang5e100432016-04-08 12:46:42 -0700510 GLint maxIndex;
511 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
512 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
513 SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100514 (void)pname;
515
keunyoungb85b2752013-03-08 12:28:03 -0800516 const GLClientState::VertexAttribState *va_state = ctx->m_state->getState(index);
517 if (va_state != NULL) {
518 *pointer = va_state->data;
519 }
520}
521
522
523void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count)
524{
525 assert(m_state);
526
Lingfeng Yang398162b2016-05-26 14:18:33 -0700527 GLuint lastBoundVbo = m_state->currentArrayVbo();
keunyoungb85b2752013-03-08 12:28:03 -0800528 for (int i = 0; i < m_state->nLocations(); i++) {
529 bool enableDirty;
530 const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty);
531
532 if (!state) {
533 continue;
534 }
535
536 if (!enableDirty && !state->enabled) {
537 continue;
538 }
539
keunyoungb85b2752013-03-08 12:28:03 -0800540 if (state->enabled) {
Lingfeng Yang398162b2016-05-26 14:18:33 -0700541 if (lastBoundVbo != state->bufferObject) {
542 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject);
543 lastBoundVbo = state->bufferObject;
544 }
keunyoungb85b2752013-03-08 12:28:03 -0800545
546 unsigned int datalen = state->elementSize * count;
547 int stride = state->stride == 0 ? state->elementSize : state->stride;
548 int firstIndex = stride * first;
549
550 if (state->bufferObject == 0) {
Yahan Zhou5507c042016-06-01 17:24:28 -0700551 m_glEnableVertexAttribArray_enc(this, i);
keunyoungb85b2752013-03-08 12:28:03 -0800552 this->glVertexAttribPointerData(this, i, state->size, state->type, state->normalized, state->stride,
553 (unsigned char *)state->data + firstIndex, datalen);
554 } else {
Yahan Zhou5507c042016-06-01 17:24:28 -0700555 const BufferData* buf = m_shared->getBufferData(state->bufferObject);
556 // The following expression actually means bufLen = stride*count;
557 // But the last element doesn't have to fill up the whole stride.
558 // So it becomes the current form.
559 unsigned int bufLen = stride * (count - 1) + state->elementSize;
560 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
561 m_glEnableVertexAttribArray_enc(this, i);
562 this->glVertexAttribPointerOffset(this, i, state->size, state->type, state->normalized, state->stride,
Tina Zhang163119f2014-03-21 08:14:41 +0800563 (uintptr_t) state->data + firstIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -0700564 } else {
565 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute.");
566 m_glDisableVertexAttribArray_enc(this, i);
567 }
keunyoungb85b2752013-03-08 12:28:03 -0800568 }
569 } else {
570 this->m_glDisableVertexAttribArray_enc(this, i);
571 }
572 }
Lingfeng Yang398162b2016-05-26 14:18:33 -0700573
574 if (lastBoundVbo != m_state->currentArrayVbo()) {
575 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
576 }
keunyoungb85b2752013-03-08 12:28:03 -0800577}
578
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700579static bool isValidDrawMode(GLenum mode)
580{
581 bool retval = false;
582 switch (mode) {
583 case GL_POINTS:
584 case GL_LINE_STRIP:
585 case GL_LINE_LOOP:
586 case GL_LINES:
587 case GL_TRIANGLE_STRIP:
588 case GL_TRIANGLE_FAN:
589 case GL_TRIANGLES:
590 retval = true;
591 }
592 return retval;
593}
594
keunyoungb85b2752013-03-08 12:28:03 -0800595void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
596{
597 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700598 assert(ctx->m_state != NULL);
599 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
600 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhoud6217a52016-02-10 16:10:46 -0800601
602 bool has_arrays = false;
603 int nLocations = ctx->m_state->nLocations();
604 for (int i = 0; i < nLocations; i++) {
605 const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
606 if (state->enabled) {
607 if (state->bufferObject || state->data) {
608 has_arrays = true;
609 }
610 else {
611 ALOGE("glDrawArrays: a vertex attribute array is enabled with no data bound\n");
612 ctx->setError(GL_INVALID_OPERATION);
613 return;
614 }
615 }
616 }
Yahan Zhoud6217a52016-02-10 16:10:46 -0800617
keunyoungb85b2752013-03-08 12:28:03 -0800618 ctx->sendVertexAttributes(first, count);
619 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
620}
621
622
623void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
624{
625
626 GL2Encoder *ctx = (GL2Encoder *)self;
627 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700628 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
629 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -0700630 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800631
632 bool has_immediate_arrays = false;
633 bool has_indirect_arrays = false;
634 int nLocations = ctx->m_state->nLocations();
Yahan Zhou5507c042016-06-01 17:24:28 -0700635 GLintptr offset = 0;
keunyoungb85b2752013-03-08 12:28:03 -0800636
637 for (int i = 0; i < nLocations; i++) {
638 const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
639 if (state->enabled) {
640 if (state->bufferObject != 0) {
641 has_indirect_arrays = true;
Yahan Zhoud6217a52016-02-10 16:10:46 -0800642 } else if (state->data) {
keunyoungb85b2752013-03-08 12:28:03 -0800643 has_immediate_arrays = true;
Yahan Zhoud6217a52016-02-10 16:10:46 -0800644 } else {
645 ALOGW("glDrawElements: a vertex attribute array is enabled with no data bound\n");
646 ctx->setError(GL_INVALID_OPERATION);
647 return;
keunyoungb85b2752013-03-08 12:28:03 -0800648 }
649 }
650 }
651
652 if (!has_immediate_arrays && !has_indirect_arrays) {
653 ALOGE("glDrawElements: no data bound to the command - ignoring\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -0700654 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
655 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800656 return;
657 }
658
Yahan Zhou5507c042016-06-01 17:24:28 -0700659 if (ctx->m_state->currentIndexVbo() != 0) {
660 offset = (GLintptr)indices;
661 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
662 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + offset);
663 }
664 int minIndex = 0, maxIndex = 0;
665 switch(type) {
666 case GL_BYTE:
667 case GL_UNSIGNED_BYTE:
668 GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex);
669 break;
670 case GL_SHORT:
671 case GL_UNSIGNED_SHORT:
672 GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex);
673 break;
674 case GL_INT:
675 case GL_UNSIGNED_INT:
676 GLUtils::minmax<unsigned int>((unsigned int *)indices, count, &minIndex, &maxIndex);
677 break;
678 default:
679 ALOGE("unsupported index buffer type %d\n", type);
680 }
681
keunyoungb85b2752013-03-08 12:28:03 -0800682 bool adjustIndices = true;
683 if (ctx->m_state->currentIndexVbo() != 0) {
684 if (!has_immediate_arrays) {
Yahan Zhou5507c042016-06-01 17:24:28 -0700685 ctx->sendVertexAttributes(0, maxIndex + 1);
keunyoungb85b2752013-03-08 12:28:03 -0800686 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -0700687 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
keunyoungb85b2752013-03-08 12:28:03 -0800688 adjustIndices = false;
689 } else {
690 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
691 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -0800692 }
693 }
694 if (adjustIndices) {
695 void *adjustedIndices = (void*)indices;
keunyoungb85b2752013-03-08 12:28:03 -0800696
Yahan Zhou5507c042016-06-01 17:24:28 -0700697 if (minIndex != 0) {
698 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
699 switch(type) {
700 case GL_BYTE:
701 case GL_UNSIGNED_BYTE:
keunyoungb85b2752013-03-08 12:28:03 -0800702 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices,
703 (unsigned char *)adjustedIndices,
704 count, -minIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -0700705 break;
706 case GL_SHORT:
707 case GL_UNSIGNED_SHORT:
keunyoungb85b2752013-03-08 12:28:03 -0800708 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices,
709 (unsigned short *)adjustedIndices,
710 count, -minIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -0700711 break;
712 case GL_INT:
713 case GL_UNSIGNED_INT:
Yahan Zhou59508522016-02-09 17:42:33 -0800714 GLUtils::shiftIndices<unsigned int>((unsigned int *)indices,
715 (unsigned int *)adjustedIndices,
716 count, -minIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -0700717 break;
718 default:
719 ALOGE("unsupported index buffer type %d\n", type);
Yahan Zhou59508522016-02-09 17:42:33 -0800720 }
keunyoungb85b2752013-03-08 12:28:03 -0800721 }
722 if (has_indirect_arrays || 1) {
723 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1);
724 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
725 count * glSizeof(type));
726 // XXX - OPTIMIZATION (see the other else branch) should be implemented
727 if(!has_indirect_arrays) {
728 //ALOGD("unoptimized drawelements !!!\n");
729 }
730 } else {
731 // we are all direct arrays and immidate mode index array -
732 // rebuild the arrays and the index array;
733 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
734 }
735 }
736}
737
738
739GLint * GL2Encoder::getCompressedTextureFormats()
740{
741 if (m_compressedTextureFormats == NULL) {
742 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
743 &m_num_compressedTextureFormats);
744 if (m_num_compressedTextureFormats > 0) {
745 // get number of texture formats;
746 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
747 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
748 }
749 }
750 return m_compressedTextureFormats;
751}
752
753// Replace uses of samplerExternalOES with sampler2D, recording the names of
754// modified shaders in data. Also remove
755// #extension GL_OES_EGL_image_external : require
756// statements.
757//
758// This implementation assumes the input has already been pre-processed. If not,
759// a few cases will be mishandled:
760//
761// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
762// the following code:
763// #if 1
764// uniform sampler2D mySampler;
765// #else
766// uniform samplerExternalOES mySampler;
767// #endif
768//
769// 2. Comments that look like sampler declarations will be incorrectly modified
770// and recorded:
771// // samplerExternalOES hahaFooledYou
772//
773// 3. However, GLSL ES does not have a concatentation operator, so things like
774// this (valid in C) are invalid and not a problem:
775// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
776// SAMPLER(ExternalOES, mySampler);
777//
778static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
779{
780 static const char STR_HASH_EXTENSION[] = "#extension";
781 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
782 static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
783 static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
784
785 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
786 char* c = str;
787 while ((c = strstr(c, STR_HASH_EXTENSION))) {
788 char* start = c;
789 c += sizeof(STR_HASH_EXTENSION)-1;
790 while (isspace(*c) && *c != '\0') {
791 c++;
792 }
793 if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
794 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
795 {
796 // #extension statements are terminated by end of line
797 c = start;
798 while (*c != '\0' && *c != '\r' && *c != '\n') {
799 *c++ = ' ';
800 }
801 }
802 }
803
804 // -- replace "samplerExternalOES" with "sampler2D" and record name
805 c = str;
806 while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
807 // Make sure "samplerExternalOES" isn't a substring of a larger token
808 if (c == str || !isspace(*(c-1))) {
809 c++;
810 continue;
811 }
812 char* sampler_start = c;
813 c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
814 if (!isspace(*c) && *c != '\0') {
815 continue;
816 }
817
818 // capture sampler name
819 while (isspace(*c) && *c != '\0') {
820 c++;
821 }
822 if (!isalpha(*c) && *c != '_') {
823 // not an identifier
824 return false;
825 }
826 char* name_start = c;
827 do {
828 c++;
829 } while (isalnum(*c) || *c == '_');
830 data->samplerExternalNames.push_back(
831 android::String8(name_start, c - name_start));
832
833 // memcpy instead of strcpy since we don't want the NUL terminator
834 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
835 }
836
837 return true;
838}
839
Bo Hu73568cd2015-01-20 16:29:50 -0800840void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
841{
842 GL2Encoder* ctx = (GL2Encoder*)self;
843 // Although it is not supported, need to set proper error code.
844 SET_ERROR_IF(1, GL_INVALID_ENUM);
845}
846
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100847void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -0800848{
849 GL2Encoder* ctx = (GL2Encoder*)self;
850 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Tina Zhang7a84f652014-12-04 12:37:30 +0800851 SET_ERROR_IF(!ctx->m_shared->isObject(shader), GL_INVALID_VALUE);
852 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
853 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800854
855 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
856 char *str = new char[len + 1];
857 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
858
859 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
860 // Perhaps we can borrow Mesa's pre-processor?
861
862 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -0700863 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -0800864 ctx->setError(GL_OUT_OF_MEMORY);
865 return;
866 }
867
868 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -0700869 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -0800870}
871
872void GL2Encoder::s_glFinish(void *self)
873{
874 GL2Encoder *ctx = (GL2Encoder *)self;
875 ctx->glFinishRoundTrip(self);
876}
877
878void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
879{
880 GL2Encoder *ctx = (GL2Encoder *)self;
881 ctx->m_glLinkProgram_enc(self, program);
882
883 GLint linkStatus = 0;
884 ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
885 if (!linkStatus)
886 return;
887
888 //get number of active uniforms in the program
889 GLint numUniforms=0;
890 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
891 ctx->m_shared->initProgramData(program,numUniforms);
892
893 //get the length of the longest uniform name
894 GLint maxLength=0;
895 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
896
897 GLint size;
898 GLenum type;
899 GLchar *name = new GLchar[maxLength+1];
900 GLint location;
901 //for each active uniform, get its size and starting location.
902 for (GLint i=0 ; i<numUniforms ; ++i)
903 {
904 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
905 location = ctx->m_glGetUniformLocation_enc(self, program, name);
906 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
907 }
908 ctx->m_shared->setupLocationShiftWAR(program);
909
910 delete[] name;
911}
912
913void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
914{
915 GL2Encoder *ctx = (GL2Encoder*)self;
916 ctx->m_glDeleteProgram_enc(self, program);
917
918 ctx->m_shared->deleteProgramData(program);
919}
920
921void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
922{
923 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang35b0fda2016-04-08 12:21:13 -0700924 SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
925 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800926 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
927 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
928 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
929 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
930}
931void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
932{
933 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang35b0fda2016-04-08 12:21:13 -0700934 SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
935 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800936 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
937 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
938 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
939 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
940}
941
942GLuint GL2Encoder::s_glCreateProgram(void * self)
943{
944 GL2Encoder *ctx = (GL2Encoder*)self;
945 GLuint program = ctx->m_glCreateProgram_enc(self);
946 if (program!=0)
947 ctx->m_shared->addProgramData(program);
948 return program;
949}
950
951GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
952{
953 GL2Encoder *ctx = (GL2Encoder*)self;
Tina Zhanga45cd9a2015-03-26 14:45:29 +0800954 RET_AND_SET_ERROR_IF(((shaderType != GL_VERTEX_SHADER) && (shaderType != GL_FRAGMENT_SHADER)),
955 GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -0800956 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
957 if (shader != 0) {
958 if (!ctx->m_shared->addShaderData(shader)) {
959 ctx->m_glDeleteShader_enc(self, shader);
960 return 0;
961 }
962 }
963 return shader;
964}
965
bohu56bf82f2014-10-17 15:35:48 -0700966void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
967 GLsizei* count, GLuint* shaders)
968{
969 GL2Encoder *ctx = (GL2Encoder*)self;
970 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
971 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
972}
973
974void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
975 GLsizei* length, GLchar* source)
976{
977 GL2Encoder *ctx = (GL2Encoder*)self;
978 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
979 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
980}
981
982void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
983 GLsizei* length, GLchar* infolog)
984{
985 GL2Encoder *ctx = (GL2Encoder*)self;
986 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
987 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
988}
989
990void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
991 GLsizei* length, GLchar* infolog)
992{
993 GL2Encoder *ctx = (GL2Encoder*)self;
994 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
995 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
996}
997
keunyoungb85b2752013-03-08 12:28:03 -0800998void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
999{
1000 GL2Encoder *ctx = (GL2Encoder*)self;
1001 ctx->m_glDeleteShader_enc(self,shader);
1002 ctx->m_shared->unrefShaderData(shader);
1003}
1004
1005void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1006{
1007 GL2Encoder *ctx = (GL2Encoder*)self;
1008 ctx->m_glAttachShader_enc(self, program, shader);
1009 ctx->m_shared->attachShader(program, shader);
1010}
1011
1012void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1013{
1014 GL2Encoder *ctx = (GL2Encoder*)self;
1015 ctx->m_glDetachShader_enc(self, program, shader);
1016 ctx->m_shared->detachShader(program, shader);
1017}
1018
1019int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1020{
1021 if (!name) return -1;
1022
1023 GL2Encoder *ctx = (GL2Encoder*)self;
1024
1025 // if we need the uniform location WAR
1026 // parse array index from the end of the name string
1027 int arrIndex = 0;
1028 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1029 if (needLocationWAR) {
1030 int namelen = strlen(name);
1031 if (name[namelen-1] == ']') {
1032 char *brace = strrchr(name,'[');
1033 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1034 return -1;
1035 }
1036
1037 }
1038 }
1039
1040 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1041 if (hostLoc >= 0 && needLocationWAR) {
1042 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1043 }
1044 return hostLoc;
1045}
1046
1047bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1048{
1049 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1050 return false;
1051
1052 m_state->setActiveTextureUnit(texUnit);
1053
1054 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1055 if (newTarget != oldTarget) {
1056 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1057 m_state->disableTextureTarget(GL_TEXTURE_2D);
1058 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1059 } else {
1060 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1061 m_state->enableTextureTarget(GL_TEXTURE_2D);
1062 }
1063 m_glActiveTexture_enc(this, texUnit);
1064 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1065 m_state->getBoundTexture(newTarget));
1066 return true;
1067 }
1068
1069 return false;
1070}
1071
1072void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1073{
1074 GL2Encoder *ctx = (GL2Encoder*)self;
1075 GLClientState* state = ctx->m_state;
1076 GLSharedGroupPtr shared = ctx->m_shared;
1077
1078 ctx->m_glUseProgram_enc(self, program);
1079 ctx->m_state->setCurrentProgram(program);
1080
1081 GLenum origActiveTexture = state->getActiveTextureUnit();
1082 GLenum hostActiveTexture = origActiveTexture;
1083 GLint samplerIdx = -1;
1084 GLint samplerVal;
1085 GLenum samplerTarget;
1086 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1087 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1088 continue;
1089 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
1090 samplerTarget))
1091 {
1092 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1093 }
1094 }
1095 state->setActiveTextureUnit(origActiveTexture);
1096 if (hostActiveTexture != origActiveTexture) {
1097 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1098 }
1099}
1100
1101void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1102{
1103 GL2Encoder *ctx = (GL2Encoder*)self;
1104 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1105 ctx->m_glUniform1f_enc(self, hostLoc, x);
1106}
1107
1108void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1109{
1110 GL2Encoder *ctx = (GL2Encoder*)self;
1111 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1112 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1113}
1114
1115void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1116{
1117 GL2Encoder *ctx = (GL2Encoder*)self;
1118 GLClientState* state = ctx->m_state;
1119 GLSharedGroupPtr shared = ctx->m_shared;
1120
1121 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1122 ctx->m_glUniform1i_enc(self, hostLoc, x);
1123
1124 GLenum target;
1125 if (shared->setSamplerUniform(state->currentProgram(), location, x, &target)) {
1126 GLenum origActiveTexture = state->getActiveTextureUnit();
1127 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1128 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1129 }
1130 state->setActiveTextureUnit(origActiveTexture);
1131 }
1132}
1133
1134void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1135{
1136 GL2Encoder *ctx = (GL2Encoder*)self;
1137 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1138 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1139}
1140
1141void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1142{
1143 GL2Encoder *ctx = (GL2Encoder*)self;
1144 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1145 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1146}
1147
1148void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1149{
1150 GL2Encoder *ctx = (GL2Encoder*)self;
1151 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1152 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1153}
1154
1155void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1156{
1157 GL2Encoder *ctx = (GL2Encoder*)self;
1158 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1159 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1160}
1161
1162void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1163{
1164 GL2Encoder *ctx = (GL2Encoder*)self;
1165 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1166 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1167}
1168
1169void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1170{
1171 GL2Encoder *ctx = (GL2Encoder*)self;
1172 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1173 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1174}
1175
1176void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1177{
1178 GL2Encoder *ctx = (GL2Encoder*)self;
1179 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1180 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1181}
1182
1183void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1184{
1185 GL2Encoder *ctx = (GL2Encoder*)self;
1186 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1187 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1188}
1189
1190void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1191{
1192 GL2Encoder *ctx = (GL2Encoder*)self;
1193 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1194 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1195}
1196
1197void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1198{
1199 GL2Encoder *ctx = (GL2Encoder*)self;
1200 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1201 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1202}
1203
1204void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1205{
1206 GL2Encoder *ctx = (GL2Encoder*)self;
1207 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1208 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1209}
1210
1211void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1212{
1213 GL2Encoder *ctx = (GL2Encoder*)self;
1214 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1215 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1216}
1217
1218void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1219{
1220 GL2Encoder *ctx = (GL2Encoder*)self;
1221 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1222 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1223}
1224
1225void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1226{
1227 GL2Encoder *ctx = (GL2Encoder*)self;
1228 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1229 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1230}
1231
1232void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1233{
1234 GL2Encoder *ctx = (GL2Encoder*)self;
1235 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1236 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1237}
1238
1239void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1240{
1241 GL2Encoder *ctx = (GL2Encoder*)self;
1242 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1243 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1244}
1245
1246void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1247{
1248 GL2Encoder* ctx = (GL2Encoder*)self;
1249 GLClientState* state = ctx->m_state;
1250 GLenum err;
1251
1252 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1253
1254 ctx->m_glActiveTexture_enc(ctx, texture);
1255}
1256
1257void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1258{
1259 GL2Encoder* ctx = (GL2Encoder*)self;
1260 GLClientState* state = ctx->m_state;
1261 GLenum err;
1262 GLboolean firstUse;
1263
1264 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1265
1266 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1267 ctx->m_glBindTexture_enc(ctx, target, texture);
1268 return;
1269 }
1270
1271 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1272
1273 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1274 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1275 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1276 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1277 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1278 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1279 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1280 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1281
1282 if (target != priorityTarget) {
1283 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1284 state->getBoundTexture(GL_TEXTURE_2D));
1285 }
1286 }
1287
1288 if (target == priorityTarget) {
1289 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1290 }
1291}
1292
1293void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1294{
1295 GL2Encoder* ctx = (GL2Encoder*)self;
1296 GLClientState* state = ctx->m_state;
1297
1298 state->deleteTextures(n, textures);
1299 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1300}
1301
1302void GL2Encoder::s_glGetTexParameterfv(void* self,
1303 GLenum target, GLenum pname, GLfloat* params)
1304{
1305 GL2Encoder* ctx = (GL2Encoder*)self;
1306 const GLClientState* state = ctx->m_state;
1307
1308 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1309 ctx->override2DTextureTarget(target);
1310 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
1311 ctx->restore2DTextureTarget();
1312 } else {
1313 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1314 }
1315}
1316
1317void GL2Encoder::s_glGetTexParameteriv(void* self,
1318 GLenum target, GLenum pname, GLint* params)
1319{
1320 GL2Encoder* ctx = (GL2Encoder*)self;
1321 const GLClientState* state = ctx->m_state;
1322
1323 switch (pname) {
1324 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1325 *params = 1;
1326 break;
1327
1328 default:
1329 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1330 ctx->override2DTextureTarget(target);
1331 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
1332 ctx->restore2DTextureTarget();
1333 } else {
1334 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1335 }
1336 break;
1337 }
1338}
1339
1340static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1341{
1342 switch (pname) {
1343 case GL_TEXTURE_MIN_FILTER:
1344 case GL_TEXTURE_MAG_FILTER:
1345 return param == GL_NEAREST || param == GL_LINEAR;
1346
1347 case GL_TEXTURE_WRAP_S:
1348 case GL_TEXTURE_WRAP_T:
1349 return param == GL_CLAMP_TO_EDGE;
1350
1351 default:
1352 return true;
1353 }
1354}
1355
1356void GL2Encoder::s_glTexParameterf(void* self,
1357 GLenum target, GLenum pname, GLfloat param)
1358{
1359 GL2Encoder* ctx = (GL2Encoder*)self;
1360 const GLClientState* state = ctx->m_state;
1361
1362 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1363 !isValidTextureExternalParam(pname, (GLenum)param)),
1364 GL_INVALID_ENUM);
1365
1366 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1367 ctx->override2DTextureTarget(target);
1368 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
1369 ctx->restore2DTextureTarget();
1370 } else {
1371 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1372 }
1373}
1374
1375void GL2Encoder::s_glTexParameterfv(void* self,
1376 GLenum target, GLenum pname, const GLfloat* params)
1377{
1378 GL2Encoder* ctx = (GL2Encoder*)self;
1379 const GLClientState* state = ctx->m_state;
1380
1381 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1382 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1383 GL_INVALID_ENUM);
1384
1385 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1386 ctx->override2DTextureTarget(target);
1387 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
1388 ctx->restore2DTextureTarget();
1389 } else {
1390 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1391 }
1392}
1393
1394void GL2Encoder::s_glTexParameteri(void* self,
1395 GLenum target, GLenum pname, GLint param)
1396{
1397 GL2Encoder* ctx = (GL2Encoder*)self;
1398 const GLClientState* state = ctx->m_state;
1399
1400 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1401 !isValidTextureExternalParam(pname, (GLenum)param)),
1402 GL_INVALID_ENUM);
1403
1404 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1405 ctx->override2DTextureTarget(target);
1406 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
1407 ctx->restore2DTextureTarget();
1408 } else {
1409 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
1410 }
1411}
1412
bohu26a92982014-11-25 16:50:37 -08001413void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
1414 GLint internalformat, GLsizei width, GLsizei height, GLint border,
1415 GLenum format, GLenum type, const GLvoid* pixels)
1416{
1417 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07001418 GLClientState* state = ctx->m_state;
bohu26a92982014-11-25 16:50:37 -08001419 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1420 ctx->override2DTextureTarget(target);
Lingfeng Yang69066602016-04-12 09:29:11 -07001421 state->setBoundTextureInternalFormat(target, internalformat);
1422 state->setBoundTextureFormat(target, format);
1423 state->setBoundTextureType(target, type);
1424
bohu26a92982014-11-25 16:50:37 -08001425 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1426 height, border, format, type, pixels);
1427 ctx->restore2DTextureTarget();
1428 } else {
1429 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1430 height, border, format, type, pixels);
1431 }
1432}
1433
1434
keunyoungb85b2752013-03-08 12:28:03 -08001435void GL2Encoder::s_glTexParameteriv(void* self,
1436 GLenum target, GLenum pname, const GLint* params)
1437{
1438 GL2Encoder* ctx = (GL2Encoder*)self;
1439 const GLClientState* state = ctx->m_state;
1440
1441 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1442 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1443 GL_INVALID_ENUM);
1444
1445 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1446 ctx->override2DTextureTarget(target);
1447 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
1448 ctx->restore2DTextureTarget();
1449 } else {
1450 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
1451 }
1452}
1453
1454void GL2Encoder::override2DTextureTarget(GLenum target)
1455{
1456 if ((target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
1457 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)) {
1458 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1459 m_state->getBoundTexture(target));
1460 }
1461}
1462
1463void GL2Encoder::restore2DTextureTarget()
1464{
1465 GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1466 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1467 m_state->getBoundTexture(priorityTarget));
1468}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07001469
1470void GL2Encoder::s_glGenRenderbuffers(void* self,
1471 GLsizei n, GLuint* renderbuffers) {
1472 GL2Encoder* ctx = (GL2Encoder*)self;
1473 GLClientState* state = ctx->m_state;
1474
1475 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1476
1477 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
1478 state->addRenderbuffers(n, renderbuffers);
1479}
1480
1481void GL2Encoder::s_glDeleteRenderbuffers(void* self,
1482 GLsizei n, const GLuint* renderbuffers) {
1483 GL2Encoder* ctx = (GL2Encoder*)self;
1484 GLClientState* state = ctx->m_state;
1485
1486 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1487
1488 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
1489 state->removeRenderbuffers(n, renderbuffers);
1490}
1491
1492void GL2Encoder::s_glBindRenderbuffer(void* self,
1493 GLenum target, GLuint renderbuffer) {
1494 GL2Encoder* ctx = (GL2Encoder*)self;
1495 GLClientState* state = ctx->m_state;
1496
1497 SET_ERROR_IF((target != GL_RENDERBUFFER),
1498 GL_INVALID_ENUM);
1499
1500 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
1501 state->bindRenderbuffer(target, renderbuffer);
1502}
1503
Lingfeng Yang69066602016-04-12 09:29:11 -07001504void GL2Encoder::s_glRenderbufferStorage(void* self,
1505 GLenum target, GLenum internalformat,
1506 GLsizei width, GLsizei height) {
1507 GL2Encoder* ctx = (GL2Encoder*) self;
1508 GLClientState* state = ctx->m_state;
1509
1510 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
1511 switch (internalformat) {
1512 // Funny internal formats
1513 // that will cause an incomplete framebuffer
1514 // attachment error. For dEQP,
1515 // we can also just abort early here in
1516 // RenderbufferStorage with a GL_INVALID_ENUM.
1517 case GL_DEPTH_COMPONENT32F:
1518 case GL_R8:
1519 case GL_R8UI:
1520 case GL_R8I:
1521 case GL_R16UI:
1522 case GL_R16I:
1523 case GL_R32UI:
1524 case GL_R32I:
1525 case GL_RG8:
1526 case GL_RG8UI:
1527 case GL_RG8I:
1528 case GL_RG16UI:
1529 case GL_RG16I:
1530 case GL_RG32UI:
1531 case GL_RG32I:
1532 case GL_SRGB8_ALPHA8:
Lingfeng Yang69066602016-04-12 09:29:11 -07001533 case GL_RGBA8UI:
1534 case GL_RGBA8I:
1535 case GL_RGB10_A2UI:
1536 case GL_RGBA16UI:
1537 case GL_RGBA16I:
1538 case GL_RGBA32I:
1539 case GL_RGBA32UI:
1540 case GL_R11F_G11F_B10F:
1541 case GL_R32F:
1542 case GL_RG32F:
1543 case GL_RGB32F:
1544 case GL_RGBA32F:
1545 SET_ERROR_IF(true, GL_INVALID_ENUM);
1546 break;
1547 // These 4 formats are still not OK,
1548 // but dEQP expects GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT or
1549 // GL_FRAMEBUFFER_UNSUPPORTED,
1550 // not a GL_INVALID_ENUM from earlier on.
1551 // So let's forward these to the rest of
1552 // FBO initialization
1553 case GL_R16F:
1554 case GL_RG16F:
1555 case GL_RGB16F:
1556 case GL_RGBA16F:
Yahan Zhouafbb4f82016-05-11 10:45:31 -07001557 // dEQP expects GL_FRAMEBUFFER_UNSUPPORTED or GL_FRAMEBUFFER_COMPLETE
1558 // for this format
1559 case GL_RGB10_A2:
Lingfeng Yang69066602016-04-12 09:29:11 -07001560 // These formats are OK
1561 case GL_DEPTH_COMPONENT16:
1562 case GL_DEPTH_COMPONENT24:
1563 case GL_DEPTH_COMPONENT32_OES:
1564 case GL_RGBA4:
1565 case GL_RGB5_A1:
1566 case GL_RGB565:
1567 case GL_RGB8_OES:
1568 case GL_RGBA8_OES:
1569 case GL_STENCIL_INDEX8:
1570 case GL_DEPTH32F_STENCIL8:
1571 case GL_DEPTH24_STENCIL8_OES:
1572 break;
1573 // Everything else: still not OK,
1574 // and they need the GL_INVALID_ENUM
1575 default:
1576 SET_ERROR_IF(true, GL_INVALID_ENUM);
1577 }
1578
1579 state->setBoundRenderbufferFormat(internalformat);
1580 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
1581 width, height);
1582}
1583
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07001584void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
1585 GLenum target, GLenum attachment,
1586 GLenum renderbuffertarget, GLuint renderbuffer) {
1587 GL2Encoder* ctx = (GL2Encoder*)self;
1588 GLClientState* state = ctx->m_state;
1589
1590 state->attachRbo(attachment, renderbuffer);
1591
1592 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
1593}
1594
1595void GL2Encoder::s_glGenFramebuffers(void* self,
1596 GLsizei n, GLuint* framebuffers) {
1597 GL2Encoder* ctx = (GL2Encoder*)self;
1598 GLClientState* state = ctx->m_state;
1599
1600 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1601
1602 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
1603 state->addFramebuffers(n, framebuffers);
1604}
1605
1606void GL2Encoder::s_glDeleteFramebuffers(void* self,
1607 GLsizei n, const GLuint* framebuffers) {
1608 GL2Encoder* ctx = (GL2Encoder*)self;
1609 GLClientState* state = ctx->m_state;
1610
1611 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1612
1613 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
1614 state->removeFramebuffers(n, framebuffers);
1615}
1616
1617void GL2Encoder::s_glBindFramebuffer(void* self,
1618 GLenum target, GLuint framebuffer) {
1619 GL2Encoder* ctx = (GL2Encoder*)self;
1620 GLClientState* state = ctx->m_state;
1621
1622 SET_ERROR_IF((target != GL_FRAMEBUFFER),
1623 GL_INVALID_ENUM);
1624
1625 state->bindFramebuffer(target, framebuffer);
1626
1627 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
1628}
1629
1630void GL2Encoder::s_glFramebufferTexture2D(void* self,
1631 GLenum target, GLenum attachment,
1632 GLenum textarget, GLuint texture, GLint level) {
1633 GL2Encoder* ctx = (GL2Encoder*)self;
1634 GLClientState* state = ctx->m_state;
1635
1636 state->attachTextureObject(attachment, texture);
1637
1638 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
1639}
1640
1641void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
1642 GLenum target, GLenum attachment,
1643 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
1644 GL2Encoder* ctx = (GL2Encoder*)self;
1645 GLClientState* state = ctx->m_state;
1646
1647 state->attachTextureObject(attachment, texture);
1648
1649 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
1650}
1651
1652void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
1653 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
1654 GL2Encoder* ctx = (GL2Encoder*)self;
1655 const GLClientState* state = ctx->m_state;
1656
1657 SET_ERROR_IF(state->boundFramebuffer() == 0,
1658 GL_INVALID_OPERATION);
1659 SET_ERROR_IF((pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) &&
1660 (!state->attachmentHasObject(attachment)),
1661 GL_INVALID_ENUM);
1662
1663 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
1664}
Lingfeng Yang69066602016-04-12 09:29:11 -07001665
1666bool GL2Encoder::isCompleteFbo(const GLClientState* state,
1667 GLenum attachment) const {
1668 FboFormatInfo fbo_format_info;
1669 state->getBoundFramebufferFormat(attachment, &fbo_format_info);
1670
1671 bool res;
1672 switch (fbo_format_info.type) {
1673 case FBO_ATTACHMENT_RENDERBUFFER:
1674 switch (fbo_format_info.rb_format) {
1675 case GL_R16F:
1676 case GL_RG16F:
1677 case GL_RGB16F:
1678 case GL_RGBA16F:
1679 res = false;
1680 break;
1681 case GL_STENCIL_INDEX8:
1682 if (attachment == GL_STENCIL_ATTACHMENT) {
1683 res = true;
1684 } else {
1685 res = false;
1686 }
1687 break;
1688 default:
1689 res = true;
1690 }
1691 break;
1692 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001693 switch (fbo_format_info.tex_internalformat) {
1694 case GL_RED:
1695 case GL_RG:
1696 case GL_R16F:
1697 case GL_RG16F:
1698 case GL_RGBA16F:
1699 case GL_RGB16F:
1700 case GL_R11F_G11F_B10F:
1701 res = false;
1702 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07001703 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001704 case GL_RGB:
1705 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07001706 switch (fbo_format_info.tex_type) {
1707 case GL_FLOAT:
1708 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001709 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07001710 res = false;
1711 break;
1712 default:
1713 res = true;
1714 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001715 break;
1716 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07001717 res = true;
1718 }
1719 break;
1720 case FBO_ATTACHMENT_NONE:
1721 res = true;
1722 break;
1723 default:
1724 res = true;
1725 }
1726 return res;
1727}
1728
1729GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
1730 GL2Encoder* ctx = (GL2Encoder*)self;
1731 GLClientState* state = ctx->m_state;
1732
1733 bool complete = ctx->isCompleteFbo(state, GL_COLOR_ATTACHMENT0) &&
1734 ctx->isCompleteFbo(state, GL_DEPTH_ATTACHMENT) &&
1735 ctx->isCompleteFbo(state, GL_STENCIL_ATTACHMENT);
1736 if (!complete) {
1737 state->setCheckFramebufferStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
1738 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1739 } else {
1740 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
1741 state->setCheckFramebufferStatus(host_checkstatus);
1742 return host_checkstatus;
1743 }
1744}