blob: 9221099028b1d6d76ff81ed9f5c3c255ac00bea8 [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 m_glEnableVertexAttribArray_enc(this, i);
546
547 unsigned int datalen = state->elementSize * count;
548 int stride = state->stride == 0 ? state->elementSize : state->stride;
549 int firstIndex = stride * first;
550
551 if (state->bufferObject == 0) {
552 this->glVertexAttribPointerData(this, i, state->size, state->type, state->normalized, state->stride,
553 (unsigned char *)state->data + firstIndex, datalen);
554 } else {
keunyoungb85b2752013-03-08 12:28:03 -0800555 this->glVertexAttribPointerOffset(this, i, state->size, state->type, state->normalized, state->stride,
Tina Zhang163119f2014-03-21 08:14:41 +0800556 (uintptr_t) state->data + firstIndex);
keunyoungb85b2752013-03-08 12:28:03 -0800557 }
558 } else {
559 this->m_glDisableVertexAttribArray_enc(this, i);
560 }
561 }
Lingfeng Yang398162b2016-05-26 14:18:33 -0700562
563 if (lastBoundVbo != m_state->currentArrayVbo()) {
564 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
565 }
566
keunyoungb85b2752013-03-08 12:28:03 -0800567}
568
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700569static bool isValidDrawMode(GLenum mode)
570{
571 bool retval = false;
572 switch (mode) {
573 case GL_POINTS:
574 case GL_LINE_STRIP:
575 case GL_LINE_LOOP:
576 case GL_LINES:
577 case GL_TRIANGLE_STRIP:
578 case GL_TRIANGLE_FAN:
579 case GL_TRIANGLES:
580 retval = true;
581 }
582 return retval;
583}
584
keunyoungb85b2752013-03-08 12:28:03 -0800585void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
586{
587 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700588 assert(ctx->m_state != NULL);
589 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
590 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhoud6217a52016-02-10 16:10:46 -0800591
592 bool has_arrays = false;
593 int nLocations = ctx->m_state->nLocations();
594 for (int i = 0; i < nLocations; i++) {
595 const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
596 if (state->enabled) {
597 if (state->bufferObject || state->data) {
598 has_arrays = true;
599 }
600 else {
601 ALOGE("glDrawArrays: a vertex attribute array is enabled with no data bound\n");
602 ctx->setError(GL_INVALID_OPERATION);
603 return;
604 }
605 }
606 }
Yahan Zhoud6217a52016-02-10 16:10:46 -0800607
keunyoungb85b2752013-03-08 12:28:03 -0800608 ctx->sendVertexAttributes(first, count);
609 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
610}
611
612
613void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
614{
615
616 GL2Encoder *ctx = (GL2Encoder *)self;
617 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700618 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
619 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -0700620 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800621
622 bool has_immediate_arrays = false;
623 bool has_indirect_arrays = false;
624 int nLocations = ctx->m_state->nLocations();
625
626 for (int i = 0; i < nLocations; i++) {
627 const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
628 if (state->enabled) {
629 if (state->bufferObject != 0) {
630 has_indirect_arrays = true;
Yahan Zhoud6217a52016-02-10 16:10:46 -0800631 } else if (state->data) {
keunyoungb85b2752013-03-08 12:28:03 -0800632 has_immediate_arrays = true;
Yahan Zhoud6217a52016-02-10 16:10:46 -0800633 } else {
634 ALOGW("glDrawElements: a vertex attribute array is enabled with no data bound\n");
635 ctx->setError(GL_INVALID_OPERATION);
636 return;
keunyoungb85b2752013-03-08 12:28:03 -0800637 }
638 }
639 }
640
641 if (!has_immediate_arrays && !has_indirect_arrays) {
642 ALOGE("glDrawElements: no data bound to the command - ignoring\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -0700643 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
644 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800645 return;
646 }
647
648 bool adjustIndices = true;
649 if (ctx->m_state->currentIndexVbo() != 0) {
650 if (!has_immediate_arrays) {
651 ctx->sendVertexAttributes(0, count);
652 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Tina Zhang163119f2014-03-21 08:14:41 +0800653 ctx->glDrawElementsOffset(ctx, mode, count, type, (uintptr_t)indices);
keunyoungb85b2752013-03-08 12:28:03 -0800654 adjustIndices = false;
655 } else {
656 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
657 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
658 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
659 }
660 }
661 if (adjustIndices) {
662 void *adjustedIndices = (void*)indices;
663 int minIndex = 0, maxIndex = 0;
664
665 switch(type) {
666 case GL_BYTE:
667 case GL_UNSIGNED_BYTE:
668 GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex);
669 if (minIndex != 0) {
670 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
671 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices,
672 (unsigned char *)adjustedIndices,
673 count, -minIndex);
674 }
675 break;
676 case GL_SHORT:
677 case GL_UNSIGNED_SHORT:
678 GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex);
679 if (minIndex != 0) {
680 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
681 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices,
682 (unsigned short *)adjustedIndices,
683 count, -minIndex);
684 }
685 break;
Yahan Zhou59508522016-02-09 17:42:33 -0800686 case GL_INT:
687 case GL_UNSIGNED_INT:
688 GLUtils::minmax<unsigned int>((unsigned int *)indices, count, &minIndex, &maxIndex);
689 if (minIndex != 0) {
690 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
691 GLUtils::shiftIndices<unsigned int>((unsigned int *)indices,
692 (unsigned int *)adjustedIndices,
693 count, -minIndex);
694 }
695 break;
keunyoungb85b2752013-03-08 12:28:03 -0800696 default:
697 ALOGE("unsupported index buffer type %d\n", type);
698 }
699 if (has_indirect_arrays || 1) {
700 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1);
701 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
702 count * glSizeof(type));
703 // XXX - OPTIMIZATION (see the other else branch) should be implemented
704 if(!has_indirect_arrays) {
705 //ALOGD("unoptimized drawelements !!!\n");
706 }
707 } else {
708 // we are all direct arrays and immidate mode index array -
709 // rebuild the arrays and the index array;
710 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
711 }
712 }
713}
714
715
716GLint * GL2Encoder::getCompressedTextureFormats()
717{
718 if (m_compressedTextureFormats == NULL) {
719 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
720 &m_num_compressedTextureFormats);
721 if (m_num_compressedTextureFormats > 0) {
722 // get number of texture formats;
723 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
724 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
725 }
726 }
727 return m_compressedTextureFormats;
728}
729
730// Replace uses of samplerExternalOES with sampler2D, recording the names of
731// modified shaders in data. Also remove
732// #extension GL_OES_EGL_image_external : require
733// statements.
734//
735// This implementation assumes the input has already been pre-processed. If not,
736// a few cases will be mishandled:
737//
738// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
739// the following code:
740// #if 1
741// uniform sampler2D mySampler;
742// #else
743// uniform samplerExternalOES mySampler;
744// #endif
745//
746// 2. Comments that look like sampler declarations will be incorrectly modified
747// and recorded:
748// // samplerExternalOES hahaFooledYou
749//
750// 3. However, GLSL ES does not have a concatentation operator, so things like
751// this (valid in C) are invalid and not a problem:
752// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
753// SAMPLER(ExternalOES, mySampler);
754//
755static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
756{
757 static const char STR_HASH_EXTENSION[] = "#extension";
758 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
759 static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
760 static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
761
762 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
763 char* c = str;
764 while ((c = strstr(c, STR_HASH_EXTENSION))) {
765 char* start = c;
766 c += sizeof(STR_HASH_EXTENSION)-1;
767 while (isspace(*c) && *c != '\0') {
768 c++;
769 }
770 if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
771 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
772 {
773 // #extension statements are terminated by end of line
774 c = start;
775 while (*c != '\0' && *c != '\r' && *c != '\n') {
776 *c++ = ' ';
777 }
778 }
779 }
780
781 // -- replace "samplerExternalOES" with "sampler2D" and record name
782 c = str;
783 while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
784 // Make sure "samplerExternalOES" isn't a substring of a larger token
785 if (c == str || !isspace(*(c-1))) {
786 c++;
787 continue;
788 }
789 char* sampler_start = c;
790 c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
791 if (!isspace(*c) && *c != '\0') {
792 continue;
793 }
794
795 // capture sampler name
796 while (isspace(*c) && *c != '\0') {
797 c++;
798 }
799 if (!isalpha(*c) && *c != '_') {
800 // not an identifier
801 return false;
802 }
803 char* name_start = c;
804 do {
805 c++;
806 } while (isalnum(*c) || *c == '_');
807 data->samplerExternalNames.push_back(
808 android::String8(name_start, c - name_start));
809
810 // memcpy instead of strcpy since we don't want the NUL terminator
811 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
812 }
813
814 return true;
815}
816
Bo Hu73568cd2015-01-20 16:29:50 -0800817void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
818{
819 GL2Encoder* ctx = (GL2Encoder*)self;
820 // Although it is not supported, need to set proper error code.
821 SET_ERROR_IF(1, GL_INVALID_ENUM);
822}
823
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100824void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -0800825{
826 GL2Encoder* ctx = (GL2Encoder*)self;
827 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Tina Zhang7a84f652014-12-04 12:37:30 +0800828 SET_ERROR_IF(!ctx->m_shared->isObject(shader), GL_INVALID_VALUE);
829 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
830 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800831
832 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
833 char *str = new char[len + 1];
834 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
835
836 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
837 // Perhaps we can borrow Mesa's pre-processor?
838
839 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -0700840 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -0800841 ctx->setError(GL_OUT_OF_MEMORY);
842 return;
843 }
844
845 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -0700846 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -0800847}
848
849void GL2Encoder::s_glFinish(void *self)
850{
851 GL2Encoder *ctx = (GL2Encoder *)self;
852 ctx->glFinishRoundTrip(self);
853}
854
855void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
856{
857 GL2Encoder *ctx = (GL2Encoder *)self;
858 ctx->m_glLinkProgram_enc(self, program);
859
860 GLint linkStatus = 0;
861 ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
862 if (!linkStatus)
863 return;
864
865 //get number of active uniforms in the program
866 GLint numUniforms=0;
867 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
868 ctx->m_shared->initProgramData(program,numUniforms);
869
870 //get the length of the longest uniform name
871 GLint maxLength=0;
872 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
873
874 GLint size;
875 GLenum type;
876 GLchar *name = new GLchar[maxLength+1];
877 GLint location;
878 //for each active uniform, get its size and starting location.
879 for (GLint i=0 ; i<numUniforms ; ++i)
880 {
881 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
882 location = ctx->m_glGetUniformLocation_enc(self, program, name);
883 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
884 }
885 ctx->m_shared->setupLocationShiftWAR(program);
886
887 delete[] name;
888}
889
890void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
891{
892 GL2Encoder *ctx = (GL2Encoder*)self;
893 ctx->m_glDeleteProgram_enc(self, program);
894
895 ctx->m_shared->deleteProgramData(program);
896}
897
898void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
899{
900 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang35b0fda2016-04-08 12:21:13 -0700901 SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
902 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800903 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
904 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
905 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
906 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
907}
908void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
909{
910 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang35b0fda2016-04-08 12:21:13 -0700911 SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
912 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800913 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
914 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
915 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
916 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
917}
918
919GLuint GL2Encoder::s_glCreateProgram(void * self)
920{
921 GL2Encoder *ctx = (GL2Encoder*)self;
922 GLuint program = ctx->m_glCreateProgram_enc(self);
923 if (program!=0)
924 ctx->m_shared->addProgramData(program);
925 return program;
926}
927
928GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
929{
930 GL2Encoder *ctx = (GL2Encoder*)self;
Tina Zhanga45cd9a2015-03-26 14:45:29 +0800931 RET_AND_SET_ERROR_IF(((shaderType != GL_VERTEX_SHADER) && (shaderType != GL_FRAGMENT_SHADER)),
932 GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -0800933 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
934 if (shader != 0) {
935 if (!ctx->m_shared->addShaderData(shader)) {
936 ctx->m_glDeleteShader_enc(self, shader);
937 return 0;
938 }
939 }
940 return shader;
941}
942
bohu56bf82f2014-10-17 15:35:48 -0700943void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
944 GLsizei* count, GLuint* shaders)
945{
946 GL2Encoder *ctx = (GL2Encoder*)self;
947 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
948 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
949}
950
951void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
952 GLsizei* length, GLchar* source)
953{
954 GL2Encoder *ctx = (GL2Encoder*)self;
955 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
956 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
957}
958
959void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
960 GLsizei* length, GLchar* infolog)
961{
962 GL2Encoder *ctx = (GL2Encoder*)self;
963 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
964 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
965}
966
967void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
968 GLsizei* length, GLchar* infolog)
969{
970 GL2Encoder *ctx = (GL2Encoder*)self;
971 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
972 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
973}
974
keunyoungb85b2752013-03-08 12:28:03 -0800975void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
976{
977 GL2Encoder *ctx = (GL2Encoder*)self;
978 ctx->m_glDeleteShader_enc(self,shader);
979 ctx->m_shared->unrefShaderData(shader);
980}
981
982void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
983{
984 GL2Encoder *ctx = (GL2Encoder*)self;
985 ctx->m_glAttachShader_enc(self, program, shader);
986 ctx->m_shared->attachShader(program, shader);
987}
988
989void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
990{
991 GL2Encoder *ctx = (GL2Encoder*)self;
992 ctx->m_glDetachShader_enc(self, program, shader);
993 ctx->m_shared->detachShader(program, shader);
994}
995
996int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
997{
998 if (!name) return -1;
999
1000 GL2Encoder *ctx = (GL2Encoder*)self;
1001
1002 // if we need the uniform location WAR
1003 // parse array index from the end of the name string
1004 int arrIndex = 0;
1005 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1006 if (needLocationWAR) {
1007 int namelen = strlen(name);
1008 if (name[namelen-1] == ']') {
1009 char *brace = strrchr(name,'[');
1010 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1011 return -1;
1012 }
1013
1014 }
1015 }
1016
1017 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1018 if (hostLoc >= 0 && needLocationWAR) {
1019 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1020 }
1021 return hostLoc;
1022}
1023
1024bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1025{
1026 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1027 return false;
1028
1029 m_state->setActiveTextureUnit(texUnit);
1030
1031 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1032 if (newTarget != oldTarget) {
1033 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1034 m_state->disableTextureTarget(GL_TEXTURE_2D);
1035 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1036 } else {
1037 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1038 m_state->enableTextureTarget(GL_TEXTURE_2D);
1039 }
1040 m_glActiveTexture_enc(this, texUnit);
1041 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1042 m_state->getBoundTexture(newTarget));
1043 return true;
1044 }
1045
1046 return false;
1047}
1048
1049void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1050{
1051 GL2Encoder *ctx = (GL2Encoder*)self;
1052 GLClientState* state = ctx->m_state;
1053 GLSharedGroupPtr shared = ctx->m_shared;
1054
1055 ctx->m_glUseProgram_enc(self, program);
1056 ctx->m_state->setCurrentProgram(program);
1057
1058 GLenum origActiveTexture = state->getActiveTextureUnit();
1059 GLenum hostActiveTexture = origActiveTexture;
1060 GLint samplerIdx = -1;
1061 GLint samplerVal;
1062 GLenum samplerTarget;
1063 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1064 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1065 continue;
1066 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
1067 samplerTarget))
1068 {
1069 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1070 }
1071 }
1072 state->setActiveTextureUnit(origActiveTexture);
1073 if (hostActiveTexture != origActiveTexture) {
1074 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1075 }
1076}
1077
1078void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1079{
1080 GL2Encoder *ctx = (GL2Encoder*)self;
1081 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1082 ctx->m_glUniform1f_enc(self, hostLoc, x);
1083}
1084
1085void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1086{
1087 GL2Encoder *ctx = (GL2Encoder*)self;
1088 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1089 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1090}
1091
1092void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1093{
1094 GL2Encoder *ctx = (GL2Encoder*)self;
1095 GLClientState* state = ctx->m_state;
1096 GLSharedGroupPtr shared = ctx->m_shared;
1097
1098 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1099 ctx->m_glUniform1i_enc(self, hostLoc, x);
1100
1101 GLenum target;
1102 if (shared->setSamplerUniform(state->currentProgram(), location, x, &target)) {
1103 GLenum origActiveTexture = state->getActiveTextureUnit();
1104 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1105 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1106 }
1107 state->setActiveTextureUnit(origActiveTexture);
1108 }
1109}
1110
1111void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1112{
1113 GL2Encoder *ctx = (GL2Encoder*)self;
1114 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1115 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1116}
1117
1118void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1119{
1120 GL2Encoder *ctx = (GL2Encoder*)self;
1121 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1122 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1123}
1124
1125void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1126{
1127 GL2Encoder *ctx = (GL2Encoder*)self;
1128 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1129 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1130}
1131
1132void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1133{
1134 GL2Encoder *ctx = (GL2Encoder*)self;
1135 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1136 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1137}
1138
1139void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1140{
1141 GL2Encoder *ctx = (GL2Encoder*)self;
1142 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1143 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1144}
1145
1146void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1147{
1148 GL2Encoder *ctx = (GL2Encoder*)self;
1149 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1150 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1151}
1152
1153void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1154{
1155 GL2Encoder *ctx = (GL2Encoder*)self;
1156 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1157 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1158}
1159
1160void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1161{
1162 GL2Encoder *ctx = (GL2Encoder*)self;
1163 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1164 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1165}
1166
1167void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1168{
1169 GL2Encoder *ctx = (GL2Encoder*)self;
1170 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1171 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1172}
1173
1174void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1175{
1176 GL2Encoder *ctx = (GL2Encoder*)self;
1177 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1178 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1179}
1180
1181void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1182{
1183 GL2Encoder *ctx = (GL2Encoder*)self;
1184 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1185 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1186}
1187
1188void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1189{
1190 GL2Encoder *ctx = (GL2Encoder*)self;
1191 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1192 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1193}
1194
1195void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1196{
1197 GL2Encoder *ctx = (GL2Encoder*)self;
1198 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1199 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1200}
1201
1202void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1203{
1204 GL2Encoder *ctx = (GL2Encoder*)self;
1205 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1206 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1207}
1208
1209void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1210{
1211 GL2Encoder *ctx = (GL2Encoder*)self;
1212 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1213 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1214}
1215
1216void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1217{
1218 GL2Encoder *ctx = (GL2Encoder*)self;
1219 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
1220 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1221}
1222
1223void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1224{
1225 GL2Encoder* ctx = (GL2Encoder*)self;
1226 GLClientState* state = ctx->m_state;
1227 GLenum err;
1228
1229 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1230
1231 ctx->m_glActiveTexture_enc(ctx, texture);
1232}
1233
1234void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1235{
1236 GL2Encoder* ctx = (GL2Encoder*)self;
1237 GLClientState* state = ctx->m_state;
1238 GLenum err;
1239 GLboolean firstUse;
1240
1241 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1242
1243 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1244 ctx->m_glBindTexture_enc(ctx, target, texture);
1245 return;
1246 }
1247
1248 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1249
1250 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1251 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1252 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1253 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1254 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1255 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1256 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1257 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1258
1259 if (target != priorityTarget) {
1260 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1261 state->getBoundTexture(GL_TEXTURE_2D));
1262 }
1263 }
1264
1265 if (target == priorityTarget) {
1266 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1267 }
1268}
1269
1270void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1271{
1272 GL2Encoder* ctx = (GL2Encoder*)self;
1273 GLClientState* state = ctx->m_state;
1274
1275 state->deleteTextures(n, textures);
1276 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1277}
1278
1279void GL2Encoder::s_glGetTexParameterfv(void* self,
1280 GLenum target, GLenum pname, GLfloat* params)
1281{
1282 GL2Encoder* ctx = (GL2Encoder*)self;
1283 const GLClientState* state = ctx->m_state;
1284
1285 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1286 ctx->override2DTextureTarget(target);
1287 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
1288 ctx->restore2DTextureTarget();
1289 } else {
1290 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1291 }
1292}
1293
1294void GL2Encoder::s_glGetTexParameteriv(void* self,
1295 GLenum target, GLenum pname, GLint* params)
1296{
1297 GL2Encoder* ctx = (GL2Encoder*)self;
1298 const GLClientState* state = ctx->m_state;
1299
1300 switch (pname) {
1301 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1302 *params = 1;
1303 break;
1304
1305 default:
1306 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1307 ctx->override2DTextureTarget(target);
1308 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
1309 ctx->restore2DTextureTarget();
1310 } else {
1311 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1312 }
1313 break;
1314 }
1315}
1316
1317static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1318{
1319 switch (pname) {
1320 case GL_TEXTURE_MIN_FILTER:
1321 case GL_TEXTURE_MAG_FILTER:
1322 return param == GL_NEAREST || param == GL_LINEAR;
1323
1324 case GL_TEXTURE_WRAP_S:
1325 case GL_TEXTURE_WRAP_T:
1326 return param == GL_CLAMP_TO_EDGE;
1327
1328 default:
1329 return true;
1330 }
1331}
1332
1333void GL2Encoder::s_glTexParameterf(void* self,
1334 GLenum target, GLenum pname, GLfloat param)
1335{
1336 GL2Encoder* ctx = (GL2Encoder*)self;
1337 const GLClientState* state = ctx->m_state;
1338
1339 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1340 !isValidTextureExternalParam(pname, (GLenum)param)),
1341 GL_INVALID_ENUM);
1342
1343 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1344 ctx->override2DTextureTarget(target);
1345 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
1346 ctx->restore2DTextureTarget();
1347 } else {
1348 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1349 }
1350}
1351
1352void GL2Encoder::s_glTexParameterfv(void* self,
1353 GLenum target, GLenum pname, const GLfloat* params)
1354{
1355 GL2Encoder* ctx = (GL2Encoder*)self;
1356 const GLClientState* state = ctx->m_state;
1357
1358 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1359 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1360 GL_INVALID_ENUM);
1361
1362 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1363 ctx->override2DTextureTarget(target);
1364 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
1365 ctx->restore2DTextureTarget();
1366 } else {
1367 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1368 }
1369}
1370
1371void GL2Encoder::s_glTexParameteri(void* self,
1372 GLenum target, GLenum pname, GLint param)
1373{
1374 GL2Encoder* ctx = (GL2Encoder*)self;
1375 const GLClientState* state = ctx->m_state;
1376
1377 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1378 !isValidTextureExternalParam(pname, (GLenum)param)),
1379 GL_INVALID_ENUM);
1380
1381 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1382 ctx->override2DTextureTarget(target);
1383 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
1384 ctx->restore2DTextureTarget();
1385 } else {
1386 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
1387 }
1388}
1389
bohu26a92982014-11-25 16:50:37 -08001390void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
1391 GLint internalformat, GLsizei width, GLsizei height, GLint border,
1392 GLenum format, GLenum type, const GLvoid* pixels)
1393{
1394 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07001395 GLClientState* state = ctx->m_state;
bohu26a92982014-11-25 16:50:37 -08001396 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1397 ctx->override2DTextureTarget(target);
Lingfeng Yang69066602016-04-12 09:29:11 -07001398 state->setBoundTextureInternalFormat(target, internalformat);
1399 state->setBoundTextureFormat(target, format);
1400 state->setBoundTextureType(target, type);
1401
bohu26a92982014-11-25 16:50:37 -08001402 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1403 height, border, format, type, pixels);
1404 ctx->restore2DTextureTarget();
1405 } else {
1406 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
1407 height, border, format, type, pixels);
1408 }
1409}
1410
1411
keunyoungb85b2752013-03-08 12:28:03 -08001412void GL2Encoder::s_glTexParameteriv(void* self,
1413 GLenum target, GLenum pname, const GLint* params)
1414{
1415 GL2Encoder* ctx = (GL2Encoder*)self;
1416 const GLClientState* state = ctx->m_state;
1417
1418 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1419 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1420 GL_INVALID_ENUM);
1421
1422 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1423 ctx->override2DTextureTarget(target);
1424 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
1425 ctx->restore2DTextureTarget();
1426 } else {
1427 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
1428 }
1429}
1430
1431void GL2Encoder::override2DTextureTarget(GLenum target)
1432{
1433 if ((target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
1434 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)) {
1435 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1436 m_state->getBoundTexture(target));
1437 }
1438}
1439
1440void GL2Encoder::restore2DTextureTarget()
1441{
1442 GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1443 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1444 m_state->getBoundTexture(priorityTarget));
1445}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07001446
1447void GL2Encoder::s_glGenRenderbuffers(void* self,
1448 GLsizei n, GLuint* renderbuffers) {
1449 GL2Encoder* ctx = (GL2Encoder*)self;
1450 GLClientState* state = ctx->m_state;
1451
1452 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1453
1454 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
1455 state->addRenderbuffers(n, renderbuffers);
1456}
1457
1458void GL2Encoder::s_glDeleteRenderbuffers(void* self,
1459 GLsizei n, const GLuint* renderbuffers) {
1460 GL2Encoder* ctx = (GL2Encoder*)self;
1461 GLClientState* state = ctx->m_state;
1462
1463 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1464
1465 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
1466 state->removeRenderbuffers(n, renderbuffers);
1467}
1468
1469void GL2Encoder::s_glBindRenderbuffer(void* self,
1470 GLenum target, GLuint renderbuffer) {
1471 GL2Encoder* ctx = (GL2Encoder*)self;
1472 GLClientState* state = ctx->m_state;
1473
1474 SET_ERROR_IF((target != GL_RENDERBUFFER),
1475 GL_INVALID_ENUM);
1476
1477 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
1478 state->bindRenderbuffer(target, renderbuffer);
1479}
1480
Lingfeng Yang69066602016-04-12 09:29:11 -07001481void GL2Encoder::s_glRenderbufferStorage(void* self,
1482 GLenum target, GLenum internalformat,
1483 GLsizei width, GLsizei height) {
1484 GL2Encoder* ctx = (GL2Encoder*) self;
1485 GLClientState* state = ctx->m_state;
1486
1487 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
1488 switch (internalformat) {
1489 // Funny internal formats
1490 // that will cause an incomplete framebuffer
1491 // attachment error. For dEQP,
1492 // we can also just abort early here in
1493 // RenderbufferStorage with a GL_INVALID_ENUM.
1494 case GL_DEPTH_COMPONENT32F:
1495 case GL_R8:
1496 case GL_R8UI:
1497 case GL_R8I:
1498 case GL_R16UI:
1499 case GL_R16I:
1500 case GL_R32UI:
1501 case GL_R32I:
1502 case GL_RG8:
1503 case GL_RG8UI:
1504 case GL_RG8I:
1505 case GL_RG16UI:
1506 case GL_RG16I:
1507 case GL_RG32UI:
1508 case GL_RG32I:
1509 case GL_SRGB8_ALPHA8:
Lingfeng Yang69066602016-04-12 09:29:11 -07001510 case GL_RGBA8UI:
1511 case GL_RGBA8I:
1512 case GL_RGB10_A2UI:
1513 case GL_RGBA16UI:
1514 case GL_RGBA16I:
1515 case GL_RGBA32I:
1516 case GL_RGBA32UI:
1517 case GL_R11F_G11F_B10F:
1518 case GL_R32F:
1519 case GL_RG32F:
1520 case GL_RGB32F:
1521 case GL_RGBA32F:
1522 SET_ERROR_IF(true, GL_INVALID_ENUM);
1523 break;
1524 // These 4 formats are still not OK,
1525 // but dEQP expects GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT or
1526 // GL_FRAMEBUFFER_UNSUPPORTED,
1527 // not a GL_INVALID_ENUM from earlier on.
1528 // So let's forward these to the rest of
1529 // FBO initialization
1530 case GL_R16F:
1531 case GL_RG16F:
1532 case GL_RGB16F:
1533 case GL_RGBA16F:
Yahan Zhouafbb4f82016-05-11 10:45:31 -07001534 // dEQP expects GL_FRAMEBUFFER_UNSUPPORTED or GL_FRAMEBUFFER_COMPLETE
1535 // for this format
1536 case GL_RGB10_A2:
Lingfeng Yang69066602016-04-12 09:29:11 -07001537 // These formats are OK
1538 case GL_DEPTH_COMPONENT16:
1539 case GL_DEPTH_COMPONENT24:
1540 case GL_DEPTH_COMPONENT32_OES:
1541 case GL_RGBA4:
1542 case GL_RGB5_A1:
1543 case GL_RGB565:
1544 case GL_RGB8_OES:
1545 case GL_RGBA8_OES:
1546 case GL_STENCIL_INDEX8:
1547 case GL_DEPTH32F_STENCIL8:
1548 case GL_DEPTH24_STENCIL8_OES:
1549 break;
1550 // Everything else: still not OK,
1551 // and they need the GL_INVALID_ENUM
1552 default:
1553 SET_ERROR_IF(true, GL_INVALID_ENUM);
1554 }
1555
1556 state->setBoundRenderbufferFormat(internalformat);
1557 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
1558 width, height);
1559}
1560
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07001561void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
1562 GLenum target, GLenum attachment,
1563 GLenum renderbuffertarget, GLuint renderbuffer) {
1564 GL2Encoder* ctx = (GL2Encoder*)self;
1565 GLClientState* state = ctx->m_state;
1566
1567 state->attachRbo(attachment, renderbuffer);
1568
1569 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
1570}
1571
1572void GL2Encoder::s_glGenFramebuffers(void* self,
1573 GLsizei n, GLuint* framebuffers) {
1574 GL2Encoder* ctx = (GL2Encoder*)self;
1575 GLClientState* state = ctx->m_state;
1576
1577 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1578
1579 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
1580 state->addFramebuffers(n, framebuffers);
1581}
1582
1583void GL2Encoder::s_glDeleteFramebuffers(void* self,
1584 GLsizei n, const GLuint* framebuffers) {
1585 GL2Encoder* ctx = (GL2Encoder*)self;
1586 GLClientState* state = ctx->m_state;
1587
1588 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
1589
1590 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
1591 state->removeFramebuffers(n, framebuffers);
1592}
1593
1594void GL2Encoder::s_glBindFramebuffer(void* self,
1595 GLenum target, GLuint framebuffer) {
1596 GL2Encoder* ctx = (GL2Encoder*)self;
1597 GLClientState* state = ctx->m_state;
1598
1599 SET_ERROR_IF((target != GL_FRAMEBUFFER),
1600 GL_INVALID_ENUM);
1601
1602 state->bindFramebuffer(target, framebuffer);
1603
1604 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
1605}
1606
1607void GL2Encoder::s_glFramebufferTexture2D(void* self,
1608 GLenum target, GLenum attachment,
1609 GLenum textarget, GLuint texture, GLint level) {
1610 GL2Encoder* ctx = (GL2Encoder*)self;
1611 GLClientState* state = ctx->m_state;
1612
1613 state->attachTextureObject(attachment, texture);
1614
1615 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
1616}
1617
1618void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
1619 GLenum target, GLenum attachment,
1620 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
1621 GL2Encoder* ctx = (GL2Encoder*)self;
1622 GLClientState* state = ctx->m_state;
1623
1624 state->attachTextureObject(attachment, texture);
1625
1626 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
1627}
1628
1629void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
1630 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
1631 GL2Encoder* ctx = (GL2Encoder*)self;
1632 const GLClientState* state = ctx->m_state;
1633
1634 SET_ERROR_IF(state->boundFramebuffer() == 0,
1635 GL_INVALID_OPERATION);
1636 SET_ERROR_IF((pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) &&
1637 (!state->attachmentHasObject(attachment)),
1638 GL_INVALID_ENUM);
1639
1640 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
1641}
Lingfeng Yang69066602016-04-12 09:29:11 -07001642
1643bool GL2Encoder::isCompleteFbo(const GLClientState* state,
1644 GLenum attachment) const {
1645 FboFormatInfo fbo_format_info;
1646 state->getBoundFramebufferFormat(attachment, &fbo_format_info);
1647
1648 bool res;
1649 switch (fbo_format_info.type) {
1650 case FBO_ATTACHMENT_RENDERBUFFER:
1651 switch (fbo_format_info.rb_format) {
1652 case GL_R16F:
1653 case GL_RG16F:
1654 case GL_RGB16F:
1655 case GL_RGBA16F:
1656 res = false;
1657 break;
1658 case GL_STENCIL_INDEX8:
1659 if (attachment == GL_STENCIL_ATTACHMENT) {
1660 res = true;
1661 } else {
1662 res = false;
1663 }
1664 break;
1665 default:
1666 res = true;
1667 }
1668 break;
1669 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001670 switch (fbo_format_info.tex_internalformat) {
1671 case GL_RED:
1672 case GL_RG:
1673 case GL_R16F:
1674 case GL_RG16F:
1675 case GL_RGBA16F:
1676 case GL_RGB16F:
1677 case GL_R11F_G11F_B10F:
1678 res = false;
1679 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07001680 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001681 case GL_RGB:
1682 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07001683 switch (fbo_format_info.tex_type) {
1684 case GL_FLOAT:
1685 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001686 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07001687 res = false;
1688 break;
1689 default:
1690 res = true;
1691 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07001692 break;
1693 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07001694 res = true;
1695 }
1696 break;
1697 case FBO_ATTACHMENT_NONE:
1698 res = true;
1699 break;
1700 default:
1701 res = true;
1702 }
1703 return res;
1704}
1705
1706GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
1707 GL2Encoder* ctx = (GL2Encoder*)self;
1708 GLClientState* state = ctx->m_state;
1709
1710 bool complete = ctx->isCompleteFbo(state, GL_COLOR_ATTACHMENT0) &&
1711 ctx->isCompleteFbo(state, GL_DEPTH_ATTACHMENT) &&
1712 ctx->isCompleteFbo(state, GL_STENCIL_ATTACHMENT);
1713 if (!complete) {
1714 state->setCheckFramebufferStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
1715 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1716 } else {
1717 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
1718 state->setCheckFramebufferStatus(host_checkstatus);
1719 return host_checkstatus;
1720 }
1721}