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