blob: 87a1225bf8c89d25e94b6aa3ee0be8b55565d7af [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"
Lingfeng Yang46153ab2017-01-09 13:37:22 -080018#include "GLESv2Validation.h"
19
20#include <string>
21#include <map>
22
keunyoungb85b2752013-03-08 12:28:03 -080023#include <assert.h>
24#include <ctype.h>
25
Lingfeng Yang69066602016-04-12 09:29:11 -070026#include <GLES2/gl2.h>
27#include <GLES2/gl2ext.h>
28#include <GLES2/gl2platform.h>
29
30#include <GLES3/gl3.h>
Lingfeng Yang46153ab2017-01-09 13:37:22 -080031#include <GLES3/gl31.h>
Lingfeng Yang69066602016-04-12 09:29:11 -070032
keunyoungb85b2752013-03-08 12:28:03 -080033#ifndef MIN
34#define MIN(a, b) ((a) < (b) ? (a) : (b))
35#endif
36
37static GLubyte *gVendorString= (GLubyte *) "Android";
Lingfeng Yang46153ab2017-01-09 13:37:22 -080038static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 3.0";
39static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 3.0";
Nicolas Capensfe2d51a2015-11-20 15:10:09 -050040static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external ";
keunyoungb85b2752013-03-08 12:28:03 -080041
Lingfeng Yang07289902017-01-27 12:26:19 -080042#define SET_ERROR_IF(condition, err) if((condition)) { \
keunyoungb85b2752013-03-08 12:28:03 -080043 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
Lingfeng Yang07289902017-01-27 12:26:19 -080044 ctx->setError(err); \
45 return; \
keunyoungb85b2752013-03-08 12:28:03 -080046 }
47
Lingfeng Yang07289902017-01-27 12:26:19 -080048#define SET_ERROR_WITH_MESSAGE_IF(condition, err, generator, genargs) if ((condition)) { \
49 std::string msg = generator genargs; \
50 ALOGE("%s:%s:%d GL error 0x%x\n" \
51 "Info: %s\n", __FILE__, __FUNCTION__, __LINE__, err, msg.c_str()); \
52 ctx->setError(err); \
53 return; \
54 } \
keunyoungb85b2752013-03-08 12:28:03 -080055
Lingfeng Yang07289902017-01-27 12:26:19 -080056#define RET_AND_SET_ERROR_IF(condition, err, ret) if((condition)) { \
keunyoungb85b2752013-03-08 12:28:03 -080057 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
Lingfeng Yang07289902017-01-27 12:26:19 -080058 ctx->setError(err); \
59 return ret; \
60 } \
keunyoungb85b2752013-03-08 12:28:03 -080061
Lingfeng Yang07289902017-01-27 12:26:19 -080062#define RET_AND_SET_ERROR_WITH_MESSAGE_IF(condition, err, ret, generator, genargs) if((condition)) { \
63 std::string msg = generator genargs; \
64 ALOGE("%s:%s:%d GL error 0x%x\n" \
65 "Info: %s\n", __FILE__, __FUNCTION__, __LINE__, err, msg.c_str()); \
66 ctx->setError(err); \
67 return ret; \
68 } \
keunyoungb85b2752013-03-08 12:28:03 -080069
Yahan Zhoub7f09082016-03-10 11:45:02 -080070GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
71 : gl2_encoder_context_t(stream, protocol)
keunyoungb85b2752013-03-08 12:28:03 -080072{
Lingfeng Yange6556dc2017-01-09 12:04:12 -080073 m_currMajorVersion = 2;
74 m_currMinorVersion = 0;
keunyoungb85b2752013-03-08 12:28:03 -080075 m_initialized = false;
Lingfeng Yange980c7a2018-01-12 14:50:18 -080076 m_noHostError = false;
keunyoungb85b2752013-03-08 12:28:03 -080077 m_state = NULL;
78 m_error = GL_NO_ERROR;
79 m_num_compressedTextureFormats = 0;
Lizhe Liue41f4ef2015-05-27 11:13:23 +080080 m_max_cubeMapTextureSize = 0;
81 m_max_renderBufferSize = 0;
82 m_max_textureSize = 0;
Lingfeng Yang46153ab2017-01-09 13:37:22 -080083 m_max_3d_textureSize = 0;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -080084 m_max_vertexAttribStride = 0;
keunyoungb85b2752013-03-08 12:28:03 -080085 m_compressedTextureFormats = NULL;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010086
Lingfeng Yang46153ab2017-01-09 13:37:22 -080087 m_ssbo_offset_align = 0;
88 m_ubo_offset_align = 0;
89
Lingfeng Yangde51dfb2016-10-17 22:48:59 -070090 m_drawCallFlushCount = 0;
91 m_primitiveRestartEnabled = false;
92 m_primitiveRestartIndex = 0;
93
Lingfeng Yang07289902017-01-27 12:26:19 -080094 // overrides
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010095#define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name
Lingfeng Yange6556dc2017-01-09 12:04:12 -080096#define OVERRIDE_CUSTOM(name) this-> name = &s_##name
97#define OVERRIDEWITH(name, target) do { \
98 m_##target##_enc = this-> target; \
99 this-> target = &s_##name; \
100} while(0)
101#define OVERRIDEOES(name) OVERRIDEWITH(name, name##OES)
bohu56bf82f2014-10-17 15:35:48 -0700102
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100103 OVERRIDE(glFlush);
104 OVERRIDE(glPixelStorei);
105 OVERRIDE(glGetString);
106 OVERRIDE(glBindBuffer);
107 OVERRIDE(glBufferData);
108 OVERRIDE(glBufferSubData);
109 OVERRIDE(glDeleteBuffers);
110 OVERRIDE(glDrawArrays);
111 OVERRIDE(glDrawElements);
112 OVERRIDE(glGetIntegerv);
113 OVERRIDE(glGetFloatv);
114 OVERRIDE(glGetBooleanv);
115 OVERRIDE(glVertexAttribPointer);
116 OVERRIDE(glEnableVertexAttribArray);
117 OVERRIDE(glDisableVertexAttribArray);
118 OVERRIDE(glGetVertexAttribiv);
119 OVERRIDE(glGetVertexAttribfv);
120 OVERRIDE(glGetVertexAttribPointerv);
keunyoungb85b2752013-03-08 12:28:03 -0800121
Bo Hu73568cd2015-01-20 16:29:50 -0800122 this->glShaderBinary = &s_glShaderBinary;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100123 this->glShaderSource = &s_glShaderSource;
124 this->glFinish = &s_glFinish;
keunyoungb85b2752013-03-08 12:28:03 -0800125
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100126 OVERRIDE(glGetError);
127 OVERRIDE(glLinkProgram);
128 OVERRIDE(glDeleteProgram);
129 OVERRIDE(glGetUniformiv);
130 OVERRIDE(glGetUniformfv);
131 OVERRIDE(glCreateProgram);
132 OVERRIDE(glCreateShader);
133 OVERRIDE(glDeleteShader);
134 OVERRIDE(glAttachShader);
135 OVERRIDE(glDetachShader);
136 OVERRIDE(glGetAttachedShaders);
137 OVERRIDE(glGetShaderSource);
138 OVERRIDE(glGetShaderInfoLog);
139 OVERRIDE(glGetProgramInfoLog);
140
141 OVERRIDE(glGetUniformLocation);
142 OVERRIDE(glUseProgram);
143
144 OVERRIDE(glUniform1f);
145 OVERRIDE(glUniform1fv);
146 OVERRIDE(glUniform1i);
147 OVERRIDE(glUniform1iv);
148 OVERRIDE(glUniform2f);
149 OVERRIDE(glUniform2fv);
150 OVERRIDE(glUniform2i);
151 OVERRIDE(glUniform2iv);
152 OVERRIDE(glUniform3f);
153 OVERRIDE(glUniform3fv);
154 OVERRIDE(glUniform3i);
155 OVERRIDE(glUniform3iv);
156 OVERRIDE(glUniform4f);
157 OVERRIDE(glUniform4fv);
158 OVERRIDE(glUniform4i);
159 OVERRIDE(glUniform4iv);
160 OVERRIDE(glUniformMatrix2fv);
161 OVERRIDE(glUniformMatrix3fv);
162 OVERRIDE(glUniformMatrix4fv);
163
164 OVERRIDE(glActiveTexture);
165 OVERRIDE(glBindTexture);
166 OVERRIDE(glDeleteTextures);
167 OVERRIDE(glGetTexParameterfv);
168 OVERRIDE(glGetTexParameteriv);
169 OVERRIDE(glTexParameterf);
170 OVERRIDE(glTexParameterfv);
171 OVERRIDE(glTexParameteri);
172 OVERRIDE(glTexParameteriv);
bohu26a92982014-11-25 16:50:37 -0800173 OVERRIDE(glTexImage2D);
Yahan Zhou2a208292016-06-22 15:36:04 -0700174 OVERRIDE(glTexSubImage2D);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -0700175 OVERRIDE(glCopyTexImage2D);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700176
177 OVERRIDE(glGenRenderbuffers);
178 OVERRIDE(glDeleteRenderbuffers);
179 OVERRIDE(glBindRenderbuffer);
Lingfeng Yang69066602016-04-12 09:29:11 -0700180 OVERRIDE(glRenderbufferStorage);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700181 OVERRIDE(glFramebufferRenderbuffer);
182
183 OVERRIDE(glGenFramebuffers);
184 OVERRIDE(glDeleteFramebuffers);
185 OVERRIDE(glBindFramebuffer);
186 OVERRIDE(glFramebufferTexture2D);
187 OVERRIDE(glFramebufferTexture3DOES);
188 OVERRIDE(glGetFramebufferAttachmentParameteriv);
Lingfeng Yang69066602016-04-12 09:29:11 -0700189
190 OVERRIDE(glCheckFramebufferStatus);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800191
192 OVERRIDE(glGenVertexArrays);
193 OVERRIDE(glDeleteVertexArrays);
194 OVERRIDE(glBindVertexArray);
195 OVERRIDEOES(glGenVertexArrays);
196 OVERRIDEOES(glDeleteVertexArrays);
197 OVERRIDEOES(glBindVertexArray);
198
Lingfeng Yangfb3d2bb2017-09-07 15:02:04 -0700199 OVERRIDE_CUSTOM(glMapBufferOES);
200 OVERRIDE_CUSTOM(glUnmapBufferOES);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800201 OVERRIDE_CUSTOM(glMapBufferRange);
202 OVERRIDE_CUSTOM(glUnmapBuffer);
203 OVERRIDE_CUSTOM(glFlushMappedBufferRange);
204
205 OVERRIDE(glCompressedTexImage2D);
206 OVERRIDE(glCompressedTexSubImage2D);
207
208 OVERRIDE(glBindBufferRange);
209 OVERRIDE(glBindBufferBase);
210
211 OVERRIDE(glCopyBufferSubData);
212
213 OVERRIDE(glGetBufferParameteriv);
214 OVERRIDE(glGetBufferParameteri64v);
215 OVERRIDE(glGetBufferPointerv);
216
217 OVERRIDE_CUSTOM(glGetUniformIndices);
218
219 OVERRIDE(glUniform1ui);
220 OVERRIDE(glUniform2ui);
221 OVERRIDE(glUniform3ui);
222 OVERRIDE(glUniform4ui);
223 OVERRIDE(glUniform1uiv);
224 OVERRIDE(glUniform2uiv);
225 OVERRIDE(glUniform3uiv);
226 OVERRIDE(glUniform4uiv);
227 OVERRIDE(glUniformMatrix2x3fv);
228 OVERRIDE(glUniformMatrix3x2fv);
229 OVERRIDE(glUniformMatrix2x4fv);
230 OVERRIDE(glUniformMatrix4x2fv);
231 OVERRIDE(glUniformMatrix3x4fv);
232 OVERRIDE(glUniformMatrix4x3fv);
233
234 OVERRIDE(glGetUniformuiv);
235 OVERRIDE(glGetActiveUniformBlockiv);
236
237 OVERRIDE(glGetVertexAttribIiv);
238 OVERRIDE(glGetVertexAttribIuiv);
239
240 OVERRIDE_CUSTOM(glVertexAttribIPointer);
241
242 OVERRIDE(glVertexAttribDivisor);
243
244 OVERRIDE(glRenderbufferStorageMultisample);
245 OVERRIDE(glDrawBuffers);
246 OVERRIDE(glReadBuffer);
247 OVERRIDE(glFramebufferTextureLayer);
248 OVERRIDE(glTexStorage2D);
249
250 OVERRIDE_CUSTOM(glTransformFeedbackVaryings);
251 OVERRIDE(glBeginTransformFeedback);
252 OVERRIDE(glEndTransformFeedback);
253 OVERRIDE(glPauseTransformFeedback);
254 OVERRIDE(glResumeTransformFeedback);
255
256 OVERRIDE(glTexImage3D);
257 OVERRIDE(glTexSubImage3D);
258 OVERRIDE(glTexStorage3D);
259 OVERRIDE(glCompressedTexImage3D);
260 OVERRIDE(glCompressedTexSubImage3D);
261
262 OVERRIDE(glDrawArraysInstanced);
263 OVERRIDE_CUSTOM(glDrawElementsInstanced);
264 OVERRIDE_CUSTOM(glDrawRangeElements);
265
266 OVERRIDE_CUSTOM(glGetStringi);
267 OVERRIDE(glGetProgramBinary);
268 OVERRIDE(glReadPixels);
269
270 OVERRIDE(glEnable);
271 OVERRIDE(glDisable);
272 OVERRIDE(glClearBufferiv);
273 OVERRIDE(glClearBufferuiv);
274 OVERRIDE(glClearBufferfv);
275 OVERRIDE(glBlitFramebuffer);
276 OVERRIDE_CUSTOM(glGetInternalformativ);
277
278 OVERRIDE(glGenerateMipmap);
279
280 OVERRIDE(glBindSampler);
281
Lingfeng Yangf000ab42017-01-11 18:31:38 -0800282 OVERRIDE_CUSTOM(glFenceSync);
283 OVERRIDE_CUSTOM(glClientWaitSync);
284 OVERRIDE_CUSTOM(glWaitSync);
285 OVERRIDE_CUSTOM(glDeleteSync);
286 OVERRIDE_CUSTOM(glIsSync);
287 OVERRIDE_CUSTOM(glGetSynciv);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800288
289 OVERRIDE(glGetIntegeri_v);
290 OVERRIDE(glGetInteger64i_v);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700291 OVERRIDE(glGetInteger64v);
292 OVERRIDE(glGetBooleani_v);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800293
294 OVERRIDE(glGetShaderiv);
295
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800296 OVERRIDE(glActiveShaderProgram);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800297 OVERRIDE_CUSTOM(glCreateShaderProgramv);
298 OVERRIDE(glProgramUniform1f);
299 OVERRIDE(glProgramUniform1fv);
300 OVERRIDE(glProgramUniform1i);
301 OVERRIDE(glProgramUniform1iv);
302 OVERRIDE(glProgramUniform1ui);
303 OVERRIDE(glProgramUniform1uiv);
304 OVERRIDE(glProgramUniform2f);
305 OVERRIDE(glProgramUniform2fv);
306 OVERRIDE(glProgramUniform2i);
307 OVERRIDE(glProgramUniform2iv);
308 OVERRIDE(glProgramUniform2ui);
309 OVERRIDE(glProgramUniform2uiv);
310 OVERRIDE(glProgramUniform3f);
311 OVERRIDE(glProgramUniform3fv);
312 OVERRIDE(glProgramUniform3i);
313 OVERRIDE(glProgramUniform3iv);
314 OVERRIDE(glProgramUniform3ui);
315 OVERRIDE(glProgramUniform3uiv);
316 OVERRIDE(glProgramUniform4f);
317 OVERRIDE(glProgramUniform4fv);
318 OVERRIDE(glProgramUniform4i);
319 OVERRIDE(glProgramUniform4iv);
320 OVERRIDE(glProgramUniform4ui);
321 OVERRIDE(glProgramUniform4uiv);
322 OVERRIDE(glProgramUniformMatrix2fv);
323 OVERRIDE(glProgramUniformMatrix2x3fv);
324 OVERRIDE(glProgramUniformMatrix2x4fv);
325 OVERRIDE(glProgramUniformMatrix3fv);
326 OVERRIDE(glProgramUniformMatrix3x2fv);
327 OVERRIDE(glProgramUniformMatrix3x4fv);
328 OVERRIDE(glProgramUniformMatrix4fv);
329 OVERRIDE(glProgramUniformMatrix4x2fv);
330 OVERRIDE(glProgramUniformMatrix4x3fv);
331
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800332 OVERRIDE(glProgramParameteri);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800333 OVERRIDE(glUseProgramStages);
334 OVERRIDE(glBindProgramPipeline);
335
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800336 OVERRIDE(glGetProgramResourceiv);
337 OVERRIDE(glGetProgramResourceIndex);
338 OVERRIDE(glGetProgramResourceLocation);
339 OVERRIDE(glGetProgramResourceName);
340 OVERRIDE(glGetProgramPipelineInfoLog);
341
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800342 OVERRIDE(glVertexAttribFormat);
343 OVERRIDE(glVertexAttribIFormat);
344 OVERRIDE(glVertexBindingDivisor);
345 OVERRIDE(glVertexAttribBinding);
346 OVERRIDE(glBindVertexBuffer);
347
348 OVERRIDE_CUSTOM(glDrawArraysIndirect);
349 OVERRIDE_CUSTOM(glDrawElementsIndirect);
350
351 OVERRIDE(glTexStorage2DMultisample);
keunyoungb85b2752013-03-08 12:28:03 -0800352}
353
354GL2Encoder::~GL2Encoder()
355{
356 delete m_compressedTextureFormats;
357}
358
359GLenum GL2Encoder::s_glGetError(void * self)
360{
361 GL2Encoder *ctx = (GL2Encoder *)self;
362 GLenum err = ctx->getError();
363 if(err != GL_NO_ERROR) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700364 ctx->m_glGetError_enc(ctx); // also clear host error
keunyoungb85b2752013-03-08 12:28:03 -0800365 ctx->setError(GL_NO_ERROR);
366 return err;
367 }
368
Lingfeng Yange980c7a2018-01-12 14:50:18 -0800369 if (ctx->m_noHostError) {
370 return GL_NO_ERROR;
371 } else {
372 return ctx->m_glGetError_enc(self);
373 }
Lingfeng Yang80a36332017-07-09 10:58:07 -0700374}
Yahan Zhouae30fe82016-08-10 21:15:45 +0000375
Lingfeng Yang80a36332017-07-09 10:58:07 -0700376class GL2Encoder::ErrorUpdater {
377public:
378 ErrorUpdater(GL2Encoder* ctx) :
379 mCtx(ctx),
380 guest_error(ctx->getError()),
381 host_error(ctx->m_glGetError_enc(ctx)) {
382 // Preserve any existing GL error in the guest:
383 // OpenGL ES 3.0.5 spec:
384 // The command enum GetError( void ); is used to obtain error information.
385 // Each detectable error is assigned a numeric code. When an error is
386 // detected, a flag is set and the code is recorded. Further errors, if
387 // they occur, do not affect this recorded code. When GetError is called,
388 // the code is returned and the flag is cleared, so that a further error
389 // will again record its code. If a call to GetError returns NO_ERROR, then
390 // there has been no detectable error since the last call to GetError (or
391 // since the GL was initialized).
392 if (guest_error == GL_NO_ERROR) {
393 guest_error = host_error;
394 }
395 }
396
397 GLenum getHostErrorAndUpdate() {
398 host_error = mCtx->m_glGetError_enc(mCtx);
399 if (guest_error == GL_NO_ERROR) {
400 guest_error = host_error;
401 }
402 return host_error;
403 }
404
405 void updateGuestErrorState() {
406 mCtx->setError(guest_error);
407 }
408
409private:
410 GL2Encoder* mCtx;
411 GLenum guest_error;
412 GLenum host_error;
413};
414
415template<class T>
416class GL2Encoder::ScopedQueryUpdate {
417public:
418 ScopedQueryUpdate(GL2Encoder* ctx, uint32_t bytes, T* target) :
419 mCtx(ctx),
420 mBuf(bytes, 0),
421 mTarget(target),
422 mErrorUpdater(ctx) {
423 }
424 T* hostStagingBuffer() {
425 return (T*)&mBuf[0];
426 }
427 ~ScopedQueryUpdate() {
428 GLint hostError = mErrorUpdater.getHostErrorAndUpdate();
429 if (hostError == GL_NO_ERROR) {
430 memcpy(mTarget, &mBuf[0], mBuf.size());
431 }
432 mErrorUpdater.updateGuestErrorState();
433 }
434private:
435 GL2Encoder* mCtx;
436 std::vector<char> mBuf;
437 T* mTarget;
438 ErrorUpdater mErrorUpdater;
439};
440
441void GL2Encoder::safe_glGetBooleanv(GLenum param, GLboolean* val) {
442 ScopedQueryUpdate<GLboolean> query(this, glUtilsParamSize(param) * sizeof(GLboolean), val);
443 m_glGetBooleanv_enc(this, param, query.hostStagingBuffer());
444}
445
446void GL2Encoder::safe_glGetFloatv(GLenum param, GLfloat* val) {
447 ScopedQueryUpdate<GLfloat> query(this, glUtilsParamSize(param) * sizeof(GLfloat), val);
448 m_glGetFloatv_enc(this, param, query.hostStagingBuffer());
449}
450
451void GL2Encoder::safe_glGetIntegerv(GLenum param, GLint* val) {
452 ScopedQueryUpdate<GLint> query(this, glUtilsParamSize(param) * sizeof(GLint), val);
453 m_glGetIntegerv_enc(this, param, query.hostStagingBuffer());
454}
455
456void GL2Encoder::safe_glGetInteger64v(GLenum param, GLint64* val) {
457 ScopedQueryUpdate<GLint64> query(this, glUtilsParamSize(param) * sizeof(GLint64), val);
458 m_glGetInteger64v_enc(this, param, query.hostStagingBuffer());
459}
460
461void GL2Encoder::safe_glGetIntegeri_v(GLenum param, GLuint index, GLint* val) {
462 ScopedQueryUpdate<GLint> query(this, sizeof(GLint), val);
463 m_glGetIntegeri_v_enc(this, param, index, query.hostStagingBuffer());
464}
465
466void GL2Encoder::safe_glGetInteger64i_v(GLenum param, GLuint index, GLint64* val) {
467 ScopedQueryUpdate<GLint64> query(this, sizeof(GLint64), val);
468 m_glGetInteger64i_v_enc(this, param, index, query.hostStagingBuffer());
469}
470
471void GL2Encoder::safe_glGetBooleani_v(GLenum param, GLuint index, GLboolean* val) {
472 ScopedQueryUpdate<GLboolean> query(this, sizeof(GLboolean), val);
473 m_glGetBooleani_v_enc(this, param, index, query.hostStagingBuffer());
keunyoungb85b2752013-03-08 12:28:03 -0800474}
475
476void GL2Encoder::s_glFlush(void *self)
477{
478 GL2Encoder *ctx = (GL2Encoder *) self;
479 ctx->m_glFlush_enc(self);
480 ctx->m_stream->flush();
481}
482
483const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
484{
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800485 GL2Encoder *ctx = (GL2Encoder *)self;
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100486
keunyoungb85b2752013-03-08 12:28:03 -0800487 GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800488 RET_AND_SET_ERROR_IF(
489 name != GL_VENDOR &&
490 name != GL_RENDERER &&
491 name != GL_VERSION &&
492 name != GL_EXTENSIONS,
493 GL_INVALID_ENUM,
494 retval);
keunyoungb85b2752013-03-08 12:28:03 -0800495 switch(name) {
496 case GL_VENDOR:
497 retval = gVendorString;
498 break;
499 case GL_RENDERER:
500 retval = gRendererString;
501 break;
502 case GL_VERSION:
503 retval = gVersionString;
504 break;
505 case GL_EXTENSIONS:
506 retval = gExtensionsString;
507 break;
508 }
509 return retval;
510}
511
512void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
513{
514 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800515 SET_ERROR_IF(!GLESv2Validation::pixelStoreParam(ctx, param), GL_INVALID_ENUM);
516 SET_ERROR_IF(!GLESv2Validation::pixelStoreValue(param, value), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800517 ctx->m_glPixelStorei_enc(ctx, param, value);
518 assert(ctx->m_state != NULL);
519 ctx->m_state->setPixelStore(param, value);
520}
keunyoungb85b2752013-03-08 12:28:03 -0800521void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
522{
523 GL2Encoder *ctx = (GL2Encoder *) self;
524 assert(ctx->m_state != NULL);
525 ctx->m_state->bindBuffer(target, id);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800526 ctx->m_state->addBuffer(id);
keunyoungb85b2752013-03-08 12:28:03 -0800527 // TODO set error state if needed;
528 ctx->m_glBindBuffer_enc(self, target, id);
529}
530
531void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
532{
533 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800534 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800535 GLuint bufferId = ctx->m_state->getBuffer(target);
536 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
537 SET_ERROR_IF(size<0, GL_INVALID_VALUE);
538
Roman Kiryanovfb903d62018-09-19 13:38:53 -0700539 ctx->m_shared->updateBufferData(bufferId, size, data);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800540 ctx->m_shared->setBufferUsage(bufferId, usage);
keunyoungb85b2752013-03-08 12:28:03 -0800541 ctx->m_glBufferData_enc(self, target, size, data, usage);
542}
543
544void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
545{
546 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800547 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800548 GLuint bufferId = ctx->m_state->getBuffer(target);
549 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800550 SET_ERROR_IF(ctx->isBufferTargetMapped(target), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800551
Roman Kiryanovfb903d62018-09-19 13:38:53 -0700552 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, data);
keunyoungb85b2752013-03-08 12:28:03 -0800553 SET_ERROR_IF(res, res);
554
555 ctx->m_glBufferSubData_enc(self, target, offset, size, data);
556}
557
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800558void GL2Encoder::s_glGenBuffers(void* self, GLsizei n, GLuint* buffers) {
559 GL2Encoder *ctx = (GL2Encoder *) self;
560 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
561 ctx->m_glGenBuffers_enc(self, n, buffers);
562 for (int i = 0; i < n; i++) {
563 ctx->m_state->addBuffer(buffers[i]);
564 }
565}
566
keunyoungb85b2752013-03-08 12:28:03 -0800567void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
568{
569 GL2Encoder *ctx = (GL2Encoder *) self;
570 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
571 for (int i=0; i<n; i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800572 // Technically if the buffer is mapped, we should unmap it, but we won't
573 // use it anymore after this :)
keunyoungb85b2752013-03-08 12:28:03 -0800574 ctx->m_shared->deleteBufferData(buffers[i]);
bohub0f0cdf2014-11-06 18:08:07 -0800575 ctx->m_state->unBindBuffer(buffers[i]);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800576 ctx->m_state->removeBuffer(buffers[i]);
keunyoungb85b2752013-03-08 12:28:03 -0800577 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
578 }
579}
580
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700581static bool isValidVertexAttribIndex(void *self, GLuint indx)
582{
Lingfeng Yang07289902017-01-27 12:26:19 -0800583 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700584 GLint maxIndex;
585 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
586 return indx < maxIndex;
587}
588
Lingfeng Yang07289902017-01-27 12:26:19 -0800589#define VALIDATE_VERTEX_ATTRIB_INDEX(index) \
590 SET_ERROR_WITH_MESSAGE_IF( \
591 !isValidVertexAttribIndex(self, index), GL_INVALID_VALUE, \
592 GLESv2Validation::vertexAttribIndexRangeErrorMsg, (ctx, index)); \
593
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100594void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
keunyoungb85b2752013-03-08 12:28:03 -0800595{
596 GL2Encoder *ctx = (GL2Encoder *)self;
597 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -0800598 VALIDATE_VERTEX_ATTRIB_INDEX(indx);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700599 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800600 SET_ERROR_IF(!GLESv2Validation::vertexAttribType(ctx, type), GL_INVALID_ENUM);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700601 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800602 SET_ERROR_IF((type == GL_INT_2_10_10_10_REV ||
603 type == GL_UNSIGNED_INT_2_10_10_10_REV) &&
604 size != 4,
605 GL_INVALID_OPERATION);
606 ctx->m_state->setVertexAttribBinding(indx, indx);
607 ctx->m_state->setVertexAttribFormat(indx, size, type, normalized, 0, false);
608
609 GLsizei effectiveStride = stride;
610 if (stride == 0) {
611 effectiveStride = glSizeof(type) * size;
612 switch (type) {
613 case GL_INT_2_10_10_10_REV:
614 case GL_UNSIGNED_INT_2_10_10_10_REV:
615 effectiveStride /= 4;
616 break;
617 default:
618 break;
619 }
620 }
621
622 ctx->m_state->bindIndexedBuffer(0, indx, ctx->m_state->currentArrayVbo(), (uintptr_t)ptr, 0, stride, effectiveStride);
623
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800624 if (ctx->m_state->currentArrayVbo() != 0) {
625 ctx->glVertexAttribPointerOffset(ctx, indx, size, type, normalized, stride, (uintptr_t)ptr);
626 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800627 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && ptr, GL_INVALID_OPERATION);
628 // wait for client-array handler
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800629 }
keunyoungb85b2752013-03-08 12:28:03 -0800630}
631
632void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
633{
634 GL2Encoder *ctx = (GL2Encoder *) self;
keunyoungb85b2752013-03-08 12:28:03 -0800635 GLClientState* state = ctx->m_state;
636
637 switch (param) {
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -0800638 case GL_NUM_EXTENSIONS:
639 *ptr = (int)ctx->m_currExtensionsArray.size();
640 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800641 case GL_MAJOR_VERSION:
Lingfeng Yang324c8452017-02-17 09:56:26 -0800642 *ptr = ctx->m_deviceMajorVersion;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800643 break;
644 case GL_MINOR_VERSION:
Lingfeng Yang324c8452017-02-17 09:56:26 -0800645 *ptr = ctx->m_deviceMinorVersion;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800646 break;
keunyoungb85b2752013-03-08 12:28:03 -0800647 case GL_NUM_SHADER_BINARY_FORMATS:
648 *ptr = 0;
649 break;
650 case GL_SHADER_BINARY_FORMATS:
651 // do nothing
652 break;
653
654 case GL_COMPRESSED_TEXTURE_FORMATS: {
655 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
656 if (ctx->m_num_compressedTextureFormats > 0 &&
657 compressedTextureFormats != NULL) {
658 memcpy(ptr, compressedTextureFormats,
659 ctx->m_num_compressedTextureFormats * sizeof(GLint));
660 }
661 break;
662 }
663
664 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
665 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
666 case GL_MAX_TEXTURE_IMAGE_UNITS:
Lingfeng Yang80a36332017-07-09 10:58:07 -0700667 ctx->safe_glGetIntegerv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800668 *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
669 break;
670
671 case GL_TEXTURE_BINDING_2D:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700672 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800673 *ptr = state->getBoundTexture(GL_TEXTURE_2D);
674 break;
675 case GL_TEXTURE_BINDING_EXTERNAL_OES:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700676 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800677 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
678 break;
679
Lingfeng Yangb0176982016-03-01 21:27:49 -0800680 case GL_MAX_VERTEX_ATTRIBS:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700681 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
682 if (!state->getClientStateParameter<GLint>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700683 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700684 state->setMaxVertexAttribs(*ptr);
Yahan Zhoua5c36842016-06-01 12:49:39 -0700685 }
686 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800687 case GL_MAX_VERTEX_ATTRIB_STRIDE:
688 if (ctx->m_max_vertexAttribStride != 0) {
689 *ptr = ctx->m_max_vertexAttribStride;
690 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700691 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800692 ctx->m_max_vertexAttribStride = *ptr;
693 }
694 break;
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800695 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
696 if (ctx->m_max_cubeMapTextureSize != 0) {
697 *ptr = ctx->m_max_cubeMapTextureSize;
698 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700699 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800700 ctx->m_max_cubeMapTextureSize = *ptr;
701 }
702 break;
703 case GL_MAX_RENDERBUFFER_SIZE:
704 if (ctx->m_max_renderBufferSize != 0) {
705 *ptr = ctx->m_max_renderBufferSize;
706 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700707 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800708 ctx->m_max_renderBufferSize = *ptr;
709 }
710 break;
711 case GL_MAX_TEXTURE_SIZE:
712 if (ctx->m_max_textureSize != 0) {
713 *ptr = ctx->m_max_textureSize;
714 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700715 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800716 ctx->m_max_textureSize = *ptr;
Lingfeng Yangb0176982016-03-01 21:27:49 -0800717 }
718 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800719 case GL_MAX_3D_TEXTURE_SIZE:
720 if (ctx->m_max_3d_textureSize != 0) {
721 *ptr = ctx->m_max_3d_textureSize;
722 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700723 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800724 ctx->m_max_3d_textureSize = *ptr;
725 }
726 break;
727 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
728 if (ctx->m_ssbo_offset_align != 0) {
729 *ptr = ctx->m_ssbo_offset_align;
730 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700731 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800732 ctx->m_ssbo_offset_align = *ptr;
733 }
734 break;
735 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
736 if (ctx->m_ubo_offset_align != 0) {
737 *ptr = ctx->m_ubo_offset_align;
738 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700739 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800740 ctx->m_ubo_offset_align = *ptr;
741 }
742 break;
743 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
744 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
745 case GL_MAX_SAMPLES:
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800746 case GL_MAX_COLOR_TEXTURE_SAMPLES:
747 case GL_MAX_INTEGER_SAMPLES:
748 case GL_MAX_DEPTH_TEXTURE_SAMPLES:
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800749 *ptr = 4;
750 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700751 // Checks for version-incompatible enums.
752 // Not allowed in vanilla ES 2.0.
753 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
754 case GL_MAX_UNIFORM_BUFFER_BINDINGS:
755 SET_ERROR_IF(ctx->majorVersion() < 3, GL_INVALID_ENUM);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700756 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700757 break;
758 case GL_MAX_COLOR_ATTACHMENTS:
759 case GL_MAX_DRAW_BUFFERS:
760 SET_ERROR_IF(ctx->majorVersion() < 3 &&
761 !ctx->hasExtension("GL_EXT_draw_buffers"), GL_INVALID_ENUM);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700762 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700763 break;
764 // Not allowed in ES 3.0.
765 case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
766 case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
767 case GL_MAX_VERTEX_ATTRIB_BINDINGS:
768 SET_ERROR_IF(ctx->majorVersion() < 3 ||
769 (ctx->majorVersion() == 3 &&
770 ctx->minorVersion() == 0), GL_INVALID_ENUM);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700771 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700772 break;
keunyoungb85b2752013-03-08 12:28:03 -0800773 default:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700774 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
775 if (!state->getClientStateParameter<GLint>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700776 ctx->safe_glGetIntegerv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800777 }
778 break;
779 }
780}
781
782
783void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
784{
785 GL2Encoder *ctx = (GL2Encoder *)self;
keunyoungb85b2752013-03-08 12:28:03 -0800786 GLClientState* state = ctx->m_state;
787
788 switch (param) {
789 case GL_NUM_SHADER_BINARY_FORMATS:
790 *ptr = 0;
791 break;
792 case GL_SHADER_BINARY_FORMATS:
793 // do nothing
794 break;
795
796 case GL_COMPRESSED_TEXTURE_FORMATS: {
797 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
798 if (ctx->m_num_compressedTextureFormats > 0 &&
799 compressedTextureFormats != NULL) {
800 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
801 ptr[i] = (GLfloat) compressedTextureFormats[i];
802 }
803 }
804 break;
805 }
806
807 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
808 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
809 case GL_MAX_TEXTURE_IMAGE_UNITS:
Lingfeng Yang80a36332017-07-09 10:58:07 -0700810 ctx->safe_glGetFloatv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800811 *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
812 break;
813
814 case GL_TEXTURE_BINDING_2D:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700815 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800816 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
817 break;
818 case GL_TEXTURE_BINDING_EXTERNAL_OES:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700819 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800820 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
821 break;
822
823 default:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700824 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
825 if (!state->getClientStateParameter<GLfloat>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700826 ctx->safe_glGetFloatv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800827 }
828 break;
829 }
830}
831
832
833void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
834{
835 GL2Encoder *ctx = (GL2Encoder *)self;
keunyoungb85b2752013-03-08 12:28:03 -0800836 GLClientState* state = ctx->m_state;
837
838 switch (param) {
839 case GL_NUM_SHADER_BINARY_FORMATS:
840 *ptr = GL_FALSE;
841 break;
842 case GL_SHADER_BINARY_FORMATS:
843 // do nothing
844 break;
845
846 case GL_COMPRESSED_TEXTURE_FORMATS: {
847 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
848 if (ctx->m_num_compressedTextureFormats > 0 &&
849 compressedTextureFormats != NULL) {
850 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
851 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
852 }
853 }
854 break;
855 }
856
857 case GL_TEXTURE_BINDING_2D:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700858 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800859 *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
860 break;
861 case GL_TEXTURE_BINDING_EXTERNAL_OES:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700862 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800863 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
864 ? GL_TRUE : GL_FALSE;
865 break;
866
867 default:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700868 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
869 if (!state->getClientStateParameter<GLboolean>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700870 ctx->safe_glGetBooleanv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800871 }
bohu05101d22014-11-17 16:28:42 -0800872 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
keunyoungb85b2752013-03-08 12:28:03 -0800873 break;
874 }
875}
876
877
878void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
879{
880 GL2Encoder *ctx = (GL2Encoder *)self;
881 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -0800882 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800883 ctx->m_glEnableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800884 ctx->m_state->enable(index, 1);
885}
886
887void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
888{
889 GL2Encoder *ctx = (GL2Encoder *)self;
890 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -0800891 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800892 ctx->m_glDisableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800893 ctx->m_state->enable(index, 0);
894}
895
896
897void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
898{
899 GL2Encoder *ctx = (GL2Encoder *)self;
900 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700901 GLint maxIndex;
902 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
903 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800904
905 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
906 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
907 }
908}
909
910void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
911{
912 GL2Encoder *ctx = (GL2Encoder *)self;
913 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700914 GLint maxIndex;
915 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
916 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800917
918 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
919 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
920 }
921}
922
923void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
924{
925 GL2Encoder *ctx = (GL2Encoder *)self;
926 if (ctx->m_state == NULL) return;
Lingfeng Yang5e100432016-04-08 12:46:42 -0700927 GLint maxIndex;
928 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
929 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
930 SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100931 (void)pname;
932
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800933 *pointer = (GLvoid*)(ctx->m_state->getCurrAttributeBindingInfo(index).offset);
keunyoungb85b2752013-03-08 12:28:03 -0800934}
935
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700936void GL2Encoder::calcIndexRange(const void* indices,
937 GLenum type,
938 GLsizei count,
939 int* minIndex_out,
940 int* maxIndex_out) {
941 switch(type) {
942 case GL_BYTE:
943 case GL_UNSIGNED_BYTE:
944 GLUtils::minmaxExcept(
945 (unsigned char *)indices, count,
946 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800947 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned char>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700948 break;
949 case GL_SHORT:
950 case GL_UNSIGNED_SHORT:
951 GLUtils::minmaxExcept(
952 (unsigned short *)indices, count,
953 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800954 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned short>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700955 break;
956 case GL_INT:
957 case GL_UNSIGNED_INT:
958 GLUtils::minmaxExcept(
959 (unsigned int *)indices, count,
960 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800961 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned int>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700962 break;
963 default:
964 ALOGE("unsupported index buffer type %d\n", type);
965 }
966}
967
968void* GL2Encoder::recenterIndices(const void* src,
969 GLenum type,
970 GLsizei count,
971 int minIndex) {
972
973 void* adjustedIndices = (void*)src;
974
975 if (minIndex != 0) {
976 adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count);
977 switch(type) {
978 case GL_BYTE:
979 case GL_UNSIGNED_BYTE:
980 GLUtils::shiftIndicesExcept(
981 (unsigned char *)src,
982 (unsigned char *)adjustedIndices,
983 count, -minIndex,
984 m_primitiveRestartEnabled,
985 (unsigned char)m_primitiveRestartIndex);
986 break;
987 case GL_SHORT:
988 case GL_UNSIGNED_SHORT:
989 GLUtils::shiftIndicesExcept(
990 (unsigned short *)src,
991 (unsigned short *)adjustedIndices,
992 count, -minIndex,
993 m_primitiveRestartEnabled,
994 (unsigned short)m_primitiveRestartIndex);
995 break;
996 case GL_INT:
997 case GL_UNSIGNED_INT:
998 GLUtils::shiftIndicesExcept(
999 (unsigned int *)src,
1000 (unsigned int *)adjustedIndices,
1001 count, -minIndex,
1002 m_primitiveRestartEnabled,
1003 (unsigned int)m_primitiveRestartIndex);
1004 break;
1005 default:
1006 ALOGE("unsupported index buffer type %d\n", type);
1007 }
1008 }
1009
1010 return adjustedIndices;
1011}
1012
1013void GL2Encoder::getBufferIndexRange(BufferData* buf,
1014 const void* dataWithOffset,
1015 GLenum type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001016 size_t count,
1017 size_t offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001018 int* minIndex_out,
1019 int* maxIndex_out) {
1020
1021 if (buf->m_indexRangeCache.findRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001022 type, offset, count,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001023 m_primitiveRestartEnabled,
1024 minIndex_out,
1025 maxIndex_out)) {
1026 return;
1027 }
1028
1029 calcIndexRange(dataWithOffset, type, count, minIndex_out, maxIndex_out);
1030
1031 buf->m_indexRangeCache.addRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001032 type, offset, count, m_primitiveRestartEnabled,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001033 *minIndex_out, *maxIndex_out);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001034
1035 ALOGV("%s: got range [%u %u] pr? %d", __FUNCTION__, *minIndex_out, *maxIndex_out, m_primitiveRestartEnabled);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001036}
keunyoungb85b2752013-03-08 12:28:03 -08001037
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001038// For detecting legacy usage of glVertexAttribPointer
1039void GL2Encoder::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) const {
1040 if (hasClientArrays) *hasClientArrays = false;
1041 if (hasVBOs) *hasVBOs = false;
1042
1043 for (int i = 0; i < m_state->nLocations(); i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001044 const GLClientState::VertexAttribState& state = m_state->getState(i);
1045 if (state.enabled) {
1046 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
1047 GLuint bufferObject = curr_binding.buffer;
1048 if (bufferObject == 0 && curr_binding.offset && hasClientArrays) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001049 *hasClientArrays = true;
1050 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001051 if (bufferObject != 0 && hasVBOs) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001052 *hasVBOs = true;
1053 }
1054 }
1055 }
1056}
1057
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001058void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count, bool hasClientArrays, GLsizei primcount)
keunyoungb85b2752013-03-08 12:28:03 -08001059{
1060 assert(m_state);
1061
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001062 GLuint currentVao = m_state->currentVertexArrayObject();
Lingfeng Yang398162b2016-05-26 14:18:33 -07001063 GLuint lastBoundVbo = m_state->currentArrayVbo();
keunyoungb85b2752013-03-08 12:28:03 -08001064 for (int i = 0; i < m_state->nLocations(); i++) {
1065 bool enableDirty;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001066 const GLClientState::VertexAttribState& state = m_state->getStateAndEnableDirty(i, &enableDirty);
keunyoungb85b2752013-03-08 12:28:03 -08001067
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001068 if (!enableDirty && !state.enabled) {
keunyoungb85b2752013-03-08 12:28:03 -08001069 continue;
1070 }
1071
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001072 if (state.enabled) {
1073 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
1074 GLuint bufferObject = curr_binding.buffer;
1075 if (hasClientArrays && lastBoundVbo != bufferObject) {
1076 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, bufferObject);
1077 lastBoundVbo = bufferObject;
Lingfeng Yang398162b2016-05-26 14:18:33 -07001078 }
keunyoungb85b2752013-03-08 12:28:03 -08001079
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001080 int divisor = curr_binding.divisor;
1081 int stride = curr_binding.stride;
1082 int effectiveStride = curr_binding.effectiveStride;
1083 uintptr_t offset = curr_binding.offset;
Lingfeng Yang4e5446b2017-02-15 08:44:21 -08001084
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001085 int firstIndex = effectiveStride * first;
Lingfeng Yang4e5446b2017-02-15 08:44:21 -08001086 if (firstIndex && divisor && !primcount) {
1087 // If firstIndex != 0 according to effectiveStride * first,
1088 // it needs to be adjusted if a divisor has been specified,
1089 // even if we are not in glDraw***Instanced.
1090 firstIndex = 0;
1091 }
keunyoungb85b2752013-03-08 12:28:03 -08001092
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001093 if (bufferObject == 0) {
1094 unsigned int datalen = state.elementSize * count;
1095 if (divisor && primcount) {
1096 ALOGV("%s: divisor for att %d: %d, w/ stride %d (effective stride %d) size %d type 0x%x) datalen %u",
1097 __FUNCTION__, i, divisor, state.stride, effectiveStride, state.elementSize, state.type, datalen);
1098 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
1099 datalen = state.elementSize * actual_count;
1100 ALOGV("%s: actual datalen %u", __FUNCTION__, datalen);
1101 }
1102 if (state.elementSize == 0) {
Yahan Zhou3f2f1b42016-12-01 13:49:44 -08001103 // The vertex attribute array is uninitialized. Abandon it.
1104 ALOGE("a vertex attribute array is uninitialized. Skipping corresponding vertex attribute.");
1105 this->m_glDisableVertexAttribArray_enc(this, i);
1106 continue;
1107 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001108 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang000cf4c2017-01-25 08:09:02 -08001109
1110 if (datalen && (!offset || !((unsigned char*)offset + firstIndex))) {
1111 ALOGD("%s: bad offset / len!!!!!", __FUNCTION__);
1112 continue;
1113 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001114 if (state.isInt) {
1115 this->glVertexAttribIPointerDataAEMU(this, i, state.size, state.type, stride, (unsigned char *)offset + firstIndex, datalen);
1116 } else {
1117 this->glVertexAttribPointerData(this, i, state.size, state.type, state.normalized, stride, (unsigned char *)offset + firstIndex, datalen);
1118 }
keunyoungb85b2752013-03-08 12:28:03 -08001119 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001120 const BufferData* buf = m_shared->getBufferData(bufferObject);
Yahan Zhou5507c042016-06-01 17:24:28 -07001121 // The following expression actually means bufLen = stride*count;
1122 // But the last element doesn't have to fill up the whole stride.
1123 // So it becomes the current form.
Lingfeng Yang5fe99012017-01-18 09:17:09 -08001124 unsigned int bufLen = effectiveStride * (count ? (count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001125 if (divisor && primcount) {
1126 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
Lingfeng Yang5fe99012017-01-18 09:17:09 -08001127 bufLen = effectiveStride * (actual_count ? (actual_count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001128 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001129 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001130 if (hasClientArrays) {
1131 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001132 if (state.isInt) {
1133 this->glVertexAttribIPointerOffsetAEMU(this, i, state.size, state.type, stride, offset + firstIndex);
1134 } else {
1135 this->glVertexAttribPointerOffset(this, i, state.size, state.type, state.normalized, stride, offset + firstIndex);
1136 }
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001137 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001138 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001139 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=%p", buf);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -08001140 if (buf) {
1141 ALOGE("Out of bounds vertex attribute info: "
1142 "clientArray? %d attribute %d vbo %u allocedBufferSize %u bufferDataSpecified? %d wantedStart %u wantedEnd %u",
Lingfeng Yangddfb4452018-09-24 17:26:07 -07001143 hasClientArrays, i, bufferObject, (unsigned int)buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -08001144 }
1145 m_glDisableVertexAttribArray_enc(this, i);
Yahan Zhou5507c042016-06-01 17:24:28 -07001146 }
keunyoungb85b2752013-03-08 12:28:03 -08001147 }
1148 } else {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001149 if (hasClientArrays) {
1150 this->m_glDisableVertexAttribArray_enc(this, i);
1151 }
keunyoungb85b2752013-03-08 12:28:03 -08001152 }
1153 }
Lingfeng Yang398162b2016-05-26 14:18:33 -07001154
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001155 if (hasClientArrays && lastBoundVbo != m_state->currentArrayVbo()) {
Lingfeng Yang398162b2016-05-26 14:18:33 -07001156 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
1157 }
keunyoungb85b2752013-03-08 12:28:03 -08001158}
1159
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001160void GL2Encoder::flushDrawCall() {
Lingfeng Yang1ebb33c2017-01-19 08:04:48 -08001161 // This used to be every other draw call, but
1162 // now that we are using real GPU buffers on host,
1163 // set this to every 200 draw calls
1164 // (tuned on z840 linux NVIDIA Quadro K2200)
1165 if (m_drawCallFlushCount % 200 == 0) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001166 m_stream->flush();
1167 }
1168 m_drawCallFlushCount++;
1169}
1170
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001171static bool isValidDrawMode(GLenum mode)
1172{
1173 bool retval = false;
1174 switch (mode) {
1175 case GL_POINTS:
1176 case GL_LINE_STRIP:
1177 case GL_LINE_LOOP:
1178 case GL_LINES:
1179 case GL_TRIANGLE_STRIP:
1180 case GL_TRIANGLE_FAN:
1181 case GL_TRIANGLES:
1182 retval = true;
1183 }
1184 return retval;
1185}
1186
keunyoungb85b2752013-03-08 12:28:03 -08001187void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
1188{
1189 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001190 assert(ctx->m_state != NULL);
1191 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1192 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhoud6217a52016-02-10 16:10:46 -08001193
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001194 bool has_client_vertex_arrays = false;
1195 bool has_indirect_arrays = false;
1196 ctx->getVBOUsage(&has_client_vertex_arrays,
1197 &has_indirect_arrays);
1198
1199 if (has_client_vertex_arrays ||
1200 (!has_client_vertex_arrays &&
1201 !has_indirect_arrays)) {
1202 ctx->sendVertexAttributes(first, count, true);
1203 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
1204 } else {
1205 ctx->sendVertexAttributes(0, count, false);
1206 ctx->m_glDrawArrays_enc(ctx, mode, first, count);
1207 }
keunyoungb85b2752013-03-08 12:28:03 -08001208}
1209
1210
1211void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
1212{
1213
1214 GL2Encoder *ctx = (GL2Encoder *)self;
1215 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001216 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1217 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -07001218 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001219 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001220
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001221 bool has_client_vertex_arrays = false;
keunyoungb85b2752013-03-08 12:28:03 -08001222 bool has_indirect_arrays = false;
1223 int nLocations = ctx->m_state->nLocations();
Yahan Zhou5507c042016-06-01 17:24:28 -07001224 GLintptr offset = 0;
keunyoungb85b2752013-03-08 12:28:03 -08001225
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001226 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
keunyoungb85b2752013-03-08 12:28:03 -08001227
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001228 if (!has_client_vertex_arrays && !has_indirect_arrays) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001229 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -07001230 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
1231 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001232 }
1233
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001234 BufferData* buf = NULL;
Yahan Zhou5507c042016-06-01 17:24:28 -07001235 int minIndex = 0, maxIndex = 0;
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001236
1237 // For validation/immediate index array purposes,
1238 // we need the min/max vertex index of the index array.
1239 // If the VBO != 0, this may not be the first time we have
1240 // used this particular index buffer. getBufferIndexRange
1241 // can more quickly get min/max vertex index by
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001242 // caching previous results.
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001243 if (ctx->m_state->currentIndexVbo() != 0) {
1244 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1245 offset = (GLintptr)indices;
1246 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
1247 ctx->getBufferIndexRange(buf,
1248 indices,
1249 type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001250 (size_t)count,
1251 (size_t)offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001252 &minIndex, &maxIndex);
1253 } else {
1254 // In this case, the |indices| field holds a real
1255 // array, so calculate the indices now. They will
1256 // also be needed to know how much data to
1257 // transfer to host.
1258 ctx->calcIndexRange(indices,
1259 type,
1260 count,
1261 &minIndex,
1262 &maxIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -07001263 }
1264
Lingfeng Yang26e629a2018-10-13 20:00:12 -07001265 if (count == 0) return;
1266
keunyoungb85b2752013-03-08 12:28:03 -08001267 bool adjustIndices = true;
1268 if (ctx->m_state->currentIndexVbo() != 0) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001269 if (!has_client_vertex_arrays) {
1270 ctx->sendVertexAttributes(0, maxIndex + 1, false);
keunyoungb85b2752013-03-08 12:28:03 -08001271 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -07001272 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001273 ctx->flushDrawCall();
keunyoungb85b2752013-03-08 12:28:03 -08001274 adjustIndices = false;
1275 } else {
1276 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1277 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001278 }
1279 }
1280 if (adjustIndices) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001281 void *adjustedIndices =
1282 ctx->recenterIndices(indices,
1283 type,
1284 count,
1285 minIndex);
keunyoungb85b2752013-03-08 12:28:03 -08001286
keunyoungb85b2752013-03-08 12:28:03 -08001287 if (has_indirect_arrays || 1) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001288 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
keunyoungb85b2752013-03-08 12:28:03 -08001289 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
1290 count * glSizeof(type));
1291 // XXX - OPTIMIZATION (see the other else branch) should be implemented
1292 if(!has_indirect_arrays) {
1293 //ALOGD("unoptimized drawelements !!!\n");
1294 }
1295 } else {
1296 // we are all direct arrays and immidate mode index array -
1297 // rebuild the arrays and the index array;
1298 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
1299 }
1300 }
1301}
1302
1303
1304GLint * GL2Encoder::getCompressedTextureFormats()
1305{
1306 if (m_compressedTextureFormats == NULL) {
1307 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
1308 &m_num_compressedTextureFormats);
1309 if (m_num_compressedTextureFormats > 0) {
1310 // get number of texture formats;
1311 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
1312 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
1313 }
1314 }
1315 return m_compressedTextureFormats;
1316}
1317
1318// Replace uses of samplerExternalOES with sampler2D, recording the names of
1319// modified shaders in data. Also remove
1320// #extension GL_OES_EGL_image_external : require
1321// statements.
1322//
1323// This implementation assumes the input has already been pre-processed. If not,
1324// a few cases will be mishandled:
1325//
1326// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
1327// the following code:
1328// #if 1
1329// uniform sampler2D mySampler;
1330// #else
1331// uniform samplerExternalOES mySampler;
1332// #endif
1333//
1334// 2. Comments that look like sampler declarations will be incorrectly modified
1335// and recorded:
1336// // samplerExternalOES hahaFooledYou
1337//
1338// 3. However, GLSL ES does not have a concatentation operator, so things like
1339// this (valid in C) are invalid and not a problem:
1340// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
1341// SAMPLER(ExternalOES, mySampler);
1342//
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001343
1344static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
1345static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
1346static const char STR_DEFINE[] = "#define";
1347
1348static std::vector<std::string> getSamplerExternalAliases(char* str) {
1349 std::vector<std::string> res;
1350
1351 res.push_back(STR_SAMPLER_EXTERNAL_OES);
1352
1353 // -- capture #define x samplerExternalOES
1354 char* c = str;
1355 while ((c = strstr(c, STR_DEFINE))) {
1356 // Don't push it if samplerExternalOES is not even there.
1357 char* samplerExternalOES_next = strstr(c, STR_SAMPLER_EXTERNAL_OES);
1358 if (!samplerExternalOES_next) break;
1359
1360 bool prevIdent = false;
1361
1362 std::vector<std::string> idents;
1363 std::string curr;
1364
1365 while (*c != '\0') {
1366
1367 if (isspace(*c)) {
1368 if (prevIdent) {
1369 idents.push_back(curr);
1370 curr = "";
1371 }
1372 }
1373
1374 if (*c == '\n' || idents.size() == 3) break;
1375
1376 if (isalpha(*c) || *c == '_') {
1377 curr.push_back(*c);
1378 prevIdent = true;
1379 }
1380
1381 ++c;
1382 }
1383
1384 if (idents.size() != 3) continue;
1385
1386 const std::string& defineLhs = idents[1];
1387 const std::string& defineRhs = idents[2];
1388
1389 if (defineRhs == STR_SAMPLER_EXTERNAL_OES) {
1390 res.push_back(defineLhs);
1391 }
1392
1393 if (*c == '\0') break;
1394 }
1395
1396 return res;
1397}
1398
1399static bool replaceExternalSamplerUniformDefinition(char* str, const std::string& samplerExternalType, ShaderData* data) {
1400 // -- replace "samplerExternalOES" with "sampler2D" and record name
1401 char* c = str;
1402 while ((c = strstr(c, samplerExternalType.c_str()))) {
1403 // Make sure "samplerExternalOES" isn't a substring of a larger token
1404 if (c == str || !isspace(*(c-1))) {
1405 c++;
1406 continue;
1407 }
1408 char* sampler_start = c;
1409 c += samplerExternalType.size();
1410 if (!isspace(*c) && *c != '\0') {
1411 continue;
1412 }
1413
1414 // capture sampler name
1415 while (isspace(*c) && *c != '\0') {
1416 c++;
1417 }
1418 if (!isalpha(*c) && *c != '_') {
1419 // not an identifier
1420 return false;
1421 }
1422 char* name_start = c;
1423 do {
1424 c++;
1425 } while (isalnum(*c) || *c == '_');
Lingfeng Yang44209df2018-09-21 10:04:17 -07001426
1427 size_t len = (size_t)(c - name_start);
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001428 data->samplerExternalNames.push_back(
Lingfeng Yang44209df2018-09-21 10:04:17 -07001429 std::string(name_start, len));
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001430
1431 // We only need to perform a string replacement for the original
1432 // occurrence of samplerExternalOES if a #define was used.
1433 //
1434 // The important part was to record the name in
1435 // |data->samplerExternalNames|.
1436 if (samplerExternalType == STR_SAMPLER_EXTERNAL_OES) {
1437 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
1438 }
1439 }
1440
1441 return true;
1442}
1443
keunyoungb85b2752013-03-08 12:28:03 -08001444static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
1445{
1446 static const char STR_HASH_EXTENSION[] = "#extension";
1447 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
Lingfeng Yang3546c4d2018-04-10 12:34:30 -07001448 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3[] = "GL_OES_EGL_image_external_essl3";
keunyoungb85b2752013-03-08 12:28:03 -08001449
1450 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
1451 char* c = str;
1452 while ((c = strstr(c, STR_HASH_EXTENSION))) {
1453 char* start = c;
1454 c += sizeof(STR_HASH_EXTENSION)-1;
1455 while (isspace(*c) && *c != '\0') {
1456 c++;
1457 }
Lingfeng Yang3546c4d2018-04-10 12:34:30 -07001458
1459 bool hasBaseImageExternal =
1460 !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
1461 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL) - 1);
1462 bool hasEssl3ImageExternal =
1463 !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3,
1464 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3) - 1);
1465
1466 if (hasBaseImageExternal || hasEssl3ImageExternal)
keunyoungb85b2752013-03-08 12:28:03 -08001467 {
1468 // #extension statements are terminated by end of line
1469 c = start;
1470 while (*c != '\0' && *c != '\r' && *c != '\n') {
1471 *c++ = ' ';
1472 }
1473 }
1474 }
1475
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001476 std::vector<std::string> samplerExternalAliases =
1477 getSamplerExternalAliases(str);
keunyoungb85b2752013-03-08 12:28:03 -08001478
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001479 for (size_t i = 0; i < samplerExternalAliases.size(); i++) {
1480 if (!replaceExternalSamplerUniformDefinition(
1481 str, samplerExternalAliases[i], data))
keunyoungb85b2752013-03-08 12:28:03 -08001482 return false;
keunyoungb85b2752013-03-08 12:28:03 -08001483 }
1484
1485 return true;
1486}
1487
Bo Hu73568cd2015-01-20 16:29:50 -08001488void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
1489{
1490 GL2Encoder* ctx = (GL2Encoder*)self;
1491 // Although it is not supported, need to set proper error code.
1492 SET_ERROR_IF(1, GL_INVALID_ENUM);
1493}
1494
David 'Digit' Turner02fdb692014-10-30 18:07:56 +01001495void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -08001496{
1497 GL2Encoder* ctx = (GL2Encoder*)self;
1498 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001499 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(shader), GL_INVALID_VALUE);
Tina Zhang7a84f652014-12-04 12:37:30 +08001500 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
1501 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001502
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001503 // Track original sources---they may be translated in the backend
1504 std::vector<std::string> orig_sources;
1505 for (int i = 0; i < count; i++) {
1506 orig_sources.push_back(std::string((const char*)(string[i])));
1507 }
1508 shaderData->sources = orig_sources;
1509
keunyoungb85b2752013-03-08 12:28:03 -08001510 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
1511 char *str = new char[len + 1];
1512 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
1513
1514 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
1515 // Perhaps we can borrow Mesa's pre-processor?
1516
1517 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001518 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001519 ctx->setError(GL_OUT_OF_MEMORY);
1520 return;
1521 }
keunyoungb85b2752013-03-08 12:28:03 -08001522 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001523 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001524}
1525
1526void GL2Encoder::s_glFinish(void *self)
1527{
1528 GL2Encoder *ctx = (GL2Encoder *)self;
1529 ctx->glFinishRoundTrip(self);
1530}
1531
1532void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1533{
1534 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -08001535 bool isProgram = ctx->m_shared->isProgram(program);
1536 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
1537 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
1538
keunyoungb85b2752013-03-08 12:28:03 -08001539 ctx->m_glLinkProgram_enc(self, program);
1540
1541 GLint linkStatus = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07001542 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001543 if (!linkStatus) {
keunyoungb85b2752013-03-08 12:28:03 -08001544 return;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001545 }
keunyoungb85b2752013-03-08 12:28:03 -08001546
1547 //get number of active uniforms in the program
1548 GLint numUniforms=0;
1549 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
1550 ctx->m_shared->initProgramData(program,numUniforms);
1551
1552 //get the length of the longest uniform name
1553 GLint maxLength=0;
1554 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
1555
1556 GLint size;
1557 GLenum type;
1558 GLchar *name = new GLchar[maxLength+1];
1559 GLint location;
1560 //for each active uniform, get its size and starting location.
1561 for (GLint i=0 ; i<numUniforms ; ++i)
1562 {
1563 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1564 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1565 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1566 }
1567 ctx->m_shared->setupLocationShiftWAR(program);
1568
1569 delete[] name;
1570}
1571
1572void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1573{
1574 GL2Encoder *ctx = (GL2Encoder*)self;
1575 ctx->m_glDeleteProgram_enc(self, program);
1576
1577 ctx->m_shared->deleteProgramData(program);
1578}
1579
1580void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1581{
1582 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001583 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001584 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001585 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1586 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1587 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1588 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1589}
1590void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1591{
1592 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001593 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001594 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001595 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1596 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1597 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1598 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1599}
1600
1601GLuint GL2Encoder::s_glCreateProgram(void * self)
1602{
1603 GL2Encoder *ctx = (GL2Encoder*)self;
1604 GLuint program = ctx->m_glCreateProgram_enc(self);
1605 if (program!=0)
1606 ctx->m_shared->addProgramData(program);
1607 return program;
1608}
1609
1610GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1611{
1612 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001613 RET_AND_SET_ERROR_IF(!GLESv2Validation::shaderType(ctx, shaderType), GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001614 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1615 if (shader != 0) {
1616 if (!ctx->m_shared->addShaderData(shader)) {
1617 ctx->m_glDeleteShader_enc(self, shader);
1618 return 0;
1619 }
1620 }
1621 return shader;
1622}
1623
bohu56bf82f2014-10-17 15:35:48 -07001624void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1625 GLsizei* count, GLuint* shaders)
1626{
1627 GL2Encoder *ctx = (GL2Encoder*)self;
1628 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1629 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1630}
1631
1632void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1633 GLsizei* length, GLchar* source)
1634{
1635 GL2Encoder *ctx = (GL2Encoder*)self;
1636 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1637 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001638 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
1639 if (shaderData) {
1640 std::string returned;
1641 int curr_len = 0;
1642 for (int i = 0; i < shaderData->sources.size(); i++) {
1643 if (curr_len + shaderData->sources[i].size() < bufsize - 1) {
1644 returned += shaderData->sources[i];
1645 } else {
1646 returned += shaderData->sources[i].substr(0, bufsize - 1 - curr_len);
1647 break;
1648 }
1649 }
1650 memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize);
1651 }
bohu56bf82f2014-10-17 15:35:48 -07001652}
1653
1654void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1655 GLsizei* length, GLchar* infolog)
1656{
1657 GL2Encoder *ctx = (GL2Encoder*)self;
1658 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1659 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1660}
1661
1662void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1663 GLsizei* length, GLchar* infolog)
1664{
1665 GL2Encoder *ctx = (GL2Encoder*)self;
1666 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1667 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1668}
1669
keunyoungb85b2752013-03-08 12:28:03 -08001670void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1671{
1672 GL2Encoder *ctx = (GL2Encoder*)self;
1673 ctx->m_glDeleteShader_enc(self,shader);
1674 ctx->m_shared->unrefShaderData(shader);
1675}
1676
1677void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1678{
1679 GL2Encoder *ctx = (GL2Encoder*)self;
1680 ctx->m_glAttachShader_enc(self, program, shader);
1681 ctx->m_shared->attachShader(program, shader);
1682}
1683
1684void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1685{
1686 GL2Encoder *ctx = (GL2Encoder*)self;
1687 ctx->m_glDetachShader_enc(self, program, shader);
1688 ctx->m_shared->detachShader(program, shader);
1689}
1690
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001691int sArrIndexOfUniformExpr(const char* name, int* err) {
1692 *err = 0;
1693 int arrIndex = 0;
1694 int namelen = strlen(name);
1695 if (name[namelen-1] == ']') {
1696 const char *brace = strrchr(name,'[');
1697 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1698 *err = 1; return 0;
1699 }
1700 }
1701 return arrIndex;
1702}
1703
keunyoungb85b2752013-03-08 12:28:03 -08001704int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1705{
1706 if (!name) return -1;
1707
1708 GL2Encoder *ctx = (GL2Encoder*)self;
1709
1710 // if we need the uniform location WAR
1711 // parse array index from the end of the name string
1712 int arrIndex = 0;
1713 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1714 if (needLocationWAR) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001715 int err;
1716 arrIndex = sArrIndexOfUniformExpr(name, &err);
1717 if (err) return -1;
keunyoungb85b2752013-03-08 12:28:03 -08001718 }
1719
1720 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1721 if (hostLoc >= 0 && needLocationWAR) {
1722 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1723 }
1724 return hostLoc;
1725}
1726
1727bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1728{
1729 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1730 return false;
1731
1732 m_state->setActiveTextureUnit(texUnit);
1733
1734 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1735 if (newTarget != oldTarget) {
1736 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1737 m_state->disableTextureTarget(GL_TEXTURE_2D);
1738 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1739 } else {
1740 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1741 m_state->enableTextureTarget(GL_TEXTURE_2D);
1742 }
1743 m_glActiveTexture_enc(this, texUnit);
1744 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1745 m_state->getBoundTexture(newTarget));
1746 return true;
1747 }
1748
1749 return false;
1750}
1751
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001752void GL2Encoder::updateHostTexture2DBindingsFromProgramData(GLuint program) {
1753 GL2Encoder *ctx = this;
keunyoungb85b2752013-03-08 12:28:03 -08001754 GLClientState* state = ctx->m_state;
1755 GLSharedGroupPtr shared = ctx->m_shared;
1756
keunyoungb85b2752013-03-08 12:28:03 -08001757 GLenum origActiveTexture = state->getActiveTextureUnit();
1758 GLenum hostActiveTexture = origActiveTexture;
1759 GLint samplerIdx = -1;
1760 GLint samplerVal;
1761 GLenum samplerTarget;
1762 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1763 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1764 continue;
1765 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001766 samplerTarget))
keunyoungb85b2752013-03-08 12:28:03 -08001767 {
1768 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1769 }
1770 }
1771 state->setActiveTextureUnit(origActiveTexture);
1772 if (hostActiveTexture != origActiveTexture) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001773 ctx->m_glActiveTexture_enc(ctx, origActiveTexture);
keunyoungb85b2752013-03-08 12:28:03 -08001774 }
1775}
1776
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001777void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1778{
1779 GL2Encoder *ctx = (GL2Encoder*)self;
1780 GLSharedGroupPtr shared = ctx->m_shared;
1781
1782 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
1783 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1784
1785 ctx->m_glUseProgram_enc(self, program);
1786 ctx->m_state->setCurrentProgram(program);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001787 ctx->m_state->setCurrentShaderProgram(program);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001788
1789 ctx->updateHostTexture2DBindingsFromProgramData(program);
1790}
1791
keunyoungb85b2752013-03-08 12:28:03 -08001792void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1793{
1794 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001795 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001796 ctx->m_glUniform1f_enc(self, hostLoc, x);
1797}
1798
1799void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1800{
1801 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001802 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001803 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1804}
1805
1806void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1807{
1808 GL2Encoder *ctx = (GL2Encoder*)self;
1809 GLClientState* state = ctx->m_state;
1810 GLSharedGroupPtr shared = ctx->m_shared;
1811
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001812 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001813 ctx->m_glUniform1i_enc(self, hostLoc, x);
1814
1815 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001816 if (shared->setSamplerUniform(state->currentShaderProgram(), location, x, &target)) {
keunyoungb85b2752013-03-08 12:28:03 -08001817 GLenum origActiveTexture = state->getActiveTextureUnit();
1818 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1819 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1820 }
1821 state->setActiveTextureUnit(origActiveTexture);
1822 }
1823}
1824
1825void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1826{
1827 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001828 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001829 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1830}
1831
1832void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1833{
1834 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001835 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001836 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1837}
1838
1839void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1840{
1841 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001842 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001843 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1844}
1845
1846void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1847{
1848 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001849 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001850 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1851}
1852
1853void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1854{
1855 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001856 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001857 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1858}
1859
1860void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1861{
1862 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001863 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001864 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1865}
1866
1867void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1868{
1869 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001870 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001871 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1872}
1873
1874void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1875{
1876 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001877 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001878 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1879}
1880
1881void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1882{
1883 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001884 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001885 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1886}
1887
1888void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1889{
1890 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001891 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001892 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1893}
1894
1895void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1896{
1897 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001898 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001899 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1900}
1901
1902void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1903{
1904 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001905 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001906 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1907}
1908
1909void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1910{
1911 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001912 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001913 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1914}
1915
1916void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1917{
1918 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001919 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001920 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1921}
1922
1923void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1924{
1925 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001926 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001927 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1928}
1929
1930void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1931{
1932 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001933 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001934 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1935}
1936
1937void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1938{
1939 GL2Encoder* ctx = (GL2Encoder*)self;
1940 GLClientState* state = ctx->m_state;
1941 GLenum err;
1942
1943 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1944
1945 ctx->m_glActiveTexture_enc(ctx, texture);
1946}
1947
1948void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1949{
1950 GL2Encoder* ctx = (GL2Encoder*)self;
1951 GLClientState* state = ctx->m_state;
1952 GLenum err;
1953 GLboolean firstUse;
1954
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001955 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -08001956 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1957
1958 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1959 ctx->m_glBindTexture_enc(ctx, target, texture);
1960 return;
1961 }
1962
1963 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1964
1965 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1966 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1967 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1968 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1969 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1970 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1971 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1972 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1973
1974 if (target != priorityTarget) {
1975 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1976 state->getBoundTexture(GL_TEXTURE_2D));
1977 }
1978 }
1979
1980 if (target == priorityTarget) {
1981 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1982 }
1983}
1984
1985void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1986{
1987 GL2Encoder* ctx = (GL2Encoder*)self;
1988 GLClientState* state = ctx->m_state;
1989
1990 state->deleteTextures(n, textures);
1991 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1992}
1993
1994void GL2Encoder::s_glGetTexParameterfv(void* self,
1995 GLenum target, GLenum pname, GLfloat* params)
1996{
1997 GL2Encoder* ctx = (GL2Encoder*)self;
1998 const GLClientState* state = ctx->m_state;
1999
2000 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2001 ctx->override2DTextureTarget(target);
2002 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002003 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002004 } else {
2005 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
2006 }
2007}
2008
2009void GL2Encoder::s_glGetTexParameteriv(void* self,
2010 GLenum target, GLenum pname, GLint* params)
2011{
2012 GL2Encoder* ctx = (GL2Encoder*)self;
2013 const GLClientState* state = ctx->m_state;
2014
2015 switch (pname) {
2016 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
2017 *params = 1;
2018 break;
2019
2020 default:
2021 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2022 ctx->override2DTextureTarget(target);
2023 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002024 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002025 } else {
2026 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
2027 }
2028 break;
2029 }
2030}
2031
2032static bool isValidTextureExternalParam(GLenum pname, GLenum param)
2033{
2034 switch (pname) {
2035 case GL_TEXTURE_MIN_FILTER:
2036 case GL_TEXTURE_MAG_FILTER:
2037 return param == GL_NEAREST || param == GL_LINEAR;
2038
2039 case GL_TEXTURE_WRAP_S:
2040 case GL_TEXTURE_WRAP_T:
2041 return param == GL_CLAMP_TO_EDGE;
2042
2043 default:
2044 return true;
2045 }
2046}
2047
2048void GL2Encoder::s_glTexParameterf(void* self,
2049 GLenum target, GLenum pname, GLfloat param)
2050{
2051 GL2Encoder* ctx = (GL2Encoder*)self;
2052 const GLClientState* state = ctx->m_state;
2053
2054 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2055 !isValidTextureExternalParam(pname, (GLenum)param)),
2056 GL_INVALID_ENUM);
2057
2058 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2059 ctx->override2DTextureTarget(target);
2060 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002061 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002062 } else {
2063 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
2064 }
2065}
2066
2067void GL2Encoder::s_glTexParameterfv(void* self,
2068 GLenum target, GLenum pname, const GLfloat* params)
2069{
2070 GL2Encoder* ctx = (GL2Encoder*)self;
2071 const GLClientState* state = ctx->m_state;
2072
2073 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2074 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2075 GL_INVALID_ENUM);
2076
2077 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2078 ctx->override2DTextureTarget(target);
2079 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002080 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002081 } else {
2082 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
2083 }
2084}
2085
2086void GL2Encoder::s_glTexParameteri(void* self,
2087 GLenum target, GLenum pname, GLint param)
2088{
2089 GL2Encoder* ctx = (GL2Encoder*)self;
2090 const GLClientState* state = ctx->m_state;
2091
2092 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2093 !isValidTextureExternalParam(pname, (GLenum)param)),
2094 GL_INVALID_ENUM);
2095
2096 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2097 ctx->override2DTextureTarget(target);
2098 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002099 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002100 } else {
2101 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
2102 }
2103}
2104
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002105static int ilog2(uint32_t x) {
2106 int p = 0;
2107 while ((1 << p) < x)
2108 p++;
2109 return p;
2110}
2111
bohu26a92982014-11-25 16:50:37 -08002112void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
2113 GLint internalformat, GLsizei width, GLsizei height, GLint border,
2114 GLenum format, GLenum type, const GLvoid* pixels)
2115{
2116 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07002117 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002118
2119 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2120 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2121 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2122 // If unpack buffer is nonzero, verify unmapped state.
2123 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2124
2125 GLint max_texture_size;
2126 GLint max_cube_map_texture_size;
2127 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2128 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2129 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2130 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2131 SET_ERROR_IF((target == GL_TEXTURE_CUBE_MAP) &&
2132 (level > ilog2(max_cube_map_texture_size)), GL_INVALID_VALUE);
2133 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2134 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2135 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2136 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && width > max_cube_map_texture_size, GL_INVALID_VALUE);
2137 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && height > max_cube_map_texture_size, GL_INVALID_VALUE);
2138 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
2139 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2140 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2141 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2142 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 0) >
2143 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2144 GL_INVALID_OPERATION);
2145 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2146 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2147 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2148 glSizeof(type)),
2149 GL_INVALID_OPERATION);
2150 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2151 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2152 ((uintptr_t)pixels % glSizeof(type)),
2153 GL_INVALID_OPERATION);
2154 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
2155
2156 GLenum stateTarget = target;
2157 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2158 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2159 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2160 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2161 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2162 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2163 stateTarget = GL_TEXTURE_CUBE_MAP;
2164
2165 state->setBoundTextureInternalFormat(stateTarget, internalformat);
2166 state->setBoundTextureFormat(stateTarget, format);
2167 state->setBoundTextureType(stateTarget, type);
2168 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2169
bohu26a92982014-11-25 16:50:37 -08002170 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2171 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002172 }
Lingfeng Yang69066602016-04-12 09:29:11 -07002173
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002174 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2175 ctx->glTexImage2DOffsetAEMU(
2176 ctx, target, level, internalformat,
2177 width, height, border,
2178 format, type, (uintptr_t)pixels);
bohu26a92982014-11-25 16:50:37 -08002179 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002180 ctx->m_glTexImage2D_enc(
2181 ctx, target, level, internalformat,
2182 width, height, border,
2183 format, type, pixels);
2184 }
2185
2186 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2187 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08002188 }
2189}
2190
Yahan Zhou2a208292016-06-22 15:36:04 -07002191void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
2192 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
2193 GLenum type, const GLvoid* pixels)
2194{
2195 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002196 GLClientState* state = ctx->m_state;
2197
2198 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2199 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2200 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2201 // If unpack buffer is nonzero, verify unmapped state.
2202 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2203
2204 GLint max_texture_size;
2205 GLint max_cube_map_texture_size;
2206 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2207 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2208 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2209 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2210 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) &&
2211 level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2212 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2213 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2214
2215 GLuint tex = state->getBoundTexture(target);
2216 GLsizei neededWidth = xoffset + width;
2217 GLsizei neededHeight = yoffset + height;
2218 GLsizei neededDepth = 1;
2219
2220 if (tex && !state->queryTexEGLImageBacked(tex)) {
2221 SET_ERROR_IF(
2222 (neededWidth > state->queryTexWidth(level, tex) ||
2223 neededHeight > state->queryTexHeight(level, tex) ||
2224 neededDepth > state->queryTexDepth(level, tex)),
2225 GL_INVALID_VALUE);
2226 }
2227
2228 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2229 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2230 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2231 (state->pboNeededDataSize(width, height, 1, format, type, 0) >
2232 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2233 GL_INVALID_OPERATION);
2234 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2235 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2236 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2237 glSizeof(type)),
2238 GL_INVALID_OPERATION);
2239 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !pixels, GL_INVALID_OPERATION);
Yahan Zhou2a208292016-06-22 15:36:04 -07002240
2241 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2242 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002243 }
2244
2245 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2246 ctx->glTexSubImage2DOffsetAEMU(
2247 ctx, target, level,
2248 xoffset, yoffset, width, height,
2249 format, type, (uintptr_t)pixels);
Yahan Zhou2a208292016-06-22 15:36:04 -07002250 } else {
2251 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
2252 height, format, type, pixels);
2253 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002254
2255 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2256 ctx->restore2DTextureTarget(target);
2257 }
Yahan Zhou2a208292016-06-22 15:36:04 -07002258}
bohu26a92982014-11-25 16:50:37 -08002259
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002260void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
2261 GLenum internalformat, GLint x, GLint y,
2262 GLsizei width, GLsizei height, GLint border)
2263{
2264 GL2Encoder* ctx = (GL2Encoder*)self;
2265 GLClientState* state = ctx->m_state;
2266
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002267 SET_ERROR_IF(ctx->glCheckFramebufferStatus(ctx, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
2268 GL_INVALID_FRAMEBUFFER_OPERATION);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002269 // This is needed to work around underlying OpenGL drivers
2270 // (such as those feeding some some AMD GPUs) that expect
2271 // positive components of cube maps to be defined _before_
2272 // the negative components (otherwise a segfault occurs).
2273 GLenum extraTarget =
2274 state->copyTexImageLuminanceCubeMapAMDWorkaround
2275 (target, level, internalformat);
2276
2277 if (extraTarget) {
2278 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
2279 x, y, width, height, border);
2280 }
2281
2282 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
2283 x, y, width, height, border);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002284
2285 state->setBoundTextureInternalFormat(target, internalformat);
2286 state->setBoundTextureDims(target, level, width, height, 1);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002287}
2288
keunyoungb85b2752013-03-08 12:28:03 -08002289void GL2Encoder::s_glTexParameteriv(void* self,
2290 GLenum target, GLenum pname, const GLint* params)
2291{
2292 GL2Encoder* ctx = (GL2Encoder*)self;
2293 const GLClientState* state = ctx->m_state;
2294
2295 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2296 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2297 GL_INVALID_ENUM);
2298
2299 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2300 ctx->override2DTextureTarget(target);
2301 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002302 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002303 } else {
2304 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
2305 }
2306}
2307
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002308bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
2309 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
2310 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2311}
2312
keunyoungb85b2752013-03-08 12:28:03 -08002313void GL2Encoder::override2DTextureTarget(GLenum target)
2314{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002315 if (texture2DNeedsOverride(target)) {
2316 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2317 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08002318 }
2319}
2320
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002321void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08002322{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002323 if (texture2DNeedsOverride(target)) {
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002324 GLuint priorityEnabledBoundTexture =
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002325 m_state->getBoundTexture(
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002326 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D));
2327 GLuint texture2DBoundTexture =
2328 m_state->getBoundTexture(GL_TEXTURE_2D);
2329 if (!priorityEnabledBoundTexture) {
2330 m_glBindTexture_enc(this, GL_TEXTURE_2D, texture2DBoundTexture);
2331 } else {
2332 m_glBindTexture_enc(this, GL_TEXTURE_2D, priorityEnabledBoundTexture);
2333 }
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002334 }
keunyoungb85b2752013-03-08 12:28:03 -08002335}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002336
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002337void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2338 m_state->setBoundEGLImage(target, eglImage);
2339}
2340
2341
2342GLuint GL2Encoder::boundBuffer(GLenum target) const {
2343 return m_state->getBuffer(target);
2344}
2345
2346BufferData* GL2Encoder::getBufferData(GLenum target) const {
2347 GLuint bufferId = m_state->getBuffer(target);
2348 if (!bufferId) return NULL;
2349 return m_shared->getBufferData(bufferId);
2350}
2351
2352BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2353 if (!bufferId) return NULL;
2354 return m_shared->getBufferData(bufferId);
2355}
2356
2357bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2358 return m_shared->getBufferData(buffer)->m_mapped;
2359}
2360
2361bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2362 BufferData* buf = getBufferData(target);
2363 if (!buf) return false;
2364 return buf->m_mapped;
2365}
2366
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002367void GL2Encoder::s_glGenRenderbuffers(void* self,
2368 GLsizei n, GLuint* renderbuffers) {
2369 GL2Encoder* ctx = (GL2Encoder*)self;
2370 GLClientState* state = ctx->m_state;
2371
2372 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2373
2374 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2375 state->addRenderbuffers(n, renderbuffers);
2376}
2377
2378void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2379 GLsizei n, const GLuint* renderbuffers) {
2380 GL2Encoder* ctx = (GL2Encoder*)self;
2381 GLClientState* state = ctx->m_state;
2382
2383 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2384
2385 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002386
2387 // Nope, lets just leak those for now.
2388 // The spec has an *amazingly* convoluted set of conditions for when
2389 // render buffers are actually deleted:
2390 // glDeleteRenderbuffers deletes the n renderbuffer objects whose names are stored in the array addressed by renderbuffers. Unused names in renderbuffers that have been marked as used for the purposes of glGenRenderbuffers are marked as unused again. The name zero is reserved by the GL and is silently ignored, should it occur in renderbuffers, as are other unused names. Once a renderbuffer object is deleted, its name is again unused and it has no contents. If a renderbuffer that is currently bound to the target GL_RENDERBUFFER is deleted, it is as though glBindRenderbuffer had been executed with a target of GL_RENDERBUFFER and a name of zero.
2391 //
2392 // If a renderbuffer object is attached to one or more attachment points in the currently bound framebuffer, then it as if glFramebufferRenderbuffer had been called, with a renderbuffer of zero for each attachment point to which this image was attached in the currently bound framebuffer. In other words, this renderbuffer object is first detached from all attachment ponits in the currently bound framebuffer. ***Note that the renderbuffer image is specifically not detached from any non-bound framebuffers***
2393 //
2394 // So, just detach this one from the bound FBO, and ignore the rest.
2395 for (int i = 0; i < n; i++) {
2396 state->detachRbo(renderbuffers[i]);
2397 }
2398 // state->removeRenderbuffers(n, renderbuffers);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002399}
2400
2401void GL2Encoder::s_glBindRenderbuffer(void* self,
2402 GLenum target, GLuint renderbuffer) {
2403 GL2Encoder* ctx = (GL2Encoder*)self;
2404 GLClientState* state = ctx->m_state;
2405
2406 SET_ERROR_IF((target != GL_RENDERBUFFER),
2407 GL_INVALID_ENUM);
2408
2409 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2410 state->bindRenderbuffer(target, renderbuffer);
2411}
2412
Lingfeng Yang69066602016-04-12 09:29:11 -07002413void GL2Encoder::s_glRenderbufferStorage(void* self,
2414 GLenum target, GLenum internalformat,
2415 GLsizei width, GLsizei height) {
2416 GL2Encoder* ctx = (GL2Encoder*) self;
2417 GLClientState* state = ctx->m_state;
2418
2419 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002420 SET_ERROR_IF(
2421 !GLESv2Validation::rboFormat(ctx, internalformat),
2422 GL_INVALID_ENUM);
Lingfeng Yang69066602016-04-12 09:29:11 -07002423
2424 state->setBoundRenderbufferFormat(internalformat);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002425 state->setBoundRenderbufferSamples(0);
2426
Lingfeng Yang69066602016-04-12 09:29:11 -07002427 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
2428 width, height);
2429}
2430
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002431void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
2432 GLenum target, GLenum attachment,
2433 GLenum renderbuffertarget, GLuint renderbuffer) {
2434 GL2Encoder* ctx = (GL2Encoder*)self;
2435 GLClientState* state = ctx->m_state;
2436
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002437 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2438 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2439 state->attachRbo(target, attachment, renderbuffer);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002440
2441 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
2442}
2443
2444void GL2Encoder::s_glGenFramebuffers(void* self,
2445 GLsizei n, GLuint* framebuffers) {
2446 GL2Encoder* ctx = (GL2Encoder*)self;
2447 GLClientState* state = ctx->m_state;
2448
2449 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2450
2451 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2452 state->addFramebuffers(n, framebuffers);
2453}
2454
2455void GL2Encoder::s_glDeleteFramebuffers(void* self,
2456 GLsizei n, const GLuint* framebuffers) {
2457 GL2Encoder* ctx = (GL2Encoder*)self;
2458 GLClientState* state = ctx->m_state;
2459
2460 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2461
2462 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2463 state->removeFramebuffers(n, framebuffers);
2464}
2465
2466void GL2Encoder::s_glBindFramebuffer(void* self,
2467 GLenum target, GLuint framebuffer) {
2468 GL2Encoder* ctx = (GL2Encoder*)self;
2469 GLClientState* state = ctx->m_state;
2470
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002471 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002472
2473 state->bindFramebuffer(target, framebuffer);
2474
2475 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
2476}
2477
2478void GL2Encoder::s_glFramebufferTexture2D(void* self,
2479 GLenum target, GLenum attachment,
2480 GLenum textarget, GLuint texture, GLint level) {
2481 GL2Encoder* ctx = (GL2Encoder*)self;
2482 GLClientState* state = ctx->m_state;
2483
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002484 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2485 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2486 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002487
2488 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
2489}
2490
2491void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2492 GLenum target, GLenum attachment,
2493 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2494 GL2Encoder* ctx = (GL2Encoder*)self;
2495 GLClientState* state = ctx->m_state;
2496
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002497 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002498
2499 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2500}
2501
2502void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2503 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2504 GL2Encoder* ctx = (GL2Encoder*)self;
2505 const GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002506 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2507 SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2508 pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE &&
2509 !state->attachmentHasObject(target, attachment),
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002510 GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002511 SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL ||
2512 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE ||
2513 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) &&
2514 (!state->attachmentHasObject(target, attachment) ||
2515 state->getBoundFramebufferAttachmentType(target, attachment) !=
2516 FBO_ATTACHMENT_TEXTURE),
2517 !state->attachmentHasObject(target, attachment) ?
2518 GL_INVALID_OPERATION : GL_INVALID_ENUM);
2519 SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2520 pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2521 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
2522 state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
2523 GL_INVALID_OPERATION);
2524 SET_ERROR_IF(state->boundFramebuffer(target) &&
2525 (attachment == GL_BACK ||
2526 attachment == GL_FRONT),
2527 GL_INVALID_OPERATION);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002528 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
2529}
Lingfeng Yang69066602016-04-12 09:29:11 -07002530
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002531bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state,
Lingfeng Yang69066602016-04-12 09:29:11 -07002532 GLenum attachment) const {
2533 FboFormatInfo fbo_format_info;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002534 state->getBoundFramebufferFormat(target, attachment, &fbo_format_info);
Lingfeng Yang69066602016-04-12 09:29:11 -07002535
2536 bool res;
2537 switch (fbo_format_info.type) {
2538 case FBO_ATTACHMENT_RENDERBUFFER:
2539 switch (fbo_format_info.rb_format) {
2540 case GL_R16F:
2541 case GL_RG16F:
Lingfeng Yang69066602016-04-12 09:29:11 -07002542 case GL_RGBA16F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002543 case GL_R32F:
2544 case GL_RG32F:
2545 case GL_RGBA32F:
2546 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002547 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002548 break;
2549 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002550 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang69066602016-04-12 09:29:11 -07002551 break;
2552 case GL_STENCIL_INDEX8:
2553 if (attachment == GL_STENCIL_ATTACHMENT) {
2554 res = true;
2555 } else {
2556 res = false;
2557 }
2558 break;
2559 default:
2560 res = true;
2561 }
2562 break;
2563 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002564 switch (fbo_format_info.tex_internalformat) {
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002565 case GL_R16F:
2566 case GL_RG16F:
2567 case GL_RGBA16F:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002568 case GL_R32F:
2569 case GL_RG32F:
2570 case GL_RGBA32F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002571 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002572 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002573 break;
2574 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002575 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002576 break;
2577 case GL_RED:
2578 case GL_RG:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002579 case GL_SRGB8:
2580 case GL_RGB32UI:
2581 case GL_RGB16UI:
2582 case GL_RGB8UI:
2583 case GL_RGB32I:
2584 case GL_RGB16I:
2585 case GL_RGB8I:
2586 case GL_R8_SNORM:
2587 case GL_RG8_SNORM:
2588 case GL_RGB8_SNORM:
2589 case GL_RGBA8_SNORM:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002590 res = false;
2591 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07002592 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002593 case GL_RGB:
2594 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07002595 switch (fbo_format_info.tex_type) {
2596 case GL_FLOAT:
2597 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002598 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002599 case GL_UNSIGNED_INT_2_10_10_10_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07002600 res = false;
2601 break;
2602 default:
2603 res = true;
2604 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002605 break;
2606 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07002607 res = true;
2608 }
2609 break;
2610 case FBO_ATTACHMENT_NONE:
2611 res = true;
2612 break;
2613 default:
2614 res = true;
2615 }
2616 return res;
2617}
2618
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002619bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const {
2620 bool res = true;
2621
2622 for (int i = 0; i < state->getMaxColorAttachments(); i++) {
2623 res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i));
2624 }
2625
2626 res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT);
2627 res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT);
2628
2629 return res;
2630}
2631
Lingfeng Yang69066602016-04-12 09:29:11 -07002632GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
2633 GL2Encoder* ctx = (GL2Encoder*)self;
2634 GLClientState* state = ctx->m_state;
2635
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002636 bool fboCompleteByCodec =
2637 ctx->checkFramebufferCompleteness(target, state);
2638
2639 if (!fboCompleteByCodec) {
2640 state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
Lingfeng Yang69066602016-04-12 09:29:11 -07002641 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2642 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002643 // double check with underlying opengl to avoid craziness.
Lingfeng Yang69066602016-04-12 09:29:11 -07002644 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002645 state->setCheckFramebufferStatus(target, host_checkstatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002646 if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE;
Lingfeng Yang69066602016-04-12 09:29:11 -07002647 return host_checkstatus;
2648 }
2649}
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002650
2651void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2652 GL2Encoder* ctx = (GL2Encoder*)self;
2653 GLClientState* state = ctx->m_state;
2654 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2655
2656 ctx->m_glGenVertexArrays_enc(self, n, arrays);
2657 for (int i = 0; i < n; i++) {
2658 ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2659 }
2660 state->addVertexArrayObjects(n, arrays);
2661}
2662
2663void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2664 GL2Encoder* ctx = (GL2Encoder*)self;
2665 GLClientState* state = ctx->m_state;
2666 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2667
2668 ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2669 for (int i = 0; i < n; i++) {
2670 ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2671 }
2672 state->removeVertexArrayObjects(n, arrays);
2673}
2674
2675void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2676 ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2677 GL2Encoder* ctx = (GL2Encoder*)self;
2678 GLClientState* state = ctx->m_state;
2679 SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2680 ctx->m_glBindVertexArray_enc(self, array);
2681 state->setVertexArrayObject(array);
2682}
2683
Lingfeng Yangfb3d2bb2017-09-07 15:02:04 -07002684void* GL2Encoder::s_glMapBufferOES(void* self, GLenum target, GLenum access) {
2685 GL2Encoder* ctx = (GL2Encoder*)self;
2686
2687 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2688
2689 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2690
2691 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2692
2693 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2694 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2695
2696 return ctx->glMapBufferRange(ctx, target, 0, buf->m_size, access);
2697}
2698
2699GLboolean GL2Encoder::s_glUnmapBufferOES(void* self, GLenum target) {
2700 GL2Encoder* ctx = (GL2Encoder*)self;
2701
2702 return ctx->glUnmapBuffer(ctx, target);
2703}
2704
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002705void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2706 GL2Encoder* ctx = (GL2Encoder*)self;
2707 GLClientState* state = ctx->m_state;
2708
2709 // begin validation (lots)
2710
2711 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2712
2713 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2714
2715 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2716
2717 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2718 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2719
2720 GLsizeiptr bufferDataSize = buf->m_size;
2721
2722 RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2723 RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2724 RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2725 RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2726
2727 RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2728 RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2729 RET_AND_SET_ERROR_IF(
2730 (access & GL_MAP_READ_BIT) &&
2731 ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2732 (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2733 (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2734 (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2735
2736 // end validation; actually do stuff now
2737
2738 buf->m_mapped = true;
2739 buf->m_mappedAccess = access;
2740 buf->m_mappedOffset = offset;
2741 buf->m_mappedLength = length;
2742
2743 char* todo = (char*)buf->m_fixedBuffer.ptr() + offset;
2744 ctx->glMapBufferRangeAEMU(
2745 ctx, target,
2746 offset, length,
2747 access,
2748 todo);
2749
2750 return todo;
2751}
2752
2753GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
2754 GL2Encoder* ctx = (GL2Encoder*)self;
2755 GLClientState* state = ctx->m_state;
2756
2757 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
2758
2759 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2760
2761 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
2762
2763 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2764 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
2765 RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
2766
Lingfeng Yang423129e2017-01-18 09:23:12 -08002767 if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
2768 // invalide index range cache here
2769 if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) {
2770 buf->m_indexRangeCache.invalidateRange(0, buf->m_size);
2771 } else {
2772 buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength);
2773 }
2774 }
2775
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002776 GLboolean host_res = GL_TRUE;
2777
2778 ctx->glUnmapBufferAEMU(
2779 ctx, target,
2780 buf->m_mappedOffset,
2781 buf->m_mappedLength,
2782 buf->m_mappedAccess,
2783 (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
2784 &host_res);
2785
2786 buf->m_mapped = false;
2787 buf->m_mappedAccess = 0;
2788 buf->m_mappedOffset = 0;
2789 buf->m_mappedLength = 0;
2790
2791 return host_res;
2792}
2793
2794void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
2795 GL2Encoder* ctx = (GL2Encoder*)self;
2796 GLClientState* state = ctx->m_state;
2797
2798 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2799
2800 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2801 SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
2802
2803 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2804 SET_ERROR_IF(!buf, GL_INVALID_VALUE);
2805 SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
2806 SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
2807
2808 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
2809 SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
2810 SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
2811
2812 GLintptr totalOffset = buf->m_mappedOffset + offset;
Lingfeng Yang423129e2017-01-18 09:23:12 -08002813
2814 buf->m_indexRangeCache.invalidateRange(totalOffset, length);
2815
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002816 ctx->glFlushMappedBufferRangeAEMU(
2817 ctx, target,
2818 totalOffset,
2819 length,
2820 buf->m_mappedAccess,
2821 (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
2822}
2823
2824void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
2825 GL2Encoder* ctx = (GL2Encoder*)self;
2826 GLClientState* state = ctx->m_state;
2827
2828 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2829 // Filter compressed formats support.
2830 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
2831 // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
2832 GLint max_texture_size;
2833 GLint max_cube_map_texture_size;
2834 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2835 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2836 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2837 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2838 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2839 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2840 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2841 SET_ERROR_IF(border, GL_INVALID_VALUE);
2842 // If unpack buffer is nonzero, verify unmapped state.
2843 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2844 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2845 // If unpack buffer is nonzero, verify buffer data fits.
2846 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2847 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2848 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2849 GL_INVALID_OPERATION);
2850 // TODO: Fix:
2851 // If |imageSize| is inconsistent with compressed dimensions.
2852 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
2853
2854 GLenum stateTarget = target;
2855 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2856 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2857 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2858 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2859 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2860 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2861 stateTarget = GL_TEXTURE_CUBE_MAP;
2862 state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
2863 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2864
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002865 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2866 ctx->override2DTextureTarget(target);
2867 }
2868
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002869 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2870 ctx->glCompressedTexImage2DOffsetAEMU(
2871 ctx, target, level, internalformat,
2872 width, height, border,
2873 imageSize, (uintptr_t)data);
2874 } else {
2875 ctx->m_glCompressedTexImage2D_enc(
2876 ctx, target, level, internalformat,
2877 width, height, border,
2878 imageSize, data);
2879 }
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002880
2881 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2882 ctx->restore2DTextureTarget(target);
2883 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002884}
2885
2886void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
2887 GL2Encoder* ctx = (GL2Encoder*)self;
2888 GLClientState* state = ctx->m_state;
2889
2890 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2891 // If unpack buffer is nonzero, verify unmapped state.
2892 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2893 GLint max_texture_size;
2894 GLint max_cube_map_texture_size;
2895 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2896 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2897 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2898 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2899 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2900 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2901 // If unpack buffer is nonzero, verify buffer data fits.
2902 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2903 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2904 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2905 GL_INVALID_OPERATION);
2906 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2907
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002908 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2909 ctx->override2DTextureTarget(target);
2910 }
2911
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002912 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2913 ctx->glCompressedTexSubImage2DOffsetAEMU(
2914 ctx, target, level,
2915 xoffset, yoffset,
2916 width, height, format,
2917 imageSize, (uintptr_t)data);
2918 } else {
2919 ctx->m_glCompressedTexSubImage2D_enc(
2920 ctx, target, level,
2921 xoffset, yoffset,
2922 width, height, format,
2923 imageSize, data);
2924 }
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002925
2926 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2927 ctx->restore2DTextureTarget(target);
2928 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002929}
2930
2931void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
2932 GL2Encoder* ctx = (GL2Encoder*)self;
2933 GLClientState* state = ctx->m_state;
2934
2935 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2936
2937 // Only works with certain targets
2938 SET_ERROR_IF(
2939 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2940 target == GL_SHADER_STORAGE_BUFFER ||
2941 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2942 target == GL_UNIFORM_BUFFER),
2943 GL_INVALID_ENUM);
2944
2945 // Can't exceed range
2946 SET_ERROR_IF(index < 0 ||
2947 index >= state->getMaxIndexedBufferBindings(target),
2948 GL_INVALID_VALUE);
2949 SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
2950 SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
2951 target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
2952 (size % 4 || offset % 4),
2953 GL_INVALID_VALUE);
2954
2955 GLint ssbo_offset_align, ubo_offset_align;
2956 ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
2957 ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
2958 SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
2959 offset % ssbo_offset_align,
2960 GL_INVALID_VALUE);
2961 SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
2962 offset % ubo_offset_align,
2963 GL_INVALID_VALUE);
2964
2965 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002966 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002967 state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0);
2968 ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size);
2969}
2970
2971void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
2972 GL2Encoder* ctx = (GL2Encoder*)self;
2973 GLClientState* state = ctx->m_state;
2974
2975 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2976
2977 // Only works with certain targets
2978 SET_ERROR_IF(
2979 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2980 target == GL_SHADER_STORAGE_BUFFER ||
2981 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2982 target == GL_UNIFORM_BUFFER),
2983 GL_INVALID_ENUM);
2984 // Can't exceed range
2985 SET_ERROR_IF(index < 0 ||
2986 index >= state->getMaxIndexedBufferBindings(target),
2987 GL_INVALID_VALUE);
2988
2989 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002990 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002991 BufferData* buf = ctx->getBufferDataById(buffer);
2992 state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0);
2993 ctx->m_glBindBufferBase_enc(self, target, index, buffer);
2994}
2995
2996void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
2997 GL2Encoder* ctx = (GL2Encoder*)self;
2998 GLClientState* state = ctx->m_state;
2999
3000 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
3001 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
3002 SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
3003 readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
3004 readtarget == GL_DRAW_INDIRECT_BUFFER ||
3005 readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
3006 SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
3007 writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
3008 writetarget == GL_DRAW_INDIRECT_BUFFER ||
3009 writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
3010 SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
3011 SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
3012 SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
3013 SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
3014 SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
3015 SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
3016 SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
3017 SET_ERROR_IF(
3018 ctx->getBufferData(readtarget) &&
3019 (readoffset + size > ctx->getBufferData(readtarget)->m_size),
3020 GL_INVALID_VALUE);
3021 SET_ERROR_IF(
3022 ctx->getBufferData(writetarget) &&
3023 (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
3024 GL_INVALID_VALUE);
3025 SET_ERROR_IF(readtarget == writetarget &&
3026 !((writeoffset >= readoffset + size) ||
3027 (readoffset >= writeoffset + size)),
3028 GL_INVALID_VALUE);
3029
3030 ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
3031}
3032
3033void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
3034 GL2Encoder* ctx = (GL2Encoder*)self;
3035
3036 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3037 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003038 target != GL_ARRAY_BUFFER &&
3039 target != GL_ELEMENT_ARRAY_BUFFER &&
3040 target != GL_COPY_READ_BUFFER &&
3041 target != GL_COPY_WRITE_BUFFER &&
3042 target != GL_PIXEL_PACK_BUFFER &&
3043 target != GL_PIXEL_UNPACK_BUFFER &&
3044 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
3045 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003046 GL_INVALID_ENUM);
3047 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
3048 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003049 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
3050 pname != GL_BUFFER_MAPPED &&
3051 pname != GL_BUFFER_SIZE &&
3052 pname != GL_BUFFER_USAGE &&
3053 pname != GL_BUFFER_MAP_LENGTH &&
3054 pname != GL_BUFFER_MAP_OFFSET,
3055 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003056
3057 if (!params) return;
3058
3059 BufferData* buf = ctx->getBufferData(target);
3060
3061 switch (pname) {
3062 case GL_BUFFER_ACCESS_FLAGS:
3063 *params = buf ? buf->m_mappedAccess : 0;
3064 break;
3065 case GL_BUFFER_MAPPED:
3066 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3067 break;
3068 case GL_BUFFER_SIZE:
3069 *params = buf ? buf->m_size : 0;
3070 break;
3071 case GL_BUFFER_USAGE:
3072 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3073 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003074 case GL_BUFFER_MAP_LENGTH:
3075 *params = buf ? buf->m_mappedLength : 0;
3076 break;
3077 case GL_BUFFER_MAP_OFFSET:
3078 *params = buf ? buf->m_mappedOffset : 0;
3079 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003080 default:
3081 break;
3082 }
3083}
3084
3085void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
3086 GL2Encoder* ctx = (GL2Encoder*)self;
3087
3088 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3089 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003090 target != GL_ARRAY_BUFFER &&
3091 target != GL_ELEMENT_ARRAY_BUFFER &&
3092 target != GL_COPY_READ_BUFFER &&
3093 target != GL_COPY_WRITE_BUFFER &&
3094 target != GL_PIXEL_PACK_BUFFER &&
3095 target != GL_PIXEL_UNPACK_BUFFER &&
3096 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
3097 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003098 GL_INVALID_ENUM);
3099 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
3100 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003101 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
3102 pname != GL_BUFFER_MAPPED &&
3103 pname != GL_BUFFER_SIZE &&
3104 pname != GL_BUFFER_USAGE &&
3105 pname != GL_BUFFER_MAP_LENGTH &&
3106 pname != GL_BUFFER_MAP_OFFSET,
3107 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003108
3109 if (!params) return;
3110
3111 BufferData* buf = ctx->getBufferData(target);
3112
3113 switch (pname) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003114 case GL_BUFFER_ACCESS_FLAGS:
3115 *params = buf ? buf->m_mappedAccess : 0;
3116 break;
3117 case GL_BUFFER_MAPPED:
3118 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3119 break;
3120 case GL_BUFFER_SIZE:
3121 *params = buf ? buf->m_size : 0;
3122 break;
3123 case GL_BUFFER_USAGE:
3124 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3125 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003126 case GL_BUFFER_MAP_LENGTH:
3127 *params = buf ? buf->m_mappedLength : 0;
3128 break;
3129 case GL_BUFFER_MAP_OFFSET:
3130 *params = buf ? buf->m_mappedOffset : 0;
3131 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003132 default:
3133 break;
3134 }
3135}
3136
3137void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
3138 GL2Encoder* ctx = (GL2Encoder*)self;
3139 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3140 SET_ERROR_IF(
3141 target == GL_ATOMIC_COUNTER_BUFFER ||
3142 target == GL_DISPATCH_INDIRECT_BUFFER ||
3143 target == GL_DRAW_INDIRECT_BUFFER ||
3144 target == GL_SHADER_STORAGE_BUFFER,
3145 GL_INVALID_ENUM);
3146 SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
3147 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
3148 if (!params) return;
3149
3150 BufferData* buf = ctx->getBufferData(target);
3151
3152 if (!buf || !buf->m_mapped) { *params = NULL; return; }
3153
3154 *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
3155}
3156
3157static const char* const kNameDelimiter = ";";
3158
3159static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
3160
3161#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
3162
3163 std::string packed;
3164 // validate the array of char[]'s
3165 const char* currName;
3166 for (GLsizei i = 0; i < count; i++) {
3167 currName = names[i];
3168 VALIDATE(!currName, GL_INVALID_OPERATION);
3169 // check if has reasonable size
3170 size_t len = strlen(currName);
3171 VALIDATE(!len, GL_INVALID_OPERATION);
3172 // check for our delimiter, which if present
3173 // in the name, means an invalid name anyway.
3174 VALIDATE(strstr(currName, kNameDelimiter),
3175 GL_INVALID_OPERATION);
3176 packed += currName;
3177 packed += ";";
3178 }
3179
3180 *err_out = GL_NO_ERROR;
3181 return packed;
3182}
3183
3184void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
3185 GL2Encoder* ctx = (GL2Encoder*)self;
3186
3187 if (!uniformCount) return;
3188
3189 GLint err = GL_NO_ERROR;
3190 std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
3191 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3192
3193 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
3194 std::vector<int> arrIndices;
3195 for (size_t i = 0; i < uniformCount; i++) {
3196 int err;
3197 arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
3198 if (err) {
3199 ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
3200 return;
3201 }
3202 }
3203
3204 ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
3205
3206 for (int i = 0; i < uniformCount; i++) {
3207 if (uniformIndices[i] >= 0 && needLocationWAR) {
3208 uniformIndices[i] =
3209 ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
3210 }
3211 }
3212}
3213
3214void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
3215 GL2Encoder *ctx = (GL2Encoder*)self;
3216 GLClientState* state = ctx->m_state;
3217 GLSharedGroupPtr shared = ctx->m_shared;
3218
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003219 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003220 ctx->m_glUniform1ui_enc(self, hostLoc, v0);
3221
3222 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003223 if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003224 GLenum origActiveTexture = state->getActiveTextureUnit();
3225 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
3226 ctx->m_glActiveTexture_enc(self, origActiveTexture);
3227 }
3228 state->setActiveTextureUnit(origActiveTexture);
3229 }
3230}
3231
3232void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) {
3233 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003234 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003235 ctx->m_glUniform2ui_enc(self, hostLoc, v0, v1);
3236}
3237
3238void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) {
3239 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003240 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003241 ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2);
3242}
3243
3244void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) {
3245 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003246 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003247 ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3);
3248}
3249
3250void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3251 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003252 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003253 ctx->m_glUniform1uiv_enc(self, hostLoc, count, value);
3254}
3255
3256void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3257 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003258 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003259 ctx->m_glUniform2uiv_enc(self, hostLoc, count, value);
3260}
3261
3262void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3263 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003264 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003265 ctx->m_glUniform3uiv_enc(self, hostLoc, count, value);
3266}
3267
3268void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3269 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003270 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003271 ctx->m_glUniform4uiv_enc(self, hostLoc, count, value);
3272}
3273
3274void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3275 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003276 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003277 ctx->m_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value);
3278}
3279
3280void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3281 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003282 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003283 ctx->m_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value);
3284}
3285
3286void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3287 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003288 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003289 ctx->m_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value);
3290}
3291
3292void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3293 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003294 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003295 ctx->m_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value);
3296}
3297
3298void GL2Encoder::s_glUniformMatrix3x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3299 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003300 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003301 ctx->m_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value);
3302}
3303
3304void GL2Encoder::s_glUniformMatrix4x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3305 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003306 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003307 ctx->m_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value);
3308}
3309
3310void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3311 GL2Encoder *ctx = (GL2Encoder*)self;
3312 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3313 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3314 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3315 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3316 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3317 ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3318}
3319
3320void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3321 GL2Encoder* ctx = (GL2Encoder*)self;
3322 GLClientState* state = ctx->m_state;
3323
3324 // refresh client state's # active uniforms in this block
3325 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3326 // TODO if worth it: cache uniform count and other params,
3327 // invalidate on program relinking.
3328 GLint numActiveUniforms;
3329 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3330 program, uniformBlockIndex,
3331 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3332 &numActiveUniforms);
3333 ctx->m_state->setNumActiveUniformsInUniformBlock(
3334 program, uniformBlockIndex, numActiveUniforms);
3335 }
3336
3337 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3338 program, uniformBlockIndex,
3339 pname, params);
3340}
3341
3342void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3343 GL2Encoder *ctx = (GL2Encoder *)self;
3344 assert(ctx->m_state);
3345 GLint maxIndex;
3346 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3347 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3348
3349 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3350 ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3351 }
3352}
3353
3354void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3355 GL2Encoder *ctx = (GL2Encoder *)self;
3356 assert(ctx->m_state);
3357 GLint maxIndex;
3358 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3359 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3360
3361 if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3362 ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3363 }
3364}
3365
3366void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3367 GL2Encoder *ctx = (GL2Encoder *)self;
3368 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003369 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003370 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
3371 SET_ERROR_IF(
3372 !(type == GL_BYTE ||
3373 type == GL_UNSIGNED_BYTE ||
3374 type == GL_SHORT ||
3375 type == GL_UNSIGNED_SHORT ||
3376 type == GL_INT ||
3377 type == GL_UNSIGNED_INT),
3378 GL_INVALID_ENUM);
3379 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
3380
3381 ctx->m_state->setVertexAttribBinding(index, index);
3382 ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true);
3383 GLsizei effectiveStride = stride;
3384 if (stride == 0) {
3385 effectiveStride = glSizeof(type) * size;
3386 }
3387 ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride);
3388
3389 if (ctx->m_state->currentArrayVbo() != 0) {
3390 ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer);
3391 } else {
3392 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION);
3393 // wait for client-array handler
3394 }
3395}
3396
3397void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) {
3398 GL2Encoder *ctx = (GL2Encoder *)self;
3399 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003400 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003401 ctx->m_state->setVertexAttribBinding(index, index);
3402 ctx->m_state->setVertexBindingDivisor(index, divisor);
3403 ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor);
3404}
3405
3406void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3407 GLenum target, GLsizei samples, GLenum internalformat,
3408 GLsizei width, GLsizei height) {
3409 GL2Encoder *ctx = (GL2Encoder *)self;
3410 GLClientState* state = ctx->m_state;
3411
3412 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3413 SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3414
3415 GLint max_samples;
3416 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3417 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3418
3419 state->setBoundRenderbufferFormat(internalformat);
3420 state->setBoundRenderbufferSamples(samples);
3421 ctx->m_glRenderbufferStorageMultisample_enc(
3422 self, target, samples, internalformat, width, height);
3423}
3424
3425void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3426 GL2Encoder* ctx = (GL2Encoder*)self;
3427 SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3428 SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3429 for (int i = 0; i < n; i++) {
3430 SET_ERROR_IF(
3431 bufs[i] != GL_NONE &&
3432 bufs[i] != GL_BACK &&
3433 glUtilsColorAttachmentIndex(bufs[i]) == -1,
3434 GL_INVALID_ENUM);
3435 SET_ERROR_IF(
3436 !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3437 glUtilsColorAttachmentIndex(bufs[i]) != -1,
3438 GL_INVALID_OPERATION);
3439 SET_ERROR_IF(
3440 ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3441 ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3442 glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3443 (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3444 bufs[i] != GL_NONE)),
3445 GL_INVALID_OPERATION);
3446 }
3447
3448 ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3449}
3450
3451void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3452 GL2Encoder* ctx = (GL2Encoder*)self;
3453
3454 SET_ERROR_IF(
3455 glUtilsColorAttachmentIndex(src) != -1 &&
3456 (glUtilsColorAttachmentIndex(src) >=
3457 ctx->m_state->getMaxColorAttachments()),
3458 GL_INVALID_OPERATION);
3459 SET_ERROR_IF(
3460 src != GL_NONE &&
3461 src != GL_BACK &&
3462 src > GL_COLOR_ATTACHMENT0 &&
3463 src < GL_DEPTH_ATTACHMENT &&
3464 (src - GL_COLOR_ATTACHMENT0) >
3465 ctx->m_state->getMaxColorAttachments(),
3466 GL_INVALID_OPERATION);
3467 SET_ERROR_IF(
3468 src != GL_NONE &&
3469 src != GL_BACK &&
3470 glUtilsColorAttachmentIndex(src) == -1,
3471 GL_INVALID_ENUM);
3472 SET_ERROR_IF(
3473 !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3474 src != GL_NONE &&
3475 src != GL_BACK,
3476 GL_INVALID_OPERATION);
3477 SET_ERROR_IF(
3478 ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3479 src != GL_NONE &&
3480 glUtilsColorAttachmentIndex(src) == -1,
3481 GL_INVALID_OPERATION);
3482
3483 ctx->m_glReadBuffer_enc(ctx, src);
3484}
3485
3486void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3487 GL2Encoder* ctx = (GL2Encoder*)self;
3488 GLClientState* state = ctx->m_state;
3489
3490 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3491 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3492 GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3493 SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3494 lastBoundTarget != GL_TEXTURE_3D,
3495 GL_INVALID_OPERATION);
3496 state->attachTextureObject(target, attachment, texture);
3497
3498 GLint max3DTextureSize;
3499 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3500 SET_ERROR_IF(
3501 layer >= max3DTextureSize,
3502 GL_INVALID_VALUE);
3503
3504 ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3505}
3506
3507void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3508 GL2Encoder* ctx = (GL2Encoder*)self;
3509 GLClientState* state = ctx->m_state;
3510
3511 SET_ERROR_IF(
3512 target != GL_TEXTURE_2D &&
3513 target != GL_TEXTURE_CUBE_MAP,
3514 GL_INVALID_ENUM);
3515 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3516 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3517 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3518 SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3519 GL_INVALID_OPERATION);
3520 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3521
3522 state->setBoundTextureInternalFormat(target, internalformat);
3523 state->setBoundTextureDims(target, -1, width, height, 1);
3524 state->setBoundTextureImmutableFormat(target);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003525
3526 if (target == GL_TEXTURE_2D) {
3527 ctx->override2DTextureTarget(target);
3528 }
3529
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003530 ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003531
3532 if (target == GL_TEXTURE_2D) {
3533 ctx->restore2DTextureTarget(target);
3534 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003535}
3536
3537void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3538 GL2Encoder* ctx = (GL2Encoder*)self;
3539
3540 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3541
3542 GLint maxCount = 0;
3543 ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3544
3545 SET_ERROR_IF(
3546 bufferMode == GL_SEPARATE_ATTRIBS &&
3547 maxCount < count,
3548 GL_INVALID_VALUE);
3549 SET_ERROR_IF(
3550 bufferMode != GL_INTERLEAVED_ATTRIBS &&
3551 bufferMode != GL_SEPARATE_ATTRIBS,
3552 GL_INVALID_ENUM);
3553
3554 if (!count) return;
3555
3556 GLint err = GL_NO_ERROR;
3557 std::string packed = packVarNames(count, varyings, &err);
3558 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3559
3560 ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3561}
3562
3563void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3564 GL2Encoder* ctx = (GL2Encoder*)self;
3565 GLClientState* state = ctx->m_state;
3566 ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3567 state->setTransformFeedbackActiveUnpaused(true);
3568}
3569
3570void GL2Encoder::s_glEndTransformFeedback(void* self) {
3571 GL2Encoder* ctx = (GL2Encoder*)self;
3572 GLClientState* state = ctx->m_state;
3573 ctx->m_glEndTransformFeedback_enc(ctx);
3574 state->setTransformFeedbackActiveUnpaused(false);
3575}
3576
3577void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3578 GL2Encoder* ctx = (GL2Encoder*)self;
3579 GLClientState* state = ctx->m_state;
3580 ctx->m_glPauseTransformFeedback_enc(ctx);
3581 state->setTransformFeedbackActiveUnpaused(false);
3582}
3583
3584void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3585 GL2Encoder* ctx = (GL2Encoder*)self;
3586 GLClientState* state = ctx->m_state;
3587 ctx->m_glResumeTransformFeedback_enc(ctx);
3588 state->setTransformFeedbackActiveUnpaused(true);
3589}
3590
3591void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3592 GLsizei width, GLsizei height, GLsizei depth,
3593 GLint border, GLenum format, GLenum type, const GLvoid* data) {
3594 GL2Encoder* ctx = (GL2Encoder*)self;
3595 GLClientState* state = ctx->m_state;
3596
3597 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3598 target != GL_TEXTURE_2D_ARRAY,
3599 GL_INVALID_ENUM);
3600 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3601 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3602
3603 // If unpack buffer is nonzero, verify unmapped state.
3604 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3605
3606 GLint max_texture_size;
3607 GLint max_3d_texture_size;
3608 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3609 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3610 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3611 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3612 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3613
3614 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3615 SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3616 SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3617 SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3618 SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3619 SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3620 SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3621 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3622 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3623 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3624 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3625 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3626 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3627 GL_INVALID_OPERATION);
3628 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3629 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3630 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3631 glSizeof(type)),
3632 GL_INVALID_OPERATION);
3633 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3634
3635 state->setBoundTextureInternalFormat(target, internalFormat);
3636 state->setBoundTextureFormat(target, format);
3637 state->setBoundTextureType(target, type);
3638 state->setBoundTextureDims(target, level, width, height, depth);
3639
3640 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3641 ctx->glTexImage3DOffsetAEMU(
3642 ctx, target, level, internalFormat,
3643 width, height, depth,
3644 border, format, type, (uintptr_t)data);
3645 } else {
3646 ctx->m_glTexImage3D_enc(ctx,
3647 target, level, internalFormat,
3648 width, height, depth,
3649 border, format, type, data);
3650 }
3651}
3652
3653void GL2Encoder::s_glTexSubImage3D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* data) {
3654 GL2Encoder* ctx = (GL2Encoder*)self;
3655 GLClientState* state = ctx->m_state;
3656
3657 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3658 target != GL_TEXTURE_2D_ARRAY,
3659 GL_INVALID_ENUM);
3660 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3661 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3662 // If unpack buffer is nonzero, verify unmapped state.
3663 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3664 GLint max_texture_size;
3665 GLint max_3d_texture_size;
3666 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3667 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3668 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3669 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3670 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3671 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3672 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3673 GLuint tex = state->getBoundTexture(target);
3674 GLsizei neededWidth = xoffset + width;
3675 GLsizei neededHeight = yoffset + height;
3676 GLsizei neededDepth = zoffset + depth;
3677
3678 SET_ERROR_IF(tex &&
3679 (neededWidth > state->queryTexWidth(level, tex) ||
3680 neededHeight > state->queryTexHeight(level, tex) ||
3681 neededDepth > state->queryTexDepth(level, tex)),
3682 GL_INVALID_VALUE);
3683 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3684 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3685 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3686 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3687 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3688 GL_INVALID_OPERATION);
3689 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3690 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3691 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3692 glSizeof(type)),
3693 GL_INVALID_OPERATION);
3694 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
3695 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3696
3697 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3698 ctx->glTexSubImage3DOffsetAEMU(ctx,
3699 target, level,
3700 xoffset, yoffset, zoffset,
3701 width, height, depth,
3702 format, type, (uintptr_t)data);
3703 } else {
3704 ctx->m_glTexSubImage3D_enc(ctx,
3705 target, level,
3706 xoffset, yoffset, zoffset,
3707 width, height, depth,
3708 format, type, data);
3709 }
3710}
3711
3712void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
3713 GL2Encoder* ctx = (GL2Encoder*)self;
3714 GLClientState* state = ctx->m_state;
3715
3716 // Filter compressed formats support.
3717 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3718 // If unpack buffer is nonzero, verify unmapped state.
3719 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3720 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3721 SET_ERROR_IF(border, GL_INVALID_VALUE);
3722 // If unpack buffer is nonzero, verify buffer data fits.
3723 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3724 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3725 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3726 GL_INVALID_OPERATION);
3727 // TODO: Fix:
3728 // If |imageSize| is too small for compressed dimensions.
3729 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
3730 state->setBoundTextureInternalFormat(target, (GLint)internalformat);
3731 state->setBoundTextureDims(target, level, width, height, depth);
3732
3733 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3734 ctx->glCompressedTexImage3DOffsetAEMU(
3735 ctx, target, level, internalformat,
3736 width, height, depth, border,
3737 imageSize, (uintptr_t)data);
3738 } else {
3739 ctx->m_glCompressedTexImage3D_enc(
3740 ctx, target, level, internalformat,
3741 width, height, depth, border,
3742 imageSize, data);
3743 }
3744}
3745
3746void GL2Encoder::s_glCompressedTexSubImage3D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) {
3747 GL2Encoder* ctx = (GL2Encoder*)self;
3748 GLClientState* state = ctx->m_state;
3749
3750 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3751 // If unpack buffer is nonzero, verify unmapped state.
3752 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3753 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3754 // If unpack buffer is nonzero, verify buffer data fits.
3755 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3756 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3757 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3758 GL_INVALID_OPERATION);
3759 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3760
3761 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3762 ctx->glCompressedTexSubImage3DOffsetAEMU(
3763 ctx, target, level,
3764 xoffset, yoffset, zoffset,
3765 width, height, depth,
3766 format, imageSize, (uintptr_t)data);
3767 } else {
3768 ctx->m_glCompressedTexSubImage3D_enc(
3769 ctx, target, level,
3770 xoffset, yoffset, zoffset,
3771 width, height, depth,
3772 format, imageSize, data);
3773
3774 }
3775}
3776
3777void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
3778 GL2Encoder* ctx = (GL2Encoder*)self;
3779 GLClientState* state = ctx->m_state;
3780 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3781 target != GL_TEXTURE_2D_ARRAY,
3782 GL_INVALID_ENUM);
3783 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3784 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3785 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3786 SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
3787 GL_INVALID_OPERATION);
3788 SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
3789 GL_INVALID_OPERATION);
3790 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3791
3792 state->setBoundTextureInternalFormat(target, internalformat);
3793 state->setBoundTextureDims(target, -1, width, height, depth);
3794 state->setBoundTextureImmutableFormat(target);
3795 ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
3796 state->setBoundTextureImmutableFormat(target);
3797}
3798
3799void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
3800 GL2Encoder *ctx = (GL2Encoder *)self;
3801 assert(ctx->m_state != NULL);
3802 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3803 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3804
3805 bool has_client_vertex_arrays = false;
3806 bool has_indirect_arrays = false;
3807 ctx->getVBOUsage(&has_client_vertex_arrays,
3808 &has_indirect_arrays);
3809
3810 if (has_client_vertex_arrays ||
3811 (!has_client_vertex_arrays &&
3812 !has_indirect_arrays)) {
3813 ctx->sendVertexAttributes(first, count, true, primcount);
3814 ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
3815 } else {
3816 ctx->sendVertexAttributes(0, count, false, primcount);
3817 ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
3818 }
3819 ctx->m_stream->flush();
3820}
3821
3822void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
3823{
3824
3825 GL2Encoder *ctx = (GL2Encoder *)self;
3826 assert(ctx->m_state != NULL);
3827 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3828 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3829 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3830 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3831
3832 bool has_client_vertex_arrays = false;
3833 bool has_indirect_arrays = false;
3834 int nLocations = ctx->m_state->nLocations();
3835 GLintptr offset = 0;
3836
3837 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3838
3839 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3840 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3841 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3842 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3843 }
3844
3845 BufferData* buf = NULL;
3846 int minIndex = 0, maxIndex = 0;
3847
3848 // For validation/immediate index array purposes,
3849 // we need the min/max vertex index of the index array.
3850 // If the VBO != 0, this may not be the first time we have
3851 // used this particular index buffer. getBufferIndexRange
3852 // can more quickly get min/max vertex index by
3853 // caching previous results.
3854 if (ctx->m_state->currentIndexVbo() != 0) {
3855 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3856 offset = (GLintptr)indices;
3857 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3858 ctx->getBufferIndexRange(buf,
3859 indices,
3860 type,
3861 (size_t)count,
3862 (size_t)offset,
3863 &minIndex, &maxIndex);
3864 } else {
3865 // In this case, the |indices| field holds a real
3866 // array, so calculate the indices now. They will
3867 // also be needed to know how much data to
3868 // transfer to host.
3869 ctx->calcIndexRange(indices,
3870 type,
3871 count,
3872 &minIndex,
3873 &maxIndex);
3874 }
3875
Lingfeng Yang26e629a2018-10-13 20:00:12 -07003876 if (count == 0) return;
3877
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003878 bool adjustIndices = true;
3879 if (ctx->m_state->currentIndexVbo() != 0) {
3880 if (!has_client_vertex_arrays) {
3881 ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
3882 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3883 ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
3884 ctx->flushDrawCall();
3885 adjustIndices = false;
3886 } else {
3887 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3888 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3889 }
3890 }
3891 if (adjustIndices) {
3892 void *adjustedIndices =
3893 ctx->recenterIndices(indices,
3894 type,
3895 count,
3896 minIndex);
3897
3898 if (has_indirect_arrays || 1) {
3899 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
3900 ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
3901 ctx->m_stream->flush();
3902 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3903 if(!has_indirect_arrays) {
3904 //ALOGD("unoptimized drawelements !!!\n");
3905 }
3906 } else {
3907 // we are all direct arrays and immidate mode index array -
3908 // rebuild the arrays and the index array;
3909 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3910 }
3911 }
3912}
3913
3914void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
3915{
3916
3917 GL2Encoder *ctx = (GL2Encoder *)self;
3918 assert(ctx->m_state != NULL);
3919 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3920 SET_ERROR_IF(end < start, GL_INVALID_VALUE);
3921 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3922 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3923 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3924
3925 bool has_client_vertex_arrays = false;
3926 bool has_indirect_arrays = false;
3927 int nLocations = ctx->m_state->nLocations();
3928 GLintptr offset = 0;
3929
3930 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3931
3932 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3933 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3934 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3935 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3936 }
3937
3938 BufferData* buf = NULL;
3939 int minIndex = 0, maxIndex = 0;
3940
3941 // For validation/immediate index array purposes,
3942 // we need the min/max vertex index of the index array.
3943 // If the VBO != 0, this may not be the first time we have
3944 // used this particular index buffer. getBufferIndexRange
3945 // can more quickly get min/max vertex index by
3946 // caching previous results.
3947 if (ctx->m_state->currentIndexVbo() != 0) {
3948 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3949 offset = (GLintptr)indices;
3950 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3951 ctx->getBufferIndexRange(buf,
3952 indices,
3953 type,
3954 (size_t)count,
3955 (size_t)offset,
3956 &minIndex, &maxIndex);
3957 } else {
3958 // In this case, the |indices| field holds a real
3959 // array, so calculate the indices now. They will
3960 // also be needed to know how much data to
3961 // transfer to host.
3962 ctx->calcIndexRange(indices,
3963 type,
3964 count,
3965 &minIndex,
3966 &maxIndex);
3967 }
3968
Lingfeng Yang26e629a2018-10-13 20:00:12 -07003969 if (count == 0) return;
3970
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003971 bool adjustIndices = true;
3972 if (ctx->m_state->currentIndexVbo() != 0) {
3973 if (!has_client_vertex_arrays) {
3974 ctx->sendVertexAttributes(0, maxIndex + 1, false);
3975 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3976 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
3977 ctx->flushDrawCall();
3978 adjustIndices = false;
3979 } else {
3980 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3981 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3982 }
3983 }
3984 if (adjustIndices) {
3985 void *adjustedIndices =
3986 ctx->recenterIndices(indices,
3987 type,
3988 count,
3989 minIndex);
3990
3991 if (has_indirect_arrays || 1) {
3992 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
3993 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
3994 ctx->m_stream->flush();
3995 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3996 if(!has_indirect_arrays) {
3997 //ALOGD("unoptimized drawelements !!!\n");
3998 }
3999 } else {
4000 // we are all direct arrays and immidate mode index array -
4001 // rebuild the arrays and the index array;
4002 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
4003 }
4004 }
4005}
4006
4007// struct GLStringKey {
4008// GLenum name;
4009// GLuint index;
4010// };
4011//
4012// struct GLStringKeyCompare {
4013// bool operator() (const GLStringKey& a,
4014// const GLStringKey& b) const {
4015// if (a.name != b.name) return a.name < b.name;
4016// if (a.index != b.index) return a.index < b.index;
4017// return false;
4018// }
4019// };
4020//
4021// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
4022//
4023// static GLStringStore sGLStringStore;
4024// bool sGLStringStoreInitialized = false;
4025
4026const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
4027 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004028 const GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004029
4030 RET_AND_SET_ERROR_IF(
4031 name != GL_VENDOR &&
4032 name != GL_RENDERER &&
4033 name != GL_VERSION &&
4034 name != GL_EXTENSIONS,
4035 GL_INVALID_ENUM,
4036 retval);
4037
4038 RET_AND_SET_ERROR_IF(
Lingfeng Yang44209df2018-09-21 10:04:17 -07004039 (name == GL_VENDOR ||
4040 name == GL_RENDERER ||
4041 name == GL_VERSION) &&
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004042 index != 0,
4043 GL_INVALID_VALUE,
4044 retval);
4045
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004046 RET_AND_SET_ERROR_IF(
4047 name == GL_EXTENSIONS &&
4048 index >= ctx->m_currExtensionsArray.size(),
4049 GL_INVALID_VALUE,
4050 retval);
4051
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004052 switch (name) {
4053 case GL_VENDOR:
4054 retval = gVendorString;
4055 break;
4056 case GL_RENDERER:
4057 retval = gRendererString;
4058 break;
4059 case GL_VERSION:
4060 retval = gVersionString;
4061 break;
4062 case GL_EXTENSIONS:
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004063 retval = (const GLubyte*)(ctx->m_currExtensionsArray[index].c_str());
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004064 break;
4065 }
4066
4067 return retval;
4068}
4069
4070void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
4071 GL2Encoder *ctx = (GL2Encoder *)self;
4072
4073 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
4074
4075 GLint linkStatus = 0;
4076 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
4077 GLint properLength = 0;
4078 ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
4079
4080 SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
4081 SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
4082
4083 ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
4084}
4085
4086void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
4087 GL2Encoder *ctx = (GL2Encoder *)self;
4088
4089 SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
4090 SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
4091 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
4092 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
4093 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
4094 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
4095 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
4096 ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
4097 GL_INVALID_OPERATION);
4098 /*
4099GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is a fixed point normalized surface and format and type are neither GL_RGBA and GL_UNSIGNED_BYTE, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
4100
4101GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is a floating point surface and format and type are neither GL_RGBA and GL_FLOAT, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
4102
4103GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is a signed integer surface and format and type are neither GL_RGBA_INTEGER and GL_INT, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
4104
4105GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is an unsigned integer surface and format and type are neither GL_RGBA_INTEGER and GL_UNSIGNED_INT, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
4106*/
4107
4108 FboFormatInfo fbo_format_info;
4109 ctx->m_state->getBoundFramebufferFormat(
4110 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
4111 SET_ERROR_IF(
4112 fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4113 !GLESv2Validation::readPixelsFboFormatMatch(
4114 format, type, fbo_format_info.tex_type),
4115 GL_INVALID_OPERATION);
4116
4117 if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
4118 ctx->glReadPixelsOffsetAEMU(
4119 ctx, x, y, width, height,
4120 format, type, (uintptr_t)pixels);
4121 } else {
4122 ctx->m_glReadPixels_enc(
4123 ctx, x, y, width, height,
4124 format, type, pixels);
4125 }
4126}
4127
4128// Track enabled state for some things like:
4129// - Primitive restart
4130void GL2Encoder::s_glEnable(void* self, GLenum what) {
4131 GL2Encoder *ctx = (GL2Encoder *)self;
4132
4133 switch (what) {
4134 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4135 ctx->m_primitiveRestartEnabled = true;
4136 break;
4137 }
4138
4139 ctx->m_glEnable_enc(ctx, what);
4140}
4141
4142void GL2Encoder::s_glDisable(void* self, GLenum what) {
4143 GL2Encoder *ctx = (GL2Encoder *)self;
4144
4145 switch (what) {
4146 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4147 ctx->m_primitiveRestartEnabled = false;
4148 break;
4149 }
4150
4151 ctx->m_glDisable_enc(ctx, what);
4152}
4153
4154void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
4155 GL2Encoder *ctx = (GL2Encoder *)self;
4156
4157 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4158
4159 ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
4160}
4161
4162void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
4163 GL2Encoder *ctx = (GL2Encoder *)self;
4164
4165 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4166
4167 ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
4168}
4169
4170void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
4171 GL2Encoder *ctx = (GL2Encoder *)self;
4172
4173 SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4174
4175 ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
4176}
4177
4178void GL2Encoder::s_glBlitFramebuffer(void* self, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
4179 GL2Encoder *ctx = (GL2Encoder *)self;
4180 GLClientState* state = ctx->m_state;
4181
4182 bool validateColor = mask | GL_COLOR_BUFFER_BIT;
4183 bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
4184 bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
4185
4186 FboFormatInfo read_fbo_format_info;
4187 FboFormatInfo draw_fbo_format_info;
4188 if (validateColor) {
4189 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4190 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4191
4192 if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4193 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
4194 SET_ERROR_IF(
4195 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4196 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4197 !GLESv2Validation::blitFramebufferFormat(
4198 read_fbo_format_info.tex_type,
4199 draw_fbo_format_info.tex_type),
4200 GL_INVALID_OPERATION);
4201 }
4202 }
4203
4204 if (validateDepth) {
4205 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
4206 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
4207
4208 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4209 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4210 SET_ERROR_IF(
4211 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4212 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4213 !GLESv2Validation::blitFramebufferFormat(
4214 read_fbo_format_info.rb_format,
4215 draw_fbo_format_info.rb_format),
4216 GL_INVALID_OPERATION);
4217 }
4218 }
4219
4220 if (validateStencil) {
4221 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
4222 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
4223
4224 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4225 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4226 SET_ERROR_IF(
4227 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4228 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4229 !GLESv2Validation::blitFramebufferFormat(
4230 read_fbo_format_info.rb_format,
4231 draw_fbo_format_info.rb_format),
4232 GL_INVALID_OPERATION);
4233 }
4234 }
4235
4236 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4237 SET_ERROR_IF(
4238 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4239 draw_fbo_format_info.rb_multisamples > 0,
4240 GL_INVALID_OPERATION);
4241 SET_ERROR_IF(
4242 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4243 draw_fbo_format_info.tex_multisamples > 0,
4244 GL_INVALID_OPERATION);
4245
4246 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4247 SET_ERROR_IF(
4248 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4249 read_fbo_format_info.rb_multisamples > 0 &&
4250 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4251 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4252 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4253 (read_fbo_format_info.rb_format !=
4254 draw_fbo_format_info.rb_format),
4255 GL_INVALID_OPERATION);
4256 SET_ERROR_IF(
4257 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4258 read_fbo_format_info.rb_multisamples > 0 &&
4259 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4260 (srcX0 != dstX0 || srcY0 != dstY0 ||
4261 srcX1 != dstX1 || srcY1 != dstY1),
4262 GL_INVALID_OPERATION);
4263
4264 ctx->m_glBlitFramebuffer_enc(ctx,
4265 srcX0, srcY0, srcX1, srcY1,
4266 dstX0, dstY0, dstX1, dstY1,
4267 mask, filter);
4268}
4269
4270void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
4271 GL2Encoder *ctx = (GL2Encoder *)self;
4272
4273 SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
4274 pname != GL_SAMPLES,
4275 GL_INVALID_ENUM);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004276 SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004277 SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004278 !GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4279 !GLESv2Validation::depthRenderableFormat(ctx, internalformat) &&
4280 !GLESv2Validation::stencilRenderableFormat(ctx, internalformat),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004281 GL_INVALID_ENUM);
4282 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4283
4284 if (bufSize < 1) return;
4285
4286 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
4287 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
4288 switch (pname) {
4289 case GL_NUM_SAMPLE_COUNTS:
4290 *params = 3;
4291 break;
4292 case GL_SAMPLES:
4293 params[0] = 4;
4294 if (bufSize > 1) params[1] = 2;
4295 if (bufSize > 2) params[2] = 1;
4296 break;
4297 default:
4298 break;
4299 }
4300}
4301
4302void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
4303 GL2Encoder *ctx = (GL2Encoder *)self;
4304 GLClientState* state = ctx->m_state;
4305
4306 SET_ERROR_IF(target != GL_TEXTURE_2D &&
4307 target != GL_TEXTURE_3D &&
Yahan Zhou53c64582018-04-16 15:46:17 -07004308 target != GL_TEXTURE_CUBE_MAP &&
4309 target != GL_TEXTURE_2D_ARRAY,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004310 GL_INVALID_ENUM);
4311
4312 GLuint tex = state->getBoundTexture(target);
4313 GLenum internalformat = state->queryTexInternalFormat(tex);
4314 GLenum format = state->queryTexFormat(tex);
4315
4316 SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
4317 GL_INVALID_OPERATION);
4318 SET_ERROR_IF(tex &&
4319 !GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004320 !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4321 GLESv2Validation::filterableTexFormat(ctx, internalformat)),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004322 GL_INVALID_OPERATION);
4323
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08004324 if (target == GL_TEXTURE_2D) {
4325 ctx->override2DTextureTarget(target);
4326 }
4327
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004328 ctx->m_glGenerateMipmap_enc(ctx, target);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08004329
4330 if (target == GL_TEXTURE_2D) {
4331 ctx->restore2DTextureTarget(target);
4332 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004333}
4334
4335void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4336 GL2Encoder *ctx = (GL2Encoder *)self;
4337 GLint maxCombinedUnits;
4338 ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4339 SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4340
4341 ctx->m_glBindSampler_enc(ctx, unit, sampler);
4342}
4343
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004344GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4345 GL2Encoder *ctx = (GL2Encoder *)self;
4346 uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4347 return (GLsync)(uintptr_t)syncHandle;
4348}
4349
4350GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4351 GL2Encoder *ctx = (GL2Encoder *)self;
4352 return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4353}
4354
4355void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4356 GL2Encoder *ctx = (GL2Encoder *)self;
4357 ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4358}
4359
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004360void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) {
4361 GL2Encoder *ctx = (GL2Encoder *)self;
4362
4363 if (!sync) return;
4364
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004365 ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4366}
4367
4368GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4369 GL2Encoder *ctx = (GL2Encoder *)self;
4370 return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4371}
4372
4373void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4374 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004375
4376 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4377
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004378 return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004379}
4380
4381#define LIMIT_CASE(target, lim) \
4382 case target: \
4383 ctx->glGetIntegerv(ctx, lim, &limit); \
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004384 SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004385 break; \
4386
4387void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) {
4388 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004389 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004390
4391 GLint limit;
4392
4393 switch (target) {
4394 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4395 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4396 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4397 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4398 default:
4399 break;
4400 }
4401
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004402 const GLClientState::VertexAttribBindingVector& currBindings =
4403 state->currentVertexBufferBindings();
4404
4405 switch (target) {
4406 case GL_VERTEX_BINDING_DIVISOR:
4407 case GL_VERTEX_BINDING_OFFSET:
4408 case GL_VERTEX_BINDING_STRIDE:
4409 case GL_VERTEX_BINDING_BUFFER:
4410 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4411 break;
4412 default:
4413 break;
4414 }
4415
4416 switch (target) {
4417 case GL_VERTEX_BINDING_DIVISOR:
4418 *params = currBindings[index].divisor;
4419 return;
4420 case GL_VERTEX_BINDING_OFFSET:
4421 *params = currBindings[index].offset;
4422 return;
4423 case GL_VERTEX_BINDING_STRIDE:
4424 *params = currBindings[index].effectiveStride;
4425 return;
4426 case GL_VERTEX_BINDING_BUFFER:
4427 *params = currBindings[index].buffer;
4428 return;
4429 default:
4430 break;
4431 }
4432
Lingfeng Yang80a36332017-07-09 10:58:07 -07004433 ctx->safe_glGetIntegeri_v(target, index, params);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004434}
4435
4436void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
4437 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004438 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004439
4440 GLint limit;
4441
4442 switch (target) {
4443 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4444 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4445 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4446 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4447 default:
4448 break;
4449 }
4450
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004451 const GLClientState::VertexAttribBindingVector& currBindings =
4452 state->currentVertexBufferBindings();
4453
4454 switch (target) {
4455 case GL_VERTEX_BINDING_DIVISOR:
4456 case GL_VERTEX_BINDING_OFFSET:
4457 case GL_VERTEX_BINDING_STRIDE:
4458 case GL_VERTEX_BINDING_BUFFER:
4459 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4460 break;
4461 default:
4462 break;
4463 }
4464
4465 switch (target) {
4466 case GL_VERTEX_BINDING_DIVISOR:
4467 *params = currBindings[index].divisor;
4468 return;
4469 case GL_VERTEX_BINDING_OFFSET:
4470 *params = currBindings[index].offset;
4471 return;
4472 case GL_VERTEX_BINDING_STRIDE:
4473 *params = currBindings[index].effectiveStride;
4474 return;
4475 case GL_VERTEX_BINDING_BUFFER:
4476 *params = currBindings[index].buffer;
4477 return;
4478 default:
4479 break;
4480 }
4481
Lingfeng Yang80a36332017-07-09 10:58:07 -07004482 ctx->safe_glGetInteger64i_v(target, index, params);
4483}
4484
4485void GL2Encoder::s_glGetInteger64v(void* self, GLenum param, GLint64* val) {
4486 GL2Encoder *ctx = (GL2Encoder *)self;
4487 ctx->safe_glGetInteger64v(param, val);
4488}
4489
4490void GL2Encoder::s_glGetBooleani_v(void* self, GLenum param, GLuint index, GLboolean* val) {
4491 GL2Encoder *ctx = (GL2Encoder *)self;
4492 ctx->safe_glGetBooleani_v(param, index, val);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004493}
4494
4495void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4496 GL2Encoder *ctx = (GL2Encoder *)self;
4497 ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4498 if (pname == GL_SHADER_SOURCE_LENGTH) {
4499 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4500 if (shaderData) {
4501 int totalLen = 0;
4502 for (int i = 0; i < shaderData->sources.size(); i++) {
4503 totalLen += shaderData->sources[i].size();
4504 }
4505 if (totalLen != 0) {
4506 *params = totalLen + 1; // account for null terminator
4507 }
4508 }
4509 }
4510}
4511
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004512void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) {
4513 GL2Encoder *ctx = (GL2Encoder*)self;
4514 GLClientState* state = ctx->m_state;
4515 GLSharedGroupPtr shared = ctx->m_shared;
4516
4517 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4518 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4519 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4520
4521 ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program);
4522 if (!state->currentProgram()) {
4523 state->setCurrentShaderProgram(program);
4524 }
4525}
4526
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004527GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4528
4529 GLint* length = NULL;
4530 GL2Encoder* ctx = (GL2Encoder*)self;
4531
4532 int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
4533 char *str = new char[len + 1];
4534 glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
4535
4536 // Do GLSharedGroup and location WorkARound-specific initialization
4537 // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4538 uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4539 ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004540
Lingfeng Yang44209df2018-09-21 10:04:17 -07004541 if (!replaceSamplerExternalWith2D(str, &spData->shaderData)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004542 delete [] str;
4543 ctx->setError(GL_OUT_OF_MEMORY);
4544 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4545 return -1;
4546 }
4547
4548 GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
4549 delete [] str;
4550
4551 // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4552 GLint linkStatus = 0;
4553 ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4554 if (!linkStatus) {
4555 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4556 return -1;
4557 }
4558
4559 ctx->m_shared->associateGLShaderProgram(res, spDataId);
4560
4561 GLint numUniforms = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07004562 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORMS, &numUniforms);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004563 ctx->m_shared->initShaderProgramData(res, numUniforms);
4564
4565 GLint maxLength=0;
4566 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4567
4568 GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4569
4570 for (GLint i = 0; i < numUniforms; ++i) {
4571 ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4572 GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4573 ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4574 }
4575
4576 ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4577
4578 delete [] name;
4579
4580 return res;
4581}
4582
4583void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4584{
4585 GL2Encoder *ctx = (GL2Encoder*)self;
4586 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4587 ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4588}
4589
4590void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4591{
4592 GL2Encoder *ctx = (GL2Encoder*)self;
4593 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4594 ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4595}
4596
4597void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4598{
4599 GL2Encoder *ctx = (GL2Encoder*)self;
4600 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004601 ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004602
4603 GLClientState* state = ctx->m_state;
4604 GLSharedGroupPtr shared = ctx->m_shared;
4605 GLenum target;
4606
4607 if (shared->setSamplerUniform(program, location, v0, &target)) {
4608 GLenum origActiveTexture = state->getActiveTextureUnit();
4609 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4610 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4611 }
4612 state->setActiveTextureUnit(origActiveTexture);
4613 }
4614}
4615
4616void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4617{
4618 GL2Encoder *ctx = (GL2Encoder*)self;
4619 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4620 ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4621}
4622
4623void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4624{
4625 GL2Encoder *ctx = (GL2Encoder*)self;
4626 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4627 ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4628
4629 GLClientState* state = ctx->m_state;
4630 GLSharedGroupPtr shared = ctx->m_shared;
4631 GLenum target;
4632
4633 if (shared->setSamplerUniform(program, location, v0, &target)) {
4634 GLenum origActiveTexture = state->getActiveTextureUnit();
4635 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4636 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4637 }
4638 state->setActiveTextureUnit(origActiveTexture);
4639 }
4640}
4641
4642void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4643{
4644 GL2Encoder *ctx = (GL2Encoder*)self;
4645 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4646 ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
4647}
4648
4649void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
4650{
4651 GL2Encoder *ctx = (GL2Encoder*)self;
4652 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4653 ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
4654}
4655
4656void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4657{
4658 GL2Encoder *ctx = (GL2Encoder*)self;
4659 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4660 ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
4661}
4662
4663void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
4664{
4665 GL2Encoder *ctx = (GL2Encoder*)self;
4666 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4667 ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
4668}
4669
4670void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4671{
4672 GL2Encoder *ctx = (GL2Encoder*)self;
4673 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4674 ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
4675}
4676
4677void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
4678{
4679 GL2Encoder *ctx = (GL2Encoder*)self;
4680 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4681 ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
4682}
4683
4684void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4685{
4686 GL2Encoder *ctx = (GL2Encoder*)self;
4687 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4688 ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
4689}
4690
4691void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
4692{
4693 GL2Encoder *ctx = (GL2Encoder*)self;
4694 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4695 ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
4696}
4697
4698void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4699{
4700 GL2Encoder *ctx = (GL2Encoder*)self;
4701 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4702 ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
4703}
4704
4705void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
4706{
4707 GL2Encoder *ctx = (GL2Encoder*)self;
4708 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4709 ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
4710}
4711
4712void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4713{
4714 GL2Encoder *ctx = (GL2Encoder*)self;
4715 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4716 ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
4717}
4718
4719void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
4720{
4721 GL2Encoder *ctx = (GL2Encoder*)self;
4722 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4723 ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
4724}
4725
4726void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4727{
4728 GL2Encoder *ctx = (GL2Encoder*)self;
4729 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4730 ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
4731}
4732
4733void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
4734{
4735 GL2Encoder *ctx = (GL2Encoder*)self;
4736 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4737 ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
4738}
4739
4740void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4741{
4742 GL2Encoder *ctx = (GL2Encoder*)self;
4743 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4744 ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
4745}
4746
4747void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
4748{
4749 GL2Encoder *ctx = (GL2Encoder*)self;
4750 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4751 ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
4752}
4753
4754void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4755{
4756 GL2Encoder *ctx = (GL2Encoder*)self;
4757 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4758 ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
4759}
4760
4761void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
4762{
4763 GL2Encoder *ctx = (GL2Encoder*)self;
4764 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4765 ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
4766}
4767
4768void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4769{
4770 GL2Encoder *ctx = (GL2Encoder*)self;
4771 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4772 ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
4773}
4774
4775void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4776{
4777 GL2Encoder *ctx = (GL2Encoder*)self;
4778 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4779 ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
4780}
4781
4782void GL2Encoder::s_glProgramUniformMatrix2x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4783{
4784 GL2Encoder *ctx = (GL2Encoder*)self;
4785 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4786 ctx->m_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
4787}
4788
4789void GL2Encoder::s_glProgramUniformMatrix2x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4790{
4791 GL2Encoder *ctx = (GL2Encoder*)self;
4792 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4793 ctx->m_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
4794}
4795
4796void GL2Encoder::s_glProgramUniformMatrix3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4797{
4798 GL2Encoder *ctx = (GL2Encoder*)self;
4799 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4800 ctx->m_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
4801}
4802
4803void GL2Encoder::s_glProgramUniformMatrix3x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4804{
4805 GL2Encoder *ctx = (GL2Encoder*)self;
4806 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4807 ctx->m_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
4808}
4809
4810void GL2Encoder::s_glProgramUniformMatrix3x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4811{
4812 GL2Encoder *ctx = (GL2Encoder*)self;
4813 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4814 ctx->m_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
4815}
4816
4817void GL2Encoder::s_glProgramUniformMatrix4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4818{
4819 GL2Encoder *ctx = (GL2Encoder*)self;
4820 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4821 ctx->m_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
4822}
4823
4824void GL2Encoder::s_glProgramUniformMatrix4x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4825{
4826 GL2Encoder *ctx = (GL2Encoder*)self;
4827 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4828 ctx->m_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
4829}
4830
4831void GL2Encoder::s_glProgramUniformMatrix4x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4832{
4833 GL2Encoder *ctx = (GL2Encoder*)self;
4834 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4835 ctx->m_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
4836}
4837
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004838void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) {
4839 GL2Encoder* ctx = (GL2Encoder*)self;
4840 ctx->m_glProgramParameteri_enc(self, program, pname, value);
4841}
4842
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004843void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
4844{
4845 GL2Encoder *ctx = (GL2Encoder*)self;
4846 GLClientState* state = ctx->m_state;
4847 GLSharedGroupPtr shared = ctx->m_shared;
4848
4849 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4850 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4851 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4852
4853 ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
4854 state->associateProgramWithPipeline(program, pipeline);
4855
4856 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4857 if (state->currentProgram()) {
4858 return;
4859 }
4860
4861 // Otherwise, update host texture 2D bindings.
4862 ctx->updateHostTexture2DBindingsFromProgramData(program);
4863}
4864
4865void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
4866{
4867 GL2Encoder *ctx = (GL2Encoder*)self;
4868 GLClientState* state = ctx->m_state;
4869
4870 ctx->m_glBindProgramPipeline_enc(self, pipeline);
4871
4872 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4873 if (!pipeline || state->currentProgram()) {
4874 return;
4875 }
4876
4877 GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
4878 for (; it != state->programPipelineEnd(); ++it) {
4879 if (it->second == pipeline) {
4880 ctx->updateHostTexture2DBindingsFromProgramData(it->first);
4881 }
4882 }
4883}
4884
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004885void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
4886 GL2Encoder *ctx = (GL2Encoder*)self;
4887 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4888 if (bufSize == 0) {
4889 if (length) *length = 0;
4890 return;
4891 }
4892
4893 // Avoid modifying |name| if |*length| < bufSize.
4894 GLint* intermediate = new GLint[bufSize];
4895 GLsizei* myLength = length ? length : new GLsizei;
4896 bool needFreeLength = length == NULL;
4897
4898 ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
4899 GLsizei writtenInts = *myLength;
4900 memcpy(params, intermediate, writtenInts * sizeof(GLint));
4901
4902 delete [] intermediate;
4903 if (needFreeLength)
4904 delete myLength;
4905}
4906
4907GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
4908 GL2Encoder *ctx = (GL2Encoder*)self;
4909 return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
4910}
4911
4912GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
4913 GL2Encoder *ctx = (GL2Encoder*)self;
4914 return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
4915}
4916
4917void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
4918 GL2Encoder *ctx = (GL2Encoder*)self;
4919 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4920 if (bufSize == 0) {
4921 if (length) *length = 0;
4922 return;
4923 }
4924
4925 // Avoid modifying |name| if |*length| < bufSize.
4926 char* intermediate = new char[bufSize];
4927 GLsizei* myLength = length ? length : new GLsizei;
4928 bool needFreeLength = length == NULL;
4929
4930 ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
4931 GLsizei writtenStrLen = *myLength;
4932 memcpy(name, intermediate, writtenStrLen + 1);
4933
4934 delete [] intermediate;
4935 if (needFreeLength)
4936 delete myLength;
4937}
4938
4939void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
4940 GL2Encoder *ctx = (GL2Encoder*)self;
4941 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4942 if (bufSize == 0) {
4943 if (length) *length = 0;
4944 return;
4945 }
4946
4947 // Avoid modifying |infoLog| if |*length| < bufSize.
4948 GLchar* intermediate = new GLchar[bufSize];
4949 GLsizei* myLength = length ? length : new GLsizei;
4950 bool needFreeLength = length == NULL;
4951
4952 ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
4953 GLsizei writtenStrLen = *myLength;
4954 memcpy(infoLog, intermediate, writtenStrLen + 1);
4955
4956 delete [] intermediate;
4957 if (needFreeLength)
4958 delete myLength;
4959}
4960
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004961void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
4962 GL2Encoder *ctx = (GL2Encoder*)self;
4963 GLClientState* state = ctx->m_state;
4964
Lingfeng Yang07289902017-01-27 12:26:19 -08004965 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004966 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4967
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004968 state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false);
4969 ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset);
4970}
4971
4972void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
4973 GL2Encoder *ctx = (GL2Encoder*)self;
4974 GLClientState* state = ctx->m_state;
4975
Lingfeng Yang07289902017-01-27 12:26:19 -08004976 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004977 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4978
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004979 state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true);
4980 ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset);
4981}
4982
4983void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004984 GL2Encoder *ctx = (GL2Encoder*)self;
4985 GLClientState* state = ctx->m_state;
4986
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004987 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4988
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004989 state->setVertexBindingDivisor(bindingindex, divisor);
4990 ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor);
4991}
4992
4993void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) {
4994 GL2Encoder *ctx = (GL2Encoder*)self;
4995 GLClientState* state = ctx->m_state;
Lingfeng Yang07289902017-01-27 12:26:19 -08004996 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004997 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004998
4999 state->setVertexAttribBinding(attribindex, bindingindex);
5000 ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex);
5001}
5002
5003void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
5004 GL2Encoder *ctx = (GL2Encoder*)self;
5005 GLClientState* state = ctx->m_state;
5006
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005007 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
5008
5009 GLint maxStride;
5010 ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
5011 SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE);
5012
5013 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5014
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005015 state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride);
5016 ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride);
5017}
5018
5019void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) {
5020 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005021 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005022
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005023 bool hasClientArrays = false;
5024 ctx->getVBOUsage(&hasClientArrays, NULL);
5025
5026 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
5027 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5028 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
5029
5030 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005031 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005032 // BufferData* buf = ctx->getBufferData(target);
5033 // if (buf) {
5034 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
5035 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005036 ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect);
5037 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005038 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
5039 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005040 ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize);
5041 }
5042}
5043
5044void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) {
5045 GL2Encoder *ctx = (GL2Encoder*)self;
5046
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005047 GLClientState* state = ctx->m_state;
5048
5049 bool hasClientArrays = false;
5050 ctx->getVBOUsage(&hasClientArrays, NULL);
5051
5052 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
5053 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5054 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
5055
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005056 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005057
5058 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005059 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005060 // BufferData* buf = ctx->getBufferData(target);
5061 // if (buf) {
5062 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
5063 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005064 ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect);
5065 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005066 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
5067 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005068 ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize);
5069 }
5070
5071}
5072
5073void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
5074 GL2Encoder *ctx = (GL2Encoder*)self;
5075 GLClientState* state = ctx->m_state;
5076
5077 SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
5078 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
5079 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
5080 SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
5081 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005082 GLint max_samples;
5083 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
5084 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005085
5086 state->setBoundTextureInternalFormat(target, internalformat);
5087 state->setBoundTextureDims(target, 0, width, height, 1);
5088 state->setBoundTextureImmutableFormat(target);
5089 state->setBoundTextureSamples(target, samples);
5090
5091 ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
5092}
5093