blob: c3389c5e92efac8a7b3b7abf75f83100c4e5e42b [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;
Lingfeng Yang48685bb2018-10-19 06:44:20 -070080 m_max_combinedTextureImageUnits = 0;
Lizhe Liue41f4ef2015-05-27 11:13:23 +080081 m_max_cubeMapTextureSize = 0;
82 m_max_renderBufferSize = 0;
83 m_max_textureSize = 0;
Lingfeng Yang46153ab2017-01-09 13:37:22 -080084 m_max_3d_textureSize = 0;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -080085 m_max_vertexAttribStride = 0;
keunyoungb85b2752013-03-08 12:28:03 -080086 m_compressedTextureFormats = NULL;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010087
Lingfeng Yang46153ab2017-01-09 13:37:22 -080088 m_ssbo_offset_align = 0;
89 m_ubo_offset_align = 0;
90
Lingfeng Yangde51dfb2016-10-17 22:48:59 -070091 m_drawCallFlushCount = 0;
92 m_primitiveRestartEnabled = false;
93 m_primitiveRestartIndex = 0;
94
Lingfeng Yang07289902017-01-27 12:26:19 -080095 // overrides
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010096#define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name
Lingfeng Yange6556dc2017-01-09 12:04:12 -080097#define OVERRIDE_CUSTOM(name) this-> name = &s_##name
98#define OVERRIDEWITH(name, target) do { \
99 m_##target##_enc = this-> target; \
100 this-> target = &s_##name; \
101} while(0)
102#define OVERRIDEOES(name) OVERRIDEWITH(name, name##OES)
bohu56bf82f2014-10-17 15:35:48 -0700103
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100104 OVERRIDE(glFlush);
105 OVERRIDE(glPixelStorei);
106 OVERRIDE(glGetString);
107 OVERRIDE(glBindBuffer);
108 OVERRIDE(glBufferData);
109 OVERRIDE(glBufferSubData);
110 OVERRIDE(glDeleteBuffers);
111 OVERRIDE(glDrawArrays);
112 OVERRIDE(glDrawElements);
113 OVERRIDE(glGetIntegerv);
114 OVERRIDE(glGetFloatv);
115 OVERRIDE(glGetBooleanv);
116 OVERRIDE(glVertexAttribPointer);
117 OVERRIDE(glEnableVertexAttribArray);
118 OVERRIDE(glDisableVertexAttribArray);
119 OVERRIDE(glGetVertexAttribiv);
120 OVERRIDE(glGetVertexAttribfv);
121 OVERRIDE(glGetVertexAttribPointerv);
keunyoungb85b2752013-03-08 12:28:03 -0800122
Bo Hu73568cd2015-01-20 16:29:50 -0800123 this->glShaderBinary = &s_glShaderBinary;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100124 this->glShaderSource = &s_glShaderSource;
125 this->glFinish = &s_glFinish;
keunyoungb85b2752013-03-08 12:28:03 -0800126
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100127 OVERRIDE(glGetError);
128 OVERRIDE(glLinkProgram);
129 OVERRIDE(glDeleteProgram);
130 OVERRIDE(glGetUniformiv);
131 OVERRIDE(glGetUniformfv);
132 OVERRIDE(glCreateProgram);
133 OVERRIDE(glCreateShader);
134 OVERRIDE(glDeleteShader);
135 OVERRIDE(glAttachShader);
136 OVERRIDE(glDetachShader);
137 OVERRIDE(glGetAttachedShaders);
138 OVERRIDE(glGetShaderSource);
139 OVERRIDE(glGetShaderInfoLog);
140 OVERRIDE(glGetProgramInfoLog);
141
142 OVERRIDE(glGetUniformLocation);
143 OVERRIDE(glUseProgram);
144
145 OVERRIDE(glUniform1f);
146 OVERRIDE(glUniform1fv);
147 OVERRIDE(glUniform1i);
148 OVERRIDE(glUniform1iv);
149 OVERRIDE(glUniform2f);
150 OVERRIDE(glUniform2fv);
151 OVERRIDE(glUniform2i);
152 OVERRIDE(glUniform2iv);
153 OVERRIDE(glUniform3f);
154 OVERRIDE(glUniform3fv);
155 OVERRIDE(glUniform3i);
156 OVERRIDE(glUniform3iv);
157 OVERRIDE(glUniform4f);
158 OVERRIDE(glUniform4fv);
159 OVERRIDE(glUniform4i);
160 OVERRIDE(glUniform4iv);
161 OVERRIDE(glUniformMatrix2fv);
162 OVERRIDE(glUniformMatrix3fv);
163 OVERRIDE(glUniformMatrix4fv);
164
165 OVERRIDE(glActiveTexture);
166 OVERRIDE(glBindTexture);
167 OVERRIDE(glDeleteTextures);
168 OVERRIDE(glGetTexParameterfv);
169 OVERRIDE(glGetTexParameteriv);
170 OVERRIDE(glTexParameterf);
171 OVERRIDE(glTexParameterfv);
172 OVERRIDE(glTexParameteri);
173 OVERRIDE(glTexParameteriv);
bohu26a92982014-11-25 16:50:37 -0800174 OVERRIDE(glTexImage2D);
Yahan Zhou2a208292016-06-22 15:36:04 -0700175 OVERRIDE(glTexSubImage2D);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -0700176 OVERRIDE(glCopyTexImage2D);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700177
178 OVERRIDE(glGenRenderbuffers);
179 OVERRIDE(glDeleteRenderbuffers);
180 OVERRIDE(glBindRenderbuffer);
Lingfeng Yang69066602016-04-12 09:29:11 -0700181 OVERRIDE(glRenderbufferStorage);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700182 OVERRIDE(glFramebufferRenderbuffer);
183
184 OVERRIDE(glGenFramebuffers);
185 OVERRIDE(glDeleteFramebuffers);
186 OVERRIDE(glBindFramebuffer);
187 OVERRIDE(glFramebufferTexture2D);
188 OVERRIDE(glFramebufferTexture3DOES);
189 OVERRIDE(glGetFramebufferAttachmentParameteriv);
Lingfeng Yang69066602016-04-12 09:29:11 -0700190
191 OVERRIDE(glCheckFramebufferStatus);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800192
193 OVERRIDE(glGenVertexArrays);
194 OVERRIDE(glDeleteVertexArrays);
195 OVERRIDE(glBindVertexArray);
196 OVERRIDEOES(glGenVertexArrays);
197 OVERRIDEOES(glDeleteVertexArrays);
198 OVERRIDEOES(glBindVertexArray);
199
Lingfeng Yangfb3d2bb2017-09-07 15:02:04 -0700200 OVERRIDE_CUSTOM(glMapBufferOES);
201 OVERRIDE_CUSTOM(glUnmapBufferOES);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800202 OVERRIDE_CUSTOM(glMapBufferRange);
203 OVERRIDE_CUSTOM(glUnmapBuffer);
204 OVERRIDE_CUSTOM(glFlushMappedBufferRange);
205
206 OVERRIDE(glCompressedTexImage2D);
207 OVERRIDE(glCompressedTexSubImage2D);
208
209 OVERRIDE(glBindBufferRange);
210 OVERRIDE(glBindBufferBase);
211
212 OVERRIDE(glCopyBufferSubData);
213
214 OVERRIDE(glGetBufferParameteriv);
215 OVERRIDE(glGetBufferParameteri64v);
216 OVERRIDE(glGetBufferPointerv);
217
218 OVERRIDE_CUSTOM(glGetUniformIndices);
219
220 OVERRIDE(glUniform1ui);
221 OVERRIDE(glUniform2ui);
222 OVERRIDE(glUniform3ui);
223 OVERRIDE(glUniform4ui);
224 OVERRIDE(glUniform1uiv);
225 OVERRIDE(glUniform2uiv);
226 OVERRIDE(glUniform3uiv);
227 OVERRIDE(glUniform4uiv);
228 OVERRIDE(glUniformMatrix2x3fv);
229 OVERRIDE(glUniformMatrix3x2fv);
230 OVERRIDE(glUniformMatrix2x4fv);
231 OVERRIDE(glUniformMatrix4x2fv);
232 OVERRIDE(glUniformMatrix3x4fv);
233 OVERRIDE(glUniformMatrix4x3fv);
234
235 OVERRIDE(glGetUniformuiv);
236 OVERRIDE(glGetActiveUniformBlockiv);
237
238 OVERRIDE(glGetVertexAttribIiv);
239 OVERRIDE(glGetVertexAttribIuiv);
240
241 OVERRIDE_CUSTOM(glVertexAttribIPointer);
242
243 OVERRIDE(glVertexAttribDivisor);
244
245 OVERRIDE(glRenderbufferStorageMultisample);
246 OVERRIDE(glDrawBuffers);
247 OVERRIDE(glReadBuffer);
248 OVERRIDE(glFramebufferTextureLayer);
249 OVERRIDE(glTexStorage2D);
250
251 OVERRIDE_CUSTOM(glTransformFeedbackVaryings);
252 OVERRIDE(glBeginTransformFeedback);
253 OVERRIDE(glEndTransformFeedback);
254 OVERRIDE(glPauseTransformFeedback);
255 OVERRIDE(glResumeTransformFeedback);
256
257 OVERRIDE(glTexImage3D);
258 OVERRIDE(glTexSubImage3D);
259 OVERRIDE(glTexStorage3D);
260 OVERRIDE(glCompressedTexImage3D);
261 OVERRIDE(glCompressedTexSubImage3D);
262
263 OVERRIDE(glDrawArraysInstanced);
264 OVERRIDE_CUSTOM(glDrawElementsInstanced);
265 OVERRIDE_CUSTOM(glDrawRangeElements);
266
267 OVERRIDE_CUSTOM(glGetStringi);
268 OVERRIDE(glGetProgramBinary);
269 OVERRIDE(glReadPixels);
270
271 OVERRIDE(glEnable);
272 OVERRIDE(glDisable);
273 OVERRIDE(glClearBufferiv);
274 OVERRIDE(glClearBufferuiv);
275 OVERRIDE(glClearBufferfv);
276 OVERRIDE(glBlitFramebuffer);
277 OVERRIDE_CUSTOM(glGetInternalformativ);
278
279 OVERRIDE(glGenerateMipmap);
280
281 OVERRIDE(glBindSampler);
282
Lingfeng Yangf000ab42017-01-11 18:31:38 -0800283 OVERRIDE_CUSTOM(glFenceSync);
284 OVERRIDE_CUSTOM(glClientWaitSync);
285 OVERRIDE_CUSTOM(glWaitSync);
286 OVERRIDE_CUSTOM(glDeleteSync);
287 OVERRIDE_CUSTOM(glIsSync);
288 OVERRIDE_CUSTOM(glGetSynciv);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800289
290 OVERRIDE(glGetIntegeri_v);
291 OVERRIDE(glGetInteger64i_v);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700292 OVERRIDE(glGetInteger64v);
293 OVERRIDE(glGetBooleani_v);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800294
295 OVERRIDE(glGetShaderiv);
296
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800297 OVERRIDE(glActiveShaderProgram);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800298 OVERRIDE_CUSTOM(glCreateShaderProgramv);
299 OVERRIDE(glProgramUniform1f);
300 OVERRIDE(glProgramUniform1fv);
301 OVERRIDE(glProgramUniform1i);
302 OVERRIDE(glProgramUniform1iv);
303 OVERRIDE(glProgramUniform1ui);
304 OVERRIDE(glProgramUniform1uiv);
305 OVERRIDE(glProgramUniform2f);
306 OVERRIDE(glProgramUniform2fv);
307 OVERRIDE(glProgramUniform2i);
308 OVERRIDE(glProgramUniform2iv);
309 OVERRIDE(glProgramUniform2ui);
310 OVERRIDE(glProgramUniform2uiv);
311 OVERRIDE(glProgramUniform3f);
312 OVERRIDE(glProgramUniform3fv);
313 OVERRIDE(glProgramUniform3i);
314 OVERRIDE(glProgramUniform3iv);
315 OVERRIDE(glProgramUniform3ui);
316 OVERRIDE(glProgramUniform3uiv);
317 OVERRIDE(glProgramUniform4f);
318 OVERRIDE(glProgramUniform4fv);
319 OVERRIDE(glProgramUniform4i);
320 OVERRIDE(glProgramUniform4iv);
321 OVERRIDE(glProgramUniform4ui);
322 OVERRIDE(glProgramUniform4uiv);
323 OVERRIDE(glProgramUniformMatrix2fv);
324 OVERRIDE(glProgramUniformMatrix2x3fv);
325 OVERRIDE(glProgramUniformMatrix2x4fv);
326 OVERRIDE(glProgramUniformMatrix3fv);
327 OVERRIDE(glProgramUniformMatrix3x2fv);
328 OVERRIDE(glProgramUniformMatrix3x4fv);
329 OVERRIDE(glProgramUniformMatrix4fv);
330 OVERRIDE(glProgramUniformMatrix4x2fv);
331 OVERRIDE(glProgramUniformMatrix4x3fv);
332
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800333 OVERRIDE(glProgramParameteri);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800334 OVERRIDE(glUseProgramStages);
335 OVERRIDE(glBindProgramPipeline);
336
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800337 OVERRIDE(glGetProgramResourceiv);
338 OVERRIDE(glGetProgramResourceIndex);
339 OVERRIDE(glGetProgramResourceLocation);
340 OVERRIDE(glGetProgramResourceName);
341 OVERRIDE(glGetProgramPipelineInfoLog);
342
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800343 OVERRIDE(glVertexAttribFormat);
344 OVERRIDE(glVertexAttribIFormat);
345 OVERRIDE(glVertexBindingDivisor);
346 OVERRIDE(glVertexAttribBinding);
347 OVERRIDE(glBindVertexBuffer);
348
349 OVERRIDE_CUSTOM(glDrawArraysIndirect);
350 OVERRIDE_CUSTOM(glDrawElementsIndirect);
351
352 OVERRIDE(glTexStorage2DMultisample);
keunyoungb85b2752013-03-08 12:28:03 -0800353}
354
355GL2Encoder::~GL2Encoder()
356{
357 delete m_compressedTextureFormats;
358}
359
360GLenum GL2Encoder::s_glGetError(void * self)
361{
362 GL2Encoder *ctx = (GL2Encoder *)self;
363 GLenum err = ctx->getError();
364 if(err != GL_NO_ERROR) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700365 ctx->m_glGetError_enc(ctx); // also clear host error
keunyoungb85b2752013-03-08 12:28:03 -0800366 ctx->setError(GL_NO_ERROR);
367 return err;
368 }
369
Lingfeng Yange980c7a2018-01-12 14:50:18 -0800370 if (ctx->m_noHostError) {
371 return GL_NO_ERROR;
372 } else {
373 return ctx->m_glGetError_enc(self);
374 }
Lingfeng Yang80a36332017-07-09 10:58:07 -0700375}
Yahan Zhouae30fe82016-08-10 21:15:45 +0000376
Lingfeng Yang80a36332017-07-09 10:58:07 -0700377class GL2Encoder::ErrorUpdater {
378public:
379 ErrorUpdater(GL2Encoder* ctx) :
380 mCtx(ctx),
381 guest_error(ctx->getError()),
382 host_error(ctx->m_glGetError_enc(ctx)) {
383 // Preserve any existing GL error in the guest:
384 // OpenGL ES 3.0.5 spec:
385 // The command enum GetError( void ); is used to obtain error information.
386 // Each detectable error is assigned a numeric code. When an error is
387 // detected, a flag is set and the code is recorded. Further errors, if
388 // they occur, do not affect this recorded code. When GetError is called,
389 // the code is returned and the flag is cleared, so that a further error
390 // will again record its code. If a call to GetError returns NO_ERROR, then
391 // there has been no detectable error since the last call to GetError (or
392 // since the GL was initialized).
393 if (guest_error == GL_NO_ERROR) {
394 guest_error = host_error;
395 }
396 }
397
398 GLenum getHostErrorAndUpdate() {
399 host_error = mCtx->m_glGetError_enc(mCtx);
400 if (guest_error == GL_NO_ERROR) {
401 guest_error = host_error;
402 }
403 return host_error;
404 }
405
406 void updateGuestErrorState() {
407 mCtx->setError(guest_error);
408 }
409
410private:
411 GL2Encoder* mCtx;
412 GLenum guest_error;
413 GLenum host_error;
414};
415
416template<class T>
417class GL2Encoder::ScopedQueryUpdate {
418public:
419 ScopedQueryUpdate(GL2Encoder* ctx, uint32_t bytes, T* target) :
420 mCtx(ctx),
421 mBuf(bytes, 0),
422 mTarget(target),
423 mErrorUpdater(ctx) {
424 }
425 T* hostStagingBuffer() {
426 return (T*)&mBuf[0];
427 }
428 ~ScopedQueryUpdate() {
429 GLint hostError = mErrorUpdater.getHostErrorAndUpdate();
Lingfeng Yang72ecf472018-06-11 14:20:14 -0700430 if (hostError == GL_NO_ERROR && mTarget) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700431 memcpy(mTarget, &mBuf[0], mBuf.size());
432 }
433 mErrorUpdater.updateGuestErrorState();
434 }
435private:
436 GL2Encoder* mCtx;
437 std::vector<char> mBuf;
438 T* mTarget;
439 ErrorUpdater mErrorUpdater;
440};
441
442void GL2Encoder::safe_glGetBooleanv(GLenum param, GLboolean* val) {
443 ScopedQueryUpdate<GLboolean> query(this, glUtilsParamSize(param) * sizeof(GLboolean), val);
444 m_glGetBooleanv_enc(this, param, query.hostStagingBuffer());
445}
446
447void GL2Encoder::safe_glGetFloatv(GLenum param, GLfloat* val) {
448 ScopedQueryUpdate<GLfloat> query(this, glUtilsParamSize(param) * sizeof(GLfloat), val);
449 m_glGetFloatv_enc(this, param, query.hostStagingBuffer());
450}
451
452void GL2Encoder::safe_glGetIntegerv(GLenum param, GLint* val) {
453 ScopedQueryUpdate<GLint> query(this, glUtilsParamSize(param) * sizeof(GLint), val);
454 m_glGetIntegerv_enc(this, param, query.hostStagingBuffer());
455}
456
457void GL2Encoder::safe_glGetInteger64v(GLenum param, GLint64* val) {
458 ScopedQueryUpdate<GLint64> query(this, glUtilsParamSize(param) * sizeof(GLint64), val);
459 m_glGetInteger64v_enc(this, param, query.hostStagingBuffer());
460}
461
462void GL2Encoder::safe_glGetIntegeri_v(GLenum param, GLuint index, GLint* val) {
463 ScopedQueryUpdate<GLint> query(this, sizeof(GLint), val);
464 m_glGetIntegeri_v_enc(this, param, index, query.hostStagingBuffer());
465}
466
467void GL2Encoder::safe_glGetInteger64i_v(GLenum param, GLuint index, GLint64* val) {
468 ScopedQueryUpdate<GLint64> query(this, sizeof(GLint64), val);
469 m_glGetInteger64i_v_enc(this, param, index, query.hostStagingBuffer());
470}
471
472void GL2Encoder::safe_glGetBooleani_v(GLenum param, GLuint index, GLboolean* val) {
473 ScopedQueryUpdate<GLboolean> query(this, sizeof(GLboolean), val);
474 m_glGetBooleani_v_enc(this, param, index, query.hostStagingBuffer());
keunyoungb85b2752013-03-08 12:28:03 -0800475}
476
477void GL2Encoder::s_glFlush(void *self)
478{
479 GL2Encoder *ctx = (GL2Encoder *) self;
480 ctx->m_glFlush_enc(self);
481 ctx->m_stream->flush();
482}
483
484const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
485{
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800486 GL2Encoder *ctx = (GL2Encoder *)self;
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100487
keunyoungb85b2752013-03-08 12:28:03 -0800488 GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800489 RET_AND_SET_ERROR_IF(
490 name != GL_VENDOR &&
491 name != GL_RENDERER &&
492 name != GL_VERSION &&
493 name != GL_EXTENSIONS,
494 GL_INVALID_ENUM,
495 retval);
keunyoungb85b2752013-03-08 12:28:03 -0800496 switch(name) {
497 case GL_VENDOR:
498 retval = gVendorString;
499 break;
500 case GL_RENDERER:
501 retval = gRendererString;
502 break;
503 case GL_VERSION:
504 retval = gVersionString;
505 break;
506 case GL_EXTENSIONS:
507 retval = gExtensionsString;
508 break;
509 }
510 return retval;
511}
512
513void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
514{
515 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800516 SET_ERROR_IF(!GLESv2Validation::pixelStoreParam(ctx, param), GL_INVALID_ENUM);
517 SET_ERROR_IF(!GLESv2Validation::pixelStoreValue(param, value), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800518 ctx->m_glPixelStorei_enc(ctx, param, value);
519 assert(ctx->m_state != NULL);
520 ctx->m_state->setPixelStore(param, value);
521}
keunyoungb85b2752013-03-08 12:28:03 -0800522void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
523{
524 GL2Encoder *ctx = (GL2Encoder *) self;
525 assert(ctx->m_state != NULL);
526 ctx->m_state->bindBuffer(target, id);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800527 ctx->m_state->addBuffer(id);
keunyoungb85b2752013-03-08 12:28:03 -0800528 // TODO set error state if needed;
529 ctx->m_glBindBuffer_enc(self, target, id);
530}
531
532void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
533{
534 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800535 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800536 GLuint bufferId = ctx->m_state->getBuffer(target);
537 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
538 SET_ERROR_IF(size<0, GL_INVALID_VALUE);
539
Roman Kiryanovfb903d62018-09-19 13:38:53 -0700540 ctx->m_shared->updateBufferData(bufferId, size, data);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800541 ctx->m_shared->setBufferUsage(bufferId, usage);
keunyoungb85b2752013-03-08 12:28:03 -0800542 ctx->m_glBufferData_enc(self, target, size, data, usage);
543}
544
545void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
546{
547 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800548 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800549 GLuint bufferId = ctx->m_state->getBuffer(target);
550 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800551 SET_ERROR_IF(ctx->isBufferTargetMapped(target), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800552
Roman Kiryanovfb903d62018-09-19 13:38:53 -0700553 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, data);
keunyoungb85b2752013-03-08 12:28:03 -0800554 SET_ERROR_IF(res, res);
555
556 ctx->m_glBufferSubData_enc(self, target, offset, size, data);
557}
558
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800559void GL2Encoder::s_glGenBuffers(void* self, GLsizei n, GLuint* buffers) {
560 GL2Encoder *ctx = (GL2Encoder *) self;
561 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
562 ctx->m_glGenBuffers_enc(self, n, buffers);
563 for (int i = 0; i < n; i++) {
564 ctx->m_state->addBuffer(buffers[i]);
565 }
566}
567
keunyoungb85b2752013-03-08 12:28:03 -0800568void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
569{
570 GL2Encoder *ctx = (GL2Encoder *) self;
571 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
572 for (int i=0; i<n; i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800573 // Technically if the buffer is mapped, we should unmap it, but we won't
574 // use it anymore after this :)
keunyoungb85b2752013-03-08 12:28:03 -0800575 ctx->m_shared->deleteBufferData(buffers[i]);
bohub0f0cdf2014-11-06 18:08:07 -0800576 ctx->m_state->unBindBuffer(buffers[i]);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800577 ctx->m_state->removeBuffer(buffers[i]);
keunyoungb85b2752013-03-08 12:28:03 -0800578 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
579 }
580}
581
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700582static bool isValidVertexAttribIndex(void *self, GLuint indx)
583{
Lingfeng Yang07289902017-01-27 12:26:19 -0800584 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700585 GLint maxIndex;
586 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
587 return indx < maxIndex;
588}
589
Lingfeng Yang07289902017-01-27 12:26:19 -0800590#define VALIDATE_VERTEX_ATTRIB_INDEX(index) \
591 SET_ERROR_WITH_MESSAGE_IF( \
592 !isValidVertexAttribIndex(self, index), GL_INVALID_VALUE, \
593 GLESv2Validation::vertexAttribIndexRangeErrorMsg, (ctx, index)); \
594
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100595void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
keunyoungb85b2752013-03-08 12:28:03 -0800596{
597 GL2Encoder *ctx = (GL2Encoder *)self;
598 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -0800599 VALIDATE_VERTEX_ATTRIB_INDEX(indx);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700600 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800601 SET_ERROR_IF(!GLESv2Validation::vertexAttribType(ctx, type), GL_INVALID_ENUM);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700602 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800603 SET_ERROR_IF((type == GL_INT_2_10_10_10_REV ||
604 type == GL_UNSIGNED_INT_2_10_10_10_REV) &&
605 size != 4,
606 GL_INVALID_OPERATION);
607 ctx->m_state->setVertexAttribBinding(indx, indx);
608 ctx->m_state->setVertexAttribFormat(indx, size, type, normalized, 0, false);
609
610 GLsizei effectiveStride = stride;
611 if (stride == 0) {
612 effectiveStride = glSizeof(type) * size;
613 switch (type) {
614 case GL_INT_2_10_10_10_REV:
615 case GL_UNSIGNED_INT_2_10_10_10_REV:
616 effectiveStride /= 4;
617 break;
618 default:
619 break;
620 }
621 }
622
623 ctx->m_state->bindIndexedBuffer(0, indx, ctx->m_state->currentArrayVbo(), (uintptr_t)ptr, 0, stride, effectiveStride);
624
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800625 if (ctx->m_state->currentArrayVbo() != 0) {
626 ctx->glVertexAttribPointerOffset(ctx, indx, size, type, normalized, stride, (uintptr_t)ptr);
627 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800628 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && ptr, GL_INVALID_OPERATION);
629 // wait for client-array handler
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800630 }
keunyoungb85b2752013-03-08 12:28:03 -0800631}
632
633void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
634{
635 GL2Encoder *ctx = (GL2Encoder *) self;
keunyoungb85b2752013-03-08 12:28:03 -0800636 GLClientState* state = ctx->m_state;
637
638 switch (param) {
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -0800639 case GL_NUM_EXTENSIONS:
640 *ptr = (int)ctx->m_currExtensionsArray.size();
641 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800642 case GL_MAJOR_VERSION:
Lingfeng Yang324c8452017-02-17 09:56:26 -0800643 *ptr = ctx->m_deviceMajorVersion;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800644 break;
645 case GL_MINOR_VERSION:
Lingfeng Yang324c8452017-02-17 09:56:26 -0800646 *ptr = ctx->m_deviceMinorVersion;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800647 break;
keunyoungb85b2752013-03-08 12:28:03 -0800648 case GL_NUM_SHADER_BINARY_FORMATS:
649 *ptr = 0;
650 break;
651 case GL_SHADER_BINARY_FORMATS:
652 // do nothing
653 break;
654
655 case GL_COMPRESSED_TEXTURE_FORMATS: {
656 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
657 if (ctx->m_num_compressedTextureFormats > 0 &&
658 compressedTextureFormats != NULL) {
659 memcpy(ptr, compressedTextureFormats,
660 ctx->m_num_compressedTextureFormats * sizeof(GLint));
661 }
662 break;
663 }
664
665 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
Lingfeng Yang48685bb2018-10-19 06:44:20 -0700666 if (ctx->m_max_combinedTextureImageUnits != 0) {
667 *ptr = ctx->m_max_combinedTextureImageUnits;
668 } else {
669 ctx->safe_glGetIntegerv(param, ptr);
670 ctx->m_max_combinedTextureImageUnits = *ptr;
671 }
672 break;
keunyoungb85b2752013-03-08 12:28:03 -0800673 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
674 case GL_MAX_TEXTURE_IMAGE_UNITS:
Lingfeng Yang80a36332017-07-09 10:58:07 -0700675 ctx->safe_glGetIntegerv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800676 *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
677 break;
678
679 case GL_TEXTURE_BINDING_2D:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700680 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800681 *ptr = state->getBoundTexture(GL_TEXTURE_2D);
682 break;
683 case GL_TEXTURE_BINDING_EXTERNAL_OES:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700684 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800685 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
686 break;
687
Lingfeng Yangb0176982016-03-01 21:27:49 -0800688 case GL_MAX_VERTEX_ATTRIBS:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700689 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
690 if (!state->getClientStateParameter<GLint>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700691 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700692 state->setMaxVertexAttribs(*ptr);
Yahan Zhoua5c36842016-06-01 12:49:39 -0700693 }
694 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800695 case GL_MAX_VERTEX_ATTRIB_STRIDE:
696 if (ctx->m_max_vertexAttribStride != 0) {
697 *ptr = ctx->m_max_vertexAttribStride;
698 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700699 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800700 ctx->m_max_vertexAttribStride = *ptr;
701 }
702 break;
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800703 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
704 if (ctx->m_max_cubeMapTextureSize != 0) {
705 *ptr = ctx->m_max_cubeMapTextureSize;
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_cubeMapTextureSize = *ptr;
709 }
710 break;
711 case GL_MAX_RENDERBUFFER_SIZE:
712 if (ctx->m_max_renderBufferSize != 0) {
713 *ptr = ctx->m_max_renderBufferSize;
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_renderBufferSize = *ptr;
717 }
718 break;
719 case GL_MAX_TEXTURE_SIZE:
720 if (ctx->m_max_textureSize != 0) {
721 *ptr = ctx->m_max_textureSize;
722 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700723 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800724 ctx->m_max_textureSize = *ptr;
Lingfeng Yangb0176982016-03-01 21:27:49 -0800725 }
726 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800727 case GL_MAX_3D_TEXTURE_SIZE:
728 if (ctx->m_max_3d_textureSize != 0) {
729 *ptr = ctx->m_max_3d_textureSize;
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_max_3d_textureSize = *ptr;
733 }
734 break;
735 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
736 if (ctx->m_ssbo_offset_align != 0) {
737 *ptr = ctx->m_ssbo_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_ssbo_offset_align = *ptr;
741 }
742 break;
743 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
744 if (ctx->m_ubo_offset_align != 0) {
745 *ptr = ctx->m_ubo_offset_align;
746 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700747 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800748 ctx->m_ubo_offset_align = *ptr;
749 }
750 break;
751 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
752 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
753 case GL_MAX_SAMPLES:
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800754 case GL_MAX_COLOR_TEXTURE_SAMPLES:
755 case GL_MAX_INTEGER_SAMPLES:
756 case GL_MAX_DEPTH_TEXTURE_SAMPLES:
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800757 *ptr = 4;
758 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700759 // Checks for version-incompatible enums.
760 // Not allowed in vanilla ES 2.0.
761 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
762 case GL_MAX_UNIFORM_BUFFER_BINDINGS:
763 SET_ERROR_IF(ctx->majorVersion() < 3, GL_INVALID_ENUM);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700764 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700765 break;
766 case GL_MAX_COLOR_ATTACHMENTS:
767 case GL_MAX_DRAW_BUFFERS:
768 SET_ERROR_IF(ctx->majorVersion() < 3 &&
769 !ctx->hasExtension("GL_EXT_draw_buffers"), GL_INVALID_ENUM);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700770 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700771 break;
772 // Not allowed in ES 3.0.
773 case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
774 case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
775 case GL_MAX_VERTEX_ATTRIB_BINDINGS:
776 SET_ERROR_IF(ctx->majorVersion() < 3 ||
777 (ctx->majorVersion() == 3 &&
778 ctx->minorVersion() == 0), GL_INVALID_ENUM);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700779 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700780 break;
keunyoungb85b2752013-03-08 12:28:03 -0800781 default:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700782 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
783 if (!state->getClientStateParameter<GLint>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700784 ctx->safe_glGetIntegerv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800785 }
786 break;
787 }
788}
789
790
791void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
792{
793 GL2Encoder *ctx = (GL2Encoder *)self;
keunyoungb85b2752013-03-08 12:28:03 -0800794 GLClientState* state = ctx->m_state;
795
796 switch (param) {
797 case GL_NUM_SHADER_BINARY_FORMATS:
798 *ptr = 0;
799 break;
800 case GL_SHADER_BINARY_FORMATS:
801 // do nothing
802 break;
803
804 case GL_COMPRESSED_TEXTURE_FORMATS: {
805 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
806 if (ctx->m_num_compressedTextureFormats > 0 &&
807 compressedTextureFormats != NULL) {
808 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
809 ptr[i] = (GLfloat) compressedTextureFormats[i];
810 }
811 }
812 break;
813 }
814
815 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
816 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
817 case GL_MAX_TEXTURE_IMAGE_UNITS:
Lingfeng Yang80a36332017-07-09 10:58:07 -0700818 ctx->safe_glGetFloatv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800819 *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
820 break;
821
822 case GL_TEXTURE_BINDING_2D:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700823 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800824 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
825 break;
826 case GL_TEXTURE_BINDING_EXTERNAL_OES:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700827 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800828 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
829 break;
830
831 default:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700832 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
833 if (!state->getClientStateParameter<GLfloat>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700834 ctx->safe_glGetFloatv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800835 }
836 break;
837 }
838}
839
840
841void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
842{
843 GL2Encoder *ctx = (GL2Encoder *)self;
keunyoungb85b2752013-03-08 12:28:03 -0800844 GLClientState* state = ctx->m_state;
845
846 switch (param) {
847 case GL_NUM_SHADER_BINARY_FORMATS:
848 *ptr = GL_FALSE;
849 break;
850 case GL_SHADER_BINARY_FORMATS:
851 // do nothing
852 break;
853
854 case GL_COMPRESSED_TEXTURE_FORMATS: {
855 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
856 if (ctx->m_num_compressedTextureFormats > 0 &&
857 compressedTextureFormats != NULL) {
858 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
859 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
860 }
861 }
862 break;
863 }
864
865 case GL_TEXTURE_BINDING_2D:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700866 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800867 *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
868 break;
869 case GL_TEXTURE_BINDING_EXTERNAL_OES:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700870 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800871 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
872 ? GL_TRUE : GL_FALSE;
873 break;
874
875 default:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700876 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
877 if (!state->getClientStateParameter<GLboolean>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700878 ctx->safe_glGetBooleanv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800879 }
bohu05101d22014-11-17 16:28:42 -0800880 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
keunyoungb85b2752013-03-08 12:28:03 -0800881 break;
882 }
883}
884
885
886void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
887{
888 GL2Encoder *ctx = (GL2Encoder *)self;
889 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -0800890 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800891 ctx->m_glEnableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800892 ctx->m_state->enable(index, 1);
893}
894
895void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
896{
897 GL2Encoder *ctx = (GL2Encoder *)self;
898 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -0800899 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800900 ctx->m_glDisableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800901 ctx->m_state->enable(index, 0);
902}
903
904
905void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
906{
907 GL2Encoder *ctx = (GL2Encoder *)self;
908 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700909 GLint maxIndex;
910 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
911 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800912
913 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
914 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
915 }
916}
917
918void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
919{
920 GL2Encoder *ctx = (GL2Encoder *)self;
921 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700922 GLint maxIndex;
923 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
924 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800925
926 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
927 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
928 }
929}
930
931void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
932{
933 GL2Encoder *ctx = (GL2Encoder *)self;
934 if (ctx->m_state == NULL) return;
Lingfeng Yang5e100432016-04-08 12:46:42 -0700935 GLint maxIndex;
936 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
937 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
938 SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100939 (void)pname;
940
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800941 *pointer = (GLvoid*)(ctx->m_state->getCurrAttributeBindingInfo(index).offset);
keunyoungb85b2752013-03-08 12:28:03 -0800942}
943
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700944void GL2Encoder::calcIndexRange(const void* indices,
945 GLenum type,
946 GLsizei count,
947 int* minIndex_out,
948 int* maxIndex_out) {
949 switch(type) {
950 case GL_BYTE:
951 case GL_UNSIGNED_BYTE:
952 GLUtils::minmaxExcept(
953 (unsigned char *)indices, count,
954 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800955 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned char>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700956 break;
957 case GL_SHORT:
958 case GL_UNSIGNED_SHORT:
959 GLUtils::minmaxExcept(
960 (unsigned short *)indices, count,
961 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800962 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned short>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700963 break;
964 case GL_INT:
965 case GL_UNSIGNED_INT:
966 GLUtils::minmaxExcept(
967 (unsigned int *)indices, count,
968 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800969 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned int>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700970 break;
971 default:
972 ALOGE("unsupported index buffer type %d\n", type);
973 }
974}
975
976void* GL2Encoder::recenterIndices(const void* src,
977 GLenum type,
978 GLsizei count,
979 int minIndex) {
980
981 void* adjustedIndices = (void*)src;
982
983 if (minIndex != 0) {
984 adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count);
985 switch(type) {
986 case GL_BYTE:
987 case GL_UNSIGNED_BYTE:
988 GLUtils::shiftIndicesExcept(
989 (unsigned char *)src,
990 (unsigned char *)adjustedIndices,
991 count, -minIndex,
992 m_primitiveRestartEnabled,
993 (unsigned char)m_primitiveRestartIndex);
994 break;
995 case GL_SHORT:
996 case GL_UNSIGNED_SHORT:
997 GLUtils::shiftIndicesExcept(
998 (unsigned short *)src,
999 (unsigned short *)adjustedIndices,
1000 count, -minIndex,
1001 m_primitiveRestartEnabled,
1002 (unsigned short)m_primitiveRestartIndex);
1003 break;
1004 case GL_INT:
1005 case GL_UNSIGNED_INT:
1006 GLUtils::shiftIndicesExcept(
1007 (unsigned int *)src,
1008 (unsigned int *)adjustedIndices,
1009 count, -minIndex,
1010 m_primitiveRestartEnabled,
1011 (unsigned int)m_primitiveRestartIndex);
1012 break;
1013 default:
1014 ALOGE("unsupported index buffer type %d\n", type);
1015 }
1016 }
1017
1018 return adjustedIndices;
1019}
1020
1021void GL2Encoder::getBufferIndexRange(BufferData* buf,
1022 const void* dataWithOffset,
1023 GLenum type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001024 size_t count,
1025 size_t offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001026 int* minIndex_out,
1027 int* maxIndex_out) {
1028
1029 if (buf->m_indexRangeCache.findRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001030 type, offset, count,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001031 m_primitiveRestartEnabled,
1032 minIndex_out,
1033 maxIndex_out)) {
1034 return;
1035 }
1036
1037 calcIndexRange(dataWithOffset, type, count, minIndex_out, maxIndex_out);
1038
1039 buf->m_indexRangeCache.addRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001040 type, offset, count, m_primitiveRestartEnabled,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001041 *minIndex_out, *maxIndex_out);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001042
1043 ALOGV("%s: got range [%u %u] pr? %d", __FUNCTION__, *minIndex_out, *maxIndex_out, m_primitiveRestartEnabled);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001044}
keunyoungb85b2752013-03-08 12:28:03 -08001045
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001046// For detecting legacy usage of glVertexAttribPointer
1047void GL2Encoder::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) const {
1048 if (hasClientArrays) *hasClientArrays = false;
1049 if (hasVBOs) *hasVBOs = false;
1050
1051 for (int i = 0; i < m_state->nLocations(); i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001052 const GLClientState::VertexAttribState& state = m_state->getState(i);
1053 if (state.enabled) {
1054 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
1055 GLuint bufferObject = curr_binding.buffer;
1056 if (bufferObject == 0 && curr_binding.offset && hasClientArrays) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001057 *hasClientArrays = true;
1058 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001059 if (bufferObject != 0 && hasVBOs) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001060 *hasVBOs = true;
1061 }
1062 }
1063 }
1064}
1065
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001066void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count, bool hasClientArrays, GLsizei primcount)
keunyoungb85b2752013-03-08 12:28:03 -08001067{
1068 assert(m_state);
1069
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001070 GLuint currentVao = m_state->currentVertexArrayObject();
Lingfeng Yang398162b2016-05-26 14:18:33 -07001071 GLuint lastBoundVbo = m_state->currentArrayVbo();
keunyoungb85b2752013-03-08 12:28:03 -08001072 for (int i = 0; i < m_state->nLocations(); i++) {
1073 bool enableDirty;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001074 const GLClientState::VertexAttribState& state = m_state->getStateAndEnableDirty(i, &enableDirty);
keunyoungb85b2752013-03-08 12:28:03 -08001075
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001076 if (!enableDirty && !state.enabled) {
keunyoungb85b2752013-03-08 12:28:03 -08001077 continue;
1078 }
1079
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001080 if (state.enabled) {
1081 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
1082 GLuint bufferObject = curr_binding.buffer;
1083 if (hasClientArrays && lastBoundVbo != bufferObject) {
1084 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, bufferObject);
1085 lastBoundVbo = bufferObject;
Lingfeng Yang398162b2016-05-26 14:18:33 -07001086 }
keunyoungb85b2752013-03-08 12:28:03 -08001087
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001088 int divisor = curr_binding.divisor;
1089 int stride = curr_binding.stride;
1090 int effectiveStride = curr_binding.effectiveStride;
1091 uintptr_t offset = curr_binding.offset;
Lingfeng Yang4e5446b2017-02-15 08:44:21 -08001092
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001093 int firstIndex = effectiveStride * first;
Lingfeng Yang4e5446b2017-02-15 08:44:21 -08001094 if (firstIndex && divisor && !primcount) {
1095 // If firstIndex != 0 according to effectiveStride * first,
1096 // it needs to be adjusted if a divisor has been specified,
1097 // even if we are not in glDraw***Instanced.
1098 firstIndex = 0;
1099 }
keunyoungb85b2752013-03-08 12:28:03 -08001100
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001101 if (bufferObject == 0) {
1102 unsigned int datalen = state.elementSize * count;
1103 if (divisor && primcount) {
1104 ALOGV("%s: divisor for att %d: %d, w/ stride %d (effective stride %d) size %d type 0x%x) datalen %u",
1105 __FUNCTION__, i, divisor, state.stride, effectiveStride, state.elementSize, state.type, datalen);
1106 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
1107 datalen = state.elementSize * actual_count;
1108 ALOGV("%s: actual datalen %u", __FUNCTION__, datalen);
1109 }
1110 if (state.elementSize == 0) {
Yahan Zhou3f2f1b42016-12-01 13:49:44 -08001111 // The vertex attribute array is uninitialized. Abandon it.
1112 ALOGE("a vertex attribute array is uninitialized. Skipping corresponding vertex attribute.");
1113 this->m_glDisableVertexAttribArray_enc(this, i);
1114 continue;
1115 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001116 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang000cf4c2017-01-25 08:09:02 -08001117
1118 if (datalen && (!offset || !((unsigned char*)offset + firstIndex))) {
1119 ALOGD("%s: bad offset / len!!!!!", __FUNCTION__);
1120 continue;
1121 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001122 if (state.isInt) {
1123 this->glVertexAttribIPointerDataAEMU(this, i, state.size, state.type, stride, (unsigned char *)offset + firstIndex, datalen);
1124 } else {
1125 this->glVertexAttribPointerData(this, i, state.size, state.type, state.normalized, stride, (unsigned char *)offset + firstIndex, datalen);
1126 }
keunyoungb85b2752013-03-08 12:28:03 -08001127 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001128 const BufferData* buf = m_shared->getBufferData(bufferObject);
Yahan Zhou5507c042016-06-01 17:24:28 -07001129 // The following expression actually means bufLen = stride*count;
1130 // But the last element doesn't have to fill up the whole stride.
1131 // So it becomes the current form.
Lingfeng Yang5fe99012017-01-18 09:17:09 -08001132 unsigned int bufLen = effectiveStride * (count ? (count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001133 if (divisor && primcount) {
1134 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
Lingfeng Yang5fe99012017-01-18 09:17:09 -08001135 bufLen = effectiveStride * (actual_count ? (actual_count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001136 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001137 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001138 if (hasClientArrays) {
1139 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001140 if (state.isInt) {
1141 this->glVertexAttribIPointerOffsetAEMU(this, i, state.size, state.type, stride, offset + firstIndex);
1142 } else {
1143 this->glVertexAttribPointerOffset(this, i, state.size, state.type, state.normalized, stride, offset + firstIndex);
1144 }
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001145 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001146 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001147 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=%p", buf);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -08001148 if (buf) {
1149 ALOGE("Out of bounds vertex attribute info: "
1150 "clientArray? %d attribute %d vbo %u allocedBufferSize %u bufferDataSpecified? %d wantedStart %u wantedEnd %u",
Lingfeng Yangddfb4452018-09-24 17:26:07 -07001151 hasClientArrays, i, bufferObject, (unsigned int)buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -08001152 }
1153 m_glDisableVertexAttribArray_enc(this, i);
Yahan Zhou5507c042016-06-01 17:24:28 -07001154 }
keunyoungb85b2752013-03-08 12:28:03 -08001155 }
1156 } else {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001157 if (hasClientArrays) {
1158 this->m_glDisableVertexAttribArray_enc(this, i);
1159 }
keunyoungb85b2752013-03-08 12:28:03 -08001160 }
1161 }
Lingfeng Yang398162b2016-05-26 14:18:33 -07001162
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001163 if (hasClientArrays && lastBoundVbo != m_state->currentArrayVbo()) {
Lingfeng Yang398162b2016-05-26 14:18:33 -07001164 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
1165 }
keunyoungb85b2752013-03-08 12:28:03 -08001166}
1167
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001168void GL2Encoder::flushDrawCall() {
Lingfeng Yang1ebb33c2017-01-19 08:04:48 -08001169 // This used to be every other draw call, but
1170 // now that we are using real GPU buffers on host,
1171 // set this to every 200 draw calls
1172 // (tuned on z840 linux NVIDIA Quadro K2200)
1173 if (m_drawCallFlushCount % 200 == 0) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001174 m_stream->flush();
1175 }
1176 m_drawCallFlushCount++;
1177}
1178
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001179static bool isValidDrawMode(GLenum mode)
1180{
1181 bool retval = false;
1182 switch (mode) {
1183 case GL_POINTS:
1184 case GL_LINE_STRIP:
1185 case GL_LINE_LOOP:
1186 case GL_LINES:
1187 case GL_TRIANGLE_STRIP:
1188 case GL_TRIANGLE_FAN:
1189 case GL_TRIANGLES:
1190 retval = true;
1191 }
1192 return retval;
1193}
1194
keunyoungb85b2752013-03-08 12:28:03 -08001195void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
1196{
1197 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001198 assert(ctx->m_state != NULL);
1199 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1200 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhoud6217a52016-02-10 16:10:46 -08001201
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001202 bool has_client_vertex_arrays = false;
1203 bool has_indirect_arrays = false;
1204 ctx->getVBOUsage(&has_client_vertex_arrays,
1205 &has_indirect_arrays);
1206
1207 if (has_client_vertex_arrays ||
1208 (!has_client_vertex_arrays &&
1209 !has_indirect_arrays)) {
1210 ctx->sendVertexAttributes(first, count, true);
1211 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
1212 } else {
1213 ctx->sendVertexAttributes(0, count, false);
1214 ctx->m_glDrawArrays_enc(ctx, mode, first, count);
1215 }
keunyoungb85b2752013-03-08 12:28:03 -08001216}
1217
1218
1219void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
1220{
1221
1222 GL2Encoder *ctx = (GL2Encoder *)self;
1223 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001224 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1225 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -07001226 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 -08001227 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001228
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001229 bool has_client_vertex_arrays = false;
keunyoungb85b2752013-03-08 12:28:03 -08001230 bool has_indirect_arrays = false;
1231 int nLocations = ctx->m_state->nLocations();
Yahan Zhou5507c042016-06-01 17:24:28 -07001232 GLintptr offset = 0;
keunyoungb85b2752013-03-08 12:28:03 -08001233
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001234 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
keunyoungb85b2752013-03-08 12:28:03 -08001235
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001236 if (!has_client_vertex_arrays && !has_indirect_arrays) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001237 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -07001238 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
1239 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001240 }
1241
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001242 BufferData* buf = NULL;
Yahan Zhou5507c042016-06-01 17:24:28 -07001243 int minIndex = 0, maxIndex = 0;
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001244
1245 // For validation/immediate index array purposes,
1246 // we need the min/max vertex index of the index array.
1247 // If the VBO != 0, this may not be the first time we have
1248 // used this particular index buffer. getBufferIndexRange
1249 // can more quickly get min/max vertex index by
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001250 // caching previous results.
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001251 if (ctx->m_state->currentIndexVbo() != 0) {
1252 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1253 offset = (GLintptr)indices;
1254 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
1255 ctx->getBufferIndexRange(buf,
1256 indices,
1257 type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001258 (size_t)count,
1259 (size_t)offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001260 &minIndex, &maxIndex);
1261 } else {
1262 // In this case, the |indices| field holds a real
1263 // array, so calculate the indices now. They will
1264 // also be needed to know how much data to
1265 // transfer to host.
1266 ctx->calcIndexRange(indices,
1267 type,
1268 count,
1269 &minIndex,
1270 &maxIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -07001271 }
1272
Lingfeng Yang26e629a2018-10-13 20:00:12 -07001273 if (count == 0) return;
1274
keunyoungb85b2752013-03-08 12:28:03 -08001275 bool adjustIndices = true;
1276 if (ctx->m_state->currentIndexVbo() != 0) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001277 if (!has_client_vertex_arrays) {
1278 ctx->sendVertexAttributes(0, maxIndex + 1, false);
keunyoungb85b2752013-03-08 12:28:03 -08001279 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -07001280 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001281 ctx->flushDrawCall();
keunyoungb85b2752013-03-08 12:28:03 -08001282 adjustIndices = false;
1283 } else {
1284 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1285 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001286 }
1287 }
1288 if (adjustIndices) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001289 void *adjustedIndices =
1290 ctx->recenterIndices(indices,
1291 type,
1292 count,
1293 minIndex);
keunyoungb85b2752013-03-08 12:28:03 -08001294
keunyoungb85b2752013-03-08 12:28:03 -08001295 if (has_indirect_arrays || 1) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001296 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
keunyoungb85b2752013-03-08 12:28:03 -08001297 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
1298 count * glSizeof(type));
1299 // XXX - OPTIMIZATION (see the other else branch) should be implemented
1300 if(!has_indirect_arrays) {
1301 //ALOGD("unoptimized drawelements !!!\n");
1302 }
1303 } else {
1304 // we are all direct arrays and immidate mode index array -
1305 // rebuild the arrays and the index array;
1306 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
1307 }
1308 }
1309}
1310
1311
1312GLint * GL2Encoder::getCompressedTextureFormats()
1313{
1314 if (m_compressedTextureFormats == NULL) {
1315 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
1316 &m_num_compressedTextureFormats);
1317 if (m_num_compressedTextureFormats > 0) {
1318 // get number of texture formats;
1319 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
1320 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
1321 }
1322 }
1323 return m_compressedTextureFormats;
1324}
1325
1326// Replace uses of samplerExternalOES with sampler2D, recording the names of
1327// modified shaders in data. Also remove
1328// #extension GL_OES_EGL_image_external : require
1329// statements.
1330//
1331// This implementation assumes the input has already been pre-processed. If not,
1332// a few cases will be mishandled:
1333//
1334// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
1335// the following code:
1336// #if 1
1337// uniform sampler2D mySampler;
1338// #else
1339// uniform samplerExternalOES mySampler;
1340// #endif
1341//
1342// 2. Comments that look like sampler declarations will be incorrectly modified
1343// and recorded:
1344// // samplerExternalOES hahaFooledYou
1345//
1346// 3. However, GLSL ES does not have a concatentation operator, so things like
1347// this (valid in C) are invalid and not a problem:
1348// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
1349// SAMPLER(ExternalOES, mySampler);
1350//
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001351
1352static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
1353static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
1354static const char STR_DEFINE[] = "#define";
1355
1356static std::vector<std::string> getSamplerExternalAliases(char* str) {
1357 std::vector<std::string> res;
1358
1359 res.push_back(STR_SAMPLER_EXTERNAL_OES);
1360
1361 // -- capture #define x samplerExternalOES
1362 char* c = str;
1363 while ((c = strstr(c, STR_DEFINE))) {
1364 // Don't push it if samplerExternalOES is not even there.
1365 char* samplerExternalOES_next = strstr(c, STR_SAMPLER_EXTERNAL_OES);
1366 if (!samplerExternalOES_next) break;
1367
1368 bool prevIdent = false;
1369
1370 std::vector<std::string> idents;
1371 std::string curr;
1372
1373 while (*c != '\0') {
1374
1375 if (isspace(*c)) {
1376 if (prevIdent) {
1377 idents.push_back(curr);
1378 curr = "";
1379 }
1380 }
1381
1382 if (*c == '\n' || idents.size() == 3) break;
1383
1384 if (isalpha(*c) || *c == '_') {
1385 curr.push_back(*c);
1386 prevIdent = true;
1387 }
1388
1389 ++c;
1390 }
1391
1392 if (idents.size() != 3) continue;
1393
1394 const std::string& defineLhs = idents[1];
1395 const std::string& defineRhs = idents[2];
1396
1397 if (defineRhs == STR_SAMPLER_EXTERNAL_OES) {
1398 res.push_back(defineLhs);
1399 }
1400
1401 if (*c == '\0') break;
1402 }
1403
1404 return res;
1405}
1406
1407static bool replaceExternalSamplerUniformDefinition(char* str, const std::string& samplerExternalType, ShaderData* data) {
1408 // -- replace "samplerExternalOES" with "sampler2D" and record name
1409 char* c = str;
1410 while ((c = strstr(c, samplerExternalType.c_str()))) {
1411 // Make sure "samplerExternalOES" isn't a substring of a larger token
1412 if (c == str || !isspace(*(c-1))) {
1413 c++;
1414 continue;
1415 }
1416 char* sampler_start = c;
1417 c += samplerExternalType.size();
1418 if (!isspace(*c) && *c != '\0') {
1419 continue;
1420 }
1421
1422 // capture sampler name
1423 while (isspace(*c) && *c != '\0') {
1424 c++;
1425 }
1426 if (!isalpha(*c) && *c != '_') {
1427 // not an identifier
1428 return false;
1429 }
1430 char* name_start = c;
1431 do {
1432 c++;
1433 } while (isalnum(*c) || *c == '_');
Lingfeng Yang44209df2018-09-21 10:04:17 -07001434
1435 size_t len = (size_t)(c - name_start);
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001436 data->samplerExternalNames.push_back(
Lingfeng Yang44209df2018-09-21 10:04:17 -07001437 std::string(name_start, len));
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001438
1439 // We only need to perform a string replacement for the original
1440 // occurrence of samplerExternalOES if a #define was used.
1441 //
1442 // The important part was to record the name in
1443 // |data->samplerExternalNames|.
1444 if (samplerExternalType == STR_SAMPLER_EXTERNAL_OES) {
1445 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
1446 }
1447 }
1448
1449 return true;
1450}
1451
keunyoungb85b2752013-03-08 12:28:03 -08001452static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
1453{
1454 static const char STR_HASH_EXTENSION[] = "#extension";
1455 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
Lingfeng Yang3546c4d2018-04-10 12:34:30 -07001456 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3[] = "GL_OES_EGL_image_external_essl3";
keunyoungb85b2752013-03-08 12:28:03 -08001457
1458 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
1459 char* c = str;
1460 while ((c = strstr(c, STR_HASH_EXTENSION))) {
1461 char* start = c;
1462 c += sizeof(STR_HASH_EXTENSION)-1;
1463 while (isspace(*c) && *c != '\0') {
1464 c++;
1465 }
Lingfeng Yang3546c4d2018-04-10 12:34:30 -07001466
1467 bool hasBaseImageExternal =
1468 !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
1469 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL) - 1);
1470 bool hasEssl3ImageExternal =
1471 !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3,
1472 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3) - 1);
1473
1474 if (hasBaseImageExternal || hasEssl3ImageExternal)
keunyoungb85b2752013-03-08 12:28:03 -08001475 {
1476 // #extension statements are terminated by end of line
1477 c = start;
1478 while (*c != '\0' && *c != '\r' && *c != '\n') {
1479 *c++ = ' ';
1480 }
1481 }
1482 }
1483
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001484 std::vector<std::string> samplerExternalAliases =
1485 getSamplerExternalAliases(str);
keunyoungb85b2752013-03-08 12:28:03 -08001486
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001487 for (size_t i = 0; i < samplerExternalAliases.size(); i++) {
1488 if (!replaceExternalSamplerUniformDefinition(
1489 str, samplerExternalAliases[i], data))
keunyoungb85b2752013-03-08 12:28:03 -08001490 return false;
keunyoungb85b2752013-03-08 12:28:03 -08001491 }
1492
1493 return true;
1494}
1495
Bo Hu73568cd2015-01-20 16:29:50 -08001496void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
1497{
1498 GL2Encoder* ctx = (GL2Encoder*)self;
1499 // Although it is not supported, need to set proper error code.
1500 SET_ERROR_IF(1, GL_INVALID_ENUM);
1501}
1502
David 'Digit' Turner02fdb692014-10-30 18:07:56 +01001503void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -08001504{
1505 GL2Encoder* ctx = (GL2Encoder*)self;
1506 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001507 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(shader), GL_INVALID_VALUE);
Tina Zhang7a84f652014-12-04 12:37:30 +08001508 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
1509 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001510
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001511 // Track original sources---they may be translated in the backend
1512 std::vector<std::string> orig_sources;
1513 for (int i = 0; i < count; i++) {
1514 orig_sources.push_back(std::string((const char*)(string[i])));
1515 }
1516 shaderData->sources = orig_sources;
1517
keunyoungb85b2752013-03-08 12:28:03 -08001518 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
1519 char *str = new char[len + 1];
1520 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
1521
1522 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
1523 // Perhaps we can borrow Mesa's pre-processor?
1524
1525 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001526 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001527 ctx->setError(GL_OUT_OF_MEMORY);
1528 return;
1529 }
keunyoungb85b2752013-03-08 12:28:03 -08001530 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001531 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001532}
1533
1534void GL2Encoder::s_glFinish(void *self)
1535{
1536 GL2Encoder *ctx = (GL2Encoder *)self;
1537 ctx->glFinishRoundTrip(self);
1538}
1539
1540void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1541{
1542 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -08001543 bool isProgram = ctx->m_shared->isProgram(program);
1544 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
1545 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
1546
keunyoungb85b2752013-03-08 12:28:03 -08001547 ctx->m_glLinkProgram_enc(self, program);
1548
1549 GLint linkStatus = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07001550 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001551 if (!linkStatus) {
keunyoungb85b2752013-03-08 12:28:03 -08001552 return;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001553 }
keunyoungb85b2752013-03-08 12:28:03 -08001554
1555 //get number of active uniforms in the program
1556 GLint numUniforms=0;
1557 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
1558 ctx->m_shared->initProgramData(program,numUniforms);
1559
1560 //get the length of the longest uniform name
1561 GLint maxLength=0;
1562 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
1563
1564 GLint size;
1565 GLenum type;
1566 GLchar *name = new GLchar[maxLength+1];
1567 GLint location;
1568 //for each active uniform, get its size and starting location.
1569 for (GLint i=0 ; i<numUniforms ; ++i)
1570 {
1571 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1572 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1573 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1574 }
1575 ctx->m_shared->setupLocationShiftWAR(program);
1576
1577 delete[] name;
1578}
1579
1580void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1581{
1582 GL2Encoder *ctx = (GL2Encoder*)self;
1583 ctx->m_glDeleteProgram_enc(self, program);
1584
1585 ctx->m_shared->deleteProgramData(program);
1586}
1587
1588void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1589{
1590 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001591 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001592 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001593 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1594 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1595 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1596 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1597}
1598void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1599{
1600 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001601 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001602 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001603 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1604 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1605 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1606 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1607}
1608
1609GLuint GL2Encoder::s_glCreateProgram(void * self)
1610{
1611 GL2Encoder *ctx = (GL2Encoder*)self;
1612 GLuint program = ctx->m_glCreateProgram_enc(self);
1613 if (program!=0)
1614 ctx->m_shared->addProgramData(program);
1615 return program;
1616}
1617
1618GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1619{
1620 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001621 RET_AND_SET_ERROR_IF(!GLESv2Validation::shaderType(ctx, shaderType), GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001622 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1623 if (shader != 0) {
1624 if (!ctx->m_shared->addShaderData(shader)) {
1625 ctx->m_glDeleteShader_enc(self, shader);
1626 return 0;
1627 }
1628 }
1629 return shader;
1630}
1631
bohu56bf82f2014-10-17 15:35:48 -07001632void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1633 GLsizei* count, GLuint* shaders)
1634{
1635 GL2Encoder *ctx = (GL2Encoder*)self;
1636 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1637 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1638}
1639
1640void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1641 GLsizei* length, GLchar* source)
1642{
1643 GL2Encoder *ctx = (GL2Encoder*)self;
1644 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1645 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001646 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
1647 if (shaderData) {
1648 std::string returned;
1649 int curr_len = 0;
1650 for (int i = 0; i < shaderData->sources.size(); i++) {
1651 if (curr_len + shaderData->sources[i].size() < bufsize - 1) {
1652 returned += shaderData->sources[i];
1653 } else {
1654 returned += shaderData->sources[i].substr(0, bufsize - 1 - curr_len);
1655 break;
1656 }
1657 }
1658 memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize);
1659 }
bohu56bf82f2014-10-17 15:35:48 -07001660}
1661
1662void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, 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_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1668}
1669
1670void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1671 GLsizei* length, GLchar* infolog)
1672{
1673 GL2Encoder *ctx = (GL2Encoder*)self;
1674 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1675 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1676}
1677
keunyoungb85b2752013-03-08 12:28:03 -08001678void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1679{
1680 GL2Encoder *ctx = (GL2Encoder*)self;
1681 ctx->m_glDeleteShader_enc(self,shader);
1682 ctx->m_shared->unrefShaderData(shader);
1683}
1684
1685void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1686{
1687 GL2Encoder *ctx = (GL2Encoder*)self;
1688 ctx->m_glAttachShader_enc(self, program, shader);
1689 ctx->m_shared->attachShader(program, shader);
1690}
1691
1692void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1693{
1694 GL2Encoder *ctx = (GL2Encoder*)self;
1695 ctx->m_glDetachShader_enc(self, program, shader);
1696 ctx->m_shared->detachShader(program, shader);
1697}
1698
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001699int sArrIndexOfUniformExpr(const char* name, int* err) {
1700 *err = 0;
1701 int arrIndex = 0;
1702 int namelen = strlen(name);
1703 if (name[namelen-1] == ']') {
1704 const char *brace = strrchr(name,'[');
1705 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1706 *err = 1; return 0;
1707 }
1708 }
1709 return arrIndex;
1710}
1711
keunyoungb85b2752013-03-08 12:28:03 -08001712int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1713{
1714 if (!name) return -1;
1715
1716 GL2Encoder *ctx = (GL2Encoder*)self;
1717
1718 // if we need the uniform location WAR
1719 // parse array index from the end of the name string
1720 int arrIndex = 0;
1721 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1722 if (needLocationWAR) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001723 int err;
1724 arrIndex = sArrIndexOfUniformExpr(name, &err);
1725 if (err) return -1;
keunyoungb85b2752013-03-08 12:28:03 -08001726 }
1727
1728 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1729 if (hostLoc >= 0 && needLocationWAR) {
1730 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1731 }
1732 return hostLoc;
1733}
1734
1735bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1736{
1737 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1738 return false;
1739
1740 m_state->setActiveTextureUnit(texUnit);
1741
1742 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1743 if (newTarget != oldTarget) {
1744 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1745 m_state->disableTextureTarget(GL_TEXTURE_2D);
1746 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1747 } else {
1748 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1749 m_state->enableTextureTarget(GL_TEXTURE_2D);
1750 }
1751 m_glActiveTexture_enc(this, texUnit);
1752 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1753 m_state->getBoundTexture(newTarget));
1754 return true;
1755 }
1756
1757 return false;
1758}
1759
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001760void GL2Encoder::updateHostTexture2DBindingsFromProgramData(GLuint program) {
1761 GL2Encoder *ctx = this;
keunyoungb85b2752013-03-08 12:28:03 -08001762 GLClientState* state = ctx->m_state;
1763 GLSharedGroupPtr shared = ctx->m_shared;
1764
keunyoungb85b2752013-03-08 12:28:03 -08001765 GLenum origActiveTexture = state->getActiveTextureUnit();
1766 GLenum hostActiveTexture = origActiveTexture;
1767 GLint samplerIdx = -1;
1768 GLint samplerVal;
1769 GLenum samplerTarget;
1770 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1771 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1772 continue;
1773 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001774 samplerTarget))
keunyoungb85b2752013-03-08 12:28:03 -08001775 {
1776 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1777 }
1778 }
1779 state->setActiveTextureUnit(origActiveTexture);
1780 if (hostActiveTexture != origActiveTexture) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001781 ctx->m_glActiveTexture_enc(ctx, origActiveTexture);
keunyoungb85b2752013-03-08 12:28:03 -08001782 }
1783}
1784
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001785void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1786{
1787 GL2Encoder *ctx = (GL2Encoder*)self;
1788 GLSharedGroupPtr shared = ctx->m_shared;
1789
1790 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
1791 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1792
1793 ctx->m_glUseProgram_enc(self, program);
1794 ctx->m_state->setCurrentProgram(program);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001795 ctx->m_state->setCurrentShaderProgram(program);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001796
1797 ctx->updateHostTexture2DBindingsFromProgramData(program);
1798}
1799
keunyoungb85b2752013-03-08 12:28:03 -08001800void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1801{
1802 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001803 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001804 ctx->m_glUniform1f_enc(self, hostLoc, x);
1805}
1806
1807void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1808{
1809 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001810 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001811 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1812}
1813
1814void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1815{
1816 GL2Encoder *ctx = (GL2Encoder*)self;
1817 GLClientState* state = ctx->m_state;
1818 GLSharedGroupPtr shared = ctx->m_shared;
1819
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001820 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001821 ctx->m_glUniform1i_enc(self, hostLoc, x);
1822
1823 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001824 if (shared->setSamplerUniform(state->currentShaderProgram(), location, x, &target)) {
keunyoungb85b2752013-03-08 12:28:03 -08001825 GLenum origActiveTexture = state->getActiveTextureUnit();
1826 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1827 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1828 }
1829 state->setActiveTextureUnit(origActiveTexture);
1830 }
1831}
1832
1833void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1834{
1835 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001836 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001837 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1838}
1839
1840void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1841{
1842 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001843 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001844 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1845}
1846
1847void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1848{
1849 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001850 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001851 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1852}
1853
1854void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1855{
1856 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001857 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001858 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1859}
1860
1861void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1862{
1863 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001864 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001865 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1866}
1867
1868void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1869{
1870 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001871 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001872 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1873}
1874
1875void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1876{
1877 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001878 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001879 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1880}
1881
1882void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1883{
1884 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001885 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001886 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1887}
1888
1889void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1890{
1891 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001892 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001893 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1894}
1895
1896void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1897{
1898 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001899 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001900 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1901}
1902
1903void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1904{
1905 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001906 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001907 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1908}
1909
1910void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1911{
1912 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001913 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001914 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1915}
1916
1917void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1918{
1919 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001920 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001921 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1922}
1923
1924void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1925{
1926 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001927 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001928 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1929}
1930
1931void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1932{
1933 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001934 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001935 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1936}
1937
1938void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1939{
1940 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001941 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001942 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1943}
1944
1945void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1946{
1947 GL2Encoder* ctx = (GL2Encoder*)self;
1948 GLClientState* state = ctx->m_state;
1949 GLenum err;
1950
1951 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1952
1953 ctx->m_glActiveTexture_enc(ctx, texture);
1954}
1955
1956void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1957{
1958 GL2Encoder* ctx = (GL2Encoder*)self;
1959 GLClientState* state = ctx->m_state;
1960 GLenum err;
1961 GLboolean firstUse;
1962
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001963 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -08001964 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1965
1966 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1967 ctx->m_glBindTexture_enc(ctx, target, texture);
1968 return;
1969 }
1970
1971 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1972
1973 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1974 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1975 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1976 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1977 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1978 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1979 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1980 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1981
1982 if (target != priorityTarget) {
1983 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1984 state->getBoundTexture(GL_TEXTURE_2D));
1985 }
1986 }
1987
1988 if (target == priorityTarget) {
1989 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1990 }
1991}
1992
1993void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1994{
1995 GL2Encoder* ctx = (GL2Encoder*)self;
1996 GLClientState* state = ctx->m_state;
1997
1998 state->deleteTextures(n, textures);
1999 ctx->m_glDeleteTextures_enc(ctx, n, textures);
2000}
2001
2002void GL2Encoder::s_glGetTexParameterfv(void* self,
2003 GLenum target, GLenum pname, GLfloat* params)
2004{
2005 GL2Encoder* ctx = (GL2Encoder*)self;
2006 const GLClientState* state = ctx->m_state;
2007
2008 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2009 ctx->override2DTextureTarget(target);
2010 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002011 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002012 } else {
2013 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
2014 }
2015}
2016
2017void GL2Encoder::s_glGetTexParameteriv(void* self,
2018 GLenum target, GLenum pname, GLint* params)
2019{
2020 GL2Encoder* ctx = (GL2Encoder*)self;
2021 const GLClientState* state = ctx->m_state;
2022
2023 switch (pname) {
2024 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
2025 *params = 1;
2026 break;
2027
2028 default:
2029 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2030 ctx->override2DTextureTarget(target);
2031 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002032 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002033 } else {
2034 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
2035 }
2036 break;
2037 }
2038}
2039
2040static bool isValidTextureExternalParam(GLenum pname, GLenum param)
2041{
2042 switch (pname) {
2043 case GL_TEXTURE_MIN_FILTER:
2044 case GL_TEXTURE_MAG_FILTER:
2045 return param == GL_NEAREST || param == GL_LINEAR;
2046
2047 case GL_TEXTURE_WRAP_S:
2048 case GL_TEXTURE_WRAP_T:
2049 return param == GL_CLAMP_TO_EDGE;
2050
2051 default:
2052 return true;
2053 }
2054}
2055
2056void GL2Encoder::s_glTexParameterf(void* self,
2057 GLenum target, GLenum pname, GLfloat param)
2058{
2059 GL2Encoder* ctx = (GL2Encoder*)self;
2060 const GLClientState* state = ctx->m_state;
2061
2062 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2063 !isValidTextureExternalParam(pname, (GLenum)param)),
2064 GL_INVALID_ENUM);
2065
2066 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2067 ctx->override2DTextureTarget(target);
2068 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002069 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002070 } else {
2071 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
2072 }
2073}
2074
2075void GL2Encoder::s_glTexParameterfv(void* self,
2076 GLenum target, GLenum pname, const GLfloat* params)
2077{
2078 GL2Encoder* ctx = (GL2Encoder*)self;
2079 const GLClientState* state = ctx->m_state;
2080
2081 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2082 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2083 GL_INVALID_ENUM);
2084
2085 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2086 ctx->override2DTextureTarget(target);
2087 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002088 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002089 } else {
2090 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
2091 }
2092}
2093
2094void GL2Encoder::s_glTexParameteri(void* self,
2095 GLenum target, GLenum pname, GLint param)
2096{
2097 GL2Encoder* ctx = (GL2Encoder*)self;
2098 const GLClientState* state = ctx->m_state;
2099
2100 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2101 !isValidTextureExternalParam(pname, (GLenum)param)),
2102 GL_INVALID_ENUM);
2103
2104 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2105 ctx->override2DTextureTarget(target);
2106 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002107 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002108 } else {
2109 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
2110 }
2111}
2112
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002113static int ilog2(uint32_t x) {
2114 int p = 0;
2115 while ((1 << p) < x)
2116 p++;
2117 return p;
2118}
2119
bohu26a92982014-11-25 16:50:37 -08002120void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
2121 GLint internalformat, GLsizei width, GLsizei height, GLint border,
2122 GLenum format, GLenum type, const GLvoid* pixels)
2123{
2124 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07002125 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002126
2127 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2128 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2129 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2130 // If unpack buffer is nonzero, verify unmapped state.
2131 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2132
2133 GLint max_texture_size;
2134 GLint max_cube_map_texture_size;
2135 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2136 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2137 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2138 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2139 SET_ERROR_IF((target == GL_TEXTURE_CUBE_MAP) &&
2140 (level > ilog2(max_cube_map_texture_size)), GL_INVALID_VALUE);
2141 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2142 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2143 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2144 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && width > max_cube_map_texture_size, GL_INVALID_VALUE);
2145 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && height > max_cube_map_texture_size, GL_INVALID_VALUE);
2146 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
2147 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2148 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2149 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2150 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 0) >
2151 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2152 GL_INVALID_OPERATION);
2153 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2154 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2155 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2156 glSizeof(type)),
2157 GL_INVALID_OPERATION);
2158 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2159 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2160 ((uintptr_t)pixels % glSizeof(type)),
2161 GL_INVALID_OPERATION);
2162 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
2163
2164 GLenum stateTarget = target;
2165 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2166 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2167 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2168 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2169 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2170 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2171 stateTarget = GL_TEXTURE_CUBE_MAP;
2172
2173 state->setBoundTextureInternalFormat(stateTarget, internalformat);
2174 state->setBoundTextureFormat(stateTarget, format);
2175 state->setBoundTextureType(stateTarget, type);
2176 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2177
bohu26a92982014-11-25 16:50:37 -08002178 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2179 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002180 }
Lingfeng Yang69066602016-04-12 09:29:11 -07002181
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002182 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2183 ctx->glTexImage2DOffsetAEMU(
2184 ctx, target, level, internalformat,
2185 width, height, border,
2186 format, type, (uintptr_t)pixels);
bohu26a92982014-11-25 16:50:37 -08002187 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002188 ctx->m_glTexImage2D_enc(
2189 ctx, target, level, internalformat,
2190 width, height, border,
2191 format, type, pixels);
2192 }
2193
2194 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2195 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08002196 }
2197}
2198
Yahan Zhou2a208292016-06-22 15:36:04 -07002199void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
2200 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
2201 GLenum type, const GLvoid* pixels)
2202{
2203 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002204 GLClientState* state = ctx->m_state;
2205
2206 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2207 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2208 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2209 // If unpack buffer is nonzero, verify unmapped state.
2210 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2211
2212 GLint max_texture_size;
2213 GLint max_cube_map_texture_size;
2214 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2215 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2216 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2217 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2218 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) &&
2219 level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2220 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2221 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2222
2223 GLuint tex = state->getBoundTexture(target);
2224 GLsizei neededWidth = xoffset + width;
2225 GLsizei neededHeight = yoffset + height;
2226 GLsizei neededDepth = 1;
2227
2228 if (tex && !state->queryTexEGLImageBacked(tex)) {
2229 SET_ERROR_IF(
2230 (neededWidth > state->queryTexWidth(level, tex) ||
2231 neededHeight > state->queryTexHeight(level, tex) ||
2232 neededDepth > state->queryTexDepth(level, tex)),
2233 GL_INVALID_VALUE);
2234 }
2235
2236 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2237 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2238 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2239 (state->pboNeededDataSize(width, height, 1, format, type, 0) >
2240 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2241 GL_INVALID_OPERATION);
2242 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2243 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2244 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2245 glSizeof(type)),
2246 GL_INVALID_OPERATION);
2247 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !pixels, GL_INVALID_OPERATION);
Yahan Zhou2a208292016-06-22 15:36:04 -07002248
2249 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2250 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002251 }
2252
2253 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2254 ctx->glTexSubImage2DOffsetAEMU(
2255 ctx, target, level,
2256 xoffset, yoffset, width, height,
2257 format, type, (uintptr_t)pixels);
Yahan Zhou2a208292016-06-22 15:36:04 -07002258 } else {
2259 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
2260 height, format, type, pixels);
2261 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002262
2263 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2264 ctx->restore2DTextureTarget(target);
2265 }
Yahan Zhou2a208292016-06-22 15:36:04 -07002266}
bohu26a92982014-11-25 16:50:37 -08002267
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002268void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
2269 GLenum internalformat, GLint x, GLint y,
2270 GLsizei width, GLsizei height, GLint border)
2271{
2272 GL2Encoder* ctx = (GL2Encoder*)self;
2273 GLClientState* state = ctx->m_state;
2274
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002275 SET_ERROR_IF(ctx->glCheckFramebufferStatus(ctx, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
2276 GL_INVALID_FRAMEBUFFER_OPERATION);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002277 // This is needed to work around underlying OpenGL drivers
2278 // (such as those feeding some some AMD GPUs) that expect
2279 // positive components of cube maps to be defined _before_
2280 // the negative components (otherwise a segfault occurs).
2281 GLenum extraTarget =
2282 state->copyTexImageLuminanceCubeMapAMDWorkaround
2283 (target, level, internalformat);
2284
2285 if (extraTarget) {
2286 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
2287 x, y, width, height, border);
2288 }
2289
2290 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
2291 x, y, width, height, border);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002292
2293 state->setBoundTextureInternalFormat(target, internalformat);
2294 state->setBoundTextureDims(target, level, width, height, 1);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002295}
2296
keunyoungb85b2752013-03-08 12:28:03 -08002297void GL2Encoder::s_glTexParameteriv(void* self,
2298 GLenum target, GLenum pname, const GLint* params)
2299{
2300 GL2Encoder* ctx = (GL2Encoder*)self;
2301 const GLClientState* state = ctx->m_state;
2302
2303 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2304 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2305 GL_INVALID_ENUM);
2306
2307 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2308 ctx->override2DTextureTarget(target);
2309 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002310 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002311 } else {
2312 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
2313 }
2314}
2315
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002316bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
2317 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
2318 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2319}
2320
keunyoungb85b2752013-03-08 12:28:03 -08002321void GL2Encoder::override2DTextureTarget(GLenum target)
2322{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002323 if (texture2DNeedsOverride(target)) {
2324 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2325 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08002326 }
2327}
2328
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002329void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08002330{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002331 if (texture2DNeedsOverride(target)) {
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002332 GLuint priorityEnabledBoundTexture =
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002333 m_state->getBoundTexture(
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002334 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D));
2335 GLuint texture2DBoundTexture =
2336 m_state->getBoundTexture(GL_TEXTURE_2D);
2337 if (!priorityEnabledBoundTexture) {
2338 m_glBindTexture_enc(this, GL_TEXTURE_2D, texture2DBoundTexture);
2339 } else {
2340 m_glBindTexture_enc(this, GL_TEXTURE_2D, priorityEnabledBoundTexture);
2341 }
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002342 }
keunyoungb85b2752013-03-08 12:28:03 -08002343}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002344
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002345void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2346 m_state->setBoundEGLImage(target, eglImage);
2347}
2348
2349
2350GLuint GL2Encoder::boundBuffer(GLenum target) const {
2351 return m_state->getBuffer(target);
2352}
2353
2354BufferData* GL2Encoder::getBufferData(GLenum target) const {
2355 GLuint bufferId = m_state->getBuffer(target);
2356 if (!bufferId) return NULL;
2357 return m_shared->getBufferData(bufferId);
2358}
2359
2360BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2361 if (!bufferId) return NULL;
2362 return m_shared->getBufferData(bufferId);
2363}
2364
2365bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2366 return m_shared->getBufferData(buffer)->m_mapped;
2367}
2368
2369bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2370 BufferData* buf = getBufferData(target);
2371 if (!buf) return false;
2372 return buf->m_mapped;
2373}
2374
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002375void GL2Encoder::s_glGenRenderbuffers(void* self,
2376 GLsizei n, GLuint* renderbuffers) {
2377 GL2Encoder* ctx = (GL2Encoder*)self;
2378 GLClientState* state = ctx->m_state;
2379
2380 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2381
2382 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2383 state->addRenderbuffers(n, renderbuffers);
2384}
2385
2386void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2387 GLsizei n, const GLuint* renderbuffers) {
2388 GL2Encoder* ctx = (GL2Encoder*)self;
2389 GLClientState* state = ctx->m_state;
2390
2391 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2392
2393 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002394
2395 // Nope, lets just leak those for now.
2396 // The spec has an *amazingly* convoluted set of conditions for when
2397 // render buffers are actually deleted:
2398 // 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.
2399 //
2400 // 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***
2401 //
2402 // So, just detach this one from the bound FBO, and ignore the rest.
2403 for (int i = 0; i < n; i++) {
2404 state->detachRbo(renderbuffers[i]);
2405 }
2406 // state->removeRenderbuffers(n, renderbuffers);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002407}
2408
2409void GL2Encoder::s_glBindRenderbuffer(void* self,
2410 GLenum target, GLuint renderbuffer) {
2411 GL2Encoder* ctx = (GL2Encoder*)self;
2412 GLClientState* state = ctx->m_state;
2413
2414 SET_ERROR_IF((target != GL_RENDERBUFFER),
2415 GL_INVALID_ENUM);
2416
2417 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2418 state->bindRenderbuffer(target, renderbuffer);
2419}
2420
Lingfeng Yang69066602016-04-12 09:29:11 -07002421void GL2Encoder::s_glRenderbufferStorage(void* self,
2422 GLenum target, GLenum internalformat,
2423 GLsizei width, GLsizei height) {
2424 GL2Encoder* ctx = (GL2Encoder*) self;
2425 GLClientState* state = ctx->m_state;
2426
2427 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002428 SET_ERROR_IF(
2429 !GLESv2Validation::rboFormat(ctx, internalformat),
2430 GL_INVALID_ENUM);
Lingfeng Yang69066602016-04-12 09:29:11 -07002431
2432 state->setBoundRenderbufferFormat(internalformat);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002433 state->setBoundRenderbufferSamples(0);
2434
Lingfeng Yang69066602016-04-12 09:29:11 -07002435 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
2436 width, height);
2437}
2438
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002439void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
2440 GLenum target, GLenum attachment,
2441 GLenum renderbuffertarget, GLuint renderbuffer) {
2442 GL2Encoder* ctx = (GL2Encoder*)self;
2443 GLClientState* state = ctx->m_state;
2444
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002445 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2446 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2447 state->attachRbo(target, attachment, renderbuffer);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002448
2449 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
2450}
2451
2452void GL2Encoder::s_glGenFramebuffers(void* self,
2453 GLsizei n, GLuint* framebuffers) {
2454 GL2Encoder* ctx = (GL2Encoder*)self;
2455 GLClientState* state = ctx->m_state;
2456
2457 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2458
2459 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2460 state->addFramebuffers(n, framebuffers);
2461}
2462
2463void GL2Encoder::s_glDeleteFramebuffers(void* self,
2464 GLsizei n, const GLuint* framebuffers) {
2465 GL2Encoder* ctx = (GL2Encoder*)self;
2466 GLClientState* state = ctx->m_state;
2467
2468 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2469
2470 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2471 state->removeFramebuffers(n, framebuffers);
2472}
2473
2474void GL2Encoder::s_glBindFramebuffer(void* self,
2475 GLenum target, GLuint framebuffer) {
2476 GL2Encoder* ctx = (GL2Encoder*)self;
2477 GLClientState* state = ctx->m_state;
2478
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002479 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002480
2481 state->bindFramebuffer(target, framebuffer);
2482
2483 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
2484}
2485
2486void GL2Encoder::s_glFramebufferTexture2D(void* self,
2487 GLenum target, GLenum attachment,
2488 GLenum textarget, GLuint texture, GLint level) {
2489 GL2Encoder* ctx = (GL2Encoder*)self;
2490 GLClientState* state = ctx->m_state;
2491
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002492 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2493 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2494 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002495
2496 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
2497}
2498
2499void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2500 GLenum target, GLenum attachment,
2501 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2502 GL2Encoder* ctx = (GL2Encoder*)self;
2503 GLClientState* state = ctx->m_state;
2504
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002505 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002506
2507 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2508}
2509
2510void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2511 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2512 GL2Encoder* ctx = (GL2Encoder*)self;
2513 const GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002514 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2515 SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2516 pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE &&
2517 !state->attachmentHasObject(target, attachment),
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002518 GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002519 SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL ||
2520 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE ||
2521 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) &&
2522 (!state->attachmentHasObject(target, attachment) ||
2523 state->getBoundFramebufferAttachmentType(target, attachment) !=
2524 FBO_ATTACHMENT_TEXTURE),
2525 !state->attachmentHasObject(target, attachment) ?
2526 GL_INVALID_OPERATION : GL_INVALID_ENUM);
2527 SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2528 pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2529 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
2530 state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
2531 GL_INVALID_OPERATION);
2532 SET_ERROR_IF(state->boundFramebuffer(target) &&
2533 (attachment == GL_BACK ||
2534 attachment == GL_FRONT),
2535 GL_INVALID_OPERATION);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002536 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
2537}
Lingfeng Yang69066602016-04-12 09:29:11 -07002538
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002539bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state,
Lingfeng Yang69066602016-04-12 09:29:11 -07002540 GLenum attachment) const {
2541 FboFormatInfo fbo_format_info;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002542 state->getBoundFramebufferFormat(target, attachment, &fbo_format_info);
Lingfeng Yang69066602016-04-12 09:29:11 -07002543
2544 bool res;
2545 switch (fbo_format_info.type) {
2546 case FBO_ATTACHMENT_RENDERBUFFER:
2547 switch (fbo_format_info.rb_format) {
2548 case GL_R16F:
2549 case GL_RG16F:
Lingfeng Yang69066602016-04-12 09:29:11 -07002550 case GL_RGBA16F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002551 case GL_R32F:
2552 case GL_RG32F:
2553 case GL_RGBA32F:
2554 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002555 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002556 break;
2557 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002558 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang69066602016-04-12 09:29:11 -07002559 break;
2560 case GL_STENCIL_INDEX8:
2561 if (attachment == GL_STENCIL_ATTACHMENT) {
2562 res = true;
2563 } else {
2564 res = false;
2565 }
2566 break;
2567 default:
2568 res = true;
2569 }
2570 break;
2571 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002572 switch (fbo_format_info.tex_internalformat) {
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002573 case GL_R16F:
2574 case GL_RG16F:
2575 case GL_RGBA16F:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002576 case GL_R32F:
2577 case GL_RG32F:
2578 case GL_RGBA32F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002579 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002580 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002581 break;
2582 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002583 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002584 break;
2585 case GL_RED:
2586 case GL_RG:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002587 case GL_SRGB8:
2588 case GL_RGB32UI:
2589 case GL_RGB16UI:
2590 case GL_RGB8UI:
2591 case GL_RGB32I:
2592 case GL_RGB16I:
2593 case GL_RGB8I:
2594 case GL_R8_SNORM:
2595 case GL_RG8_SNORM:
2596 case GL_RGB8_SNORM:
2597 case GL_RGBA8_SNORM:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002598 res = false;
2599 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07002600 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002601 case GL_RGB:
2602 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07002603 switch (fbo_format_info.tex_type) {
2604 case GL_FLOAT:
2605 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002606 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002607 case GL_UNSIGNED_INT_2_10_10_10_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07002608 res = false;
2609 break;
2610 default:
2611 res = true;
2612 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002613 break;
2614 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07002615 res = true;
2616 }
2617 break;
2618 case FBO_ATTACHMENT_NONE:
2619 res = true;
2620 break;
2621 default:
2622 res = true;
2623 }
2624 return res;
2625}
2626
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002627bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const {
2628 bool res = true;
2629
2630 for (int i = 0; i < state->getMaxColorAttachments(); i++) {
2631 res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i));
2632 }
2633
2634 res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT);
2635 res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT);
2636
2637 return res;
2638}
2639
Lingfeng Yang69066602016-04-12 09:29:11 -07002640GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
2641 GL2Encoder* ctx = (GL2Encoder*)self;
2642 GLClientState* state = ctx->m_state;
2643
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002644 bool fboCompleteByCodec =
2645 ctx->checkFramebufferCompleteness(target, state);
2646
2647 if (!fboCompleteByCodec) {
2648 state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
Lingfeng Yang69066602016-04-12 09:29:11 -07002649 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2650 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002651 // double check with underlying opengl to avoid craziness.
Lingfeng Yang69066602016-04-12 09:29:11 -07002652 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002653 state->setCheckFramebufferStatus(target, host_checkstatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002654 if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE;
Lingfeng Yang69066602016-04-12 09:29:11 -07002655 return host_checkstatus;
2656 }
2657}
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002658
2659void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2660 GL2Encoder* ctx = (GL2Encoder*)self;
2661 GLClientState* state = ctx->m_state;
2662 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2663
2664 ctx->m_glGenVertexArrays_enc(self, n, arrays);
2665 for (int i = 0; i < n; i++) {
2666 ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2667 }
2668 state->addVertexArrayObjects(n, arrays);
2669}
2670
2671void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2672 GL2Encoder* ctx = (GL2Encoder*)self;
2673 GLClientState* state = ctx->m_state;
2674 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2675
2676 ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2677 for (int i = 0; i < n; i++) {
2678 ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2679 }
2680 state->removeVertexArrayObjects(n, arrays);
2681}
2682
2683void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2684 ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2685 GL2Encoder* ctx = (GL2Encoder*)self;
2686 GLClientState* state = ctx->m_state;
2687 SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2688 ctx->m_glBindVertexArray_enc(self, array);
2689 state->setVertexArrayObject(array);
2690}
2691
Lingfeng Yangfb3d2bb2017-09-07 15:02:04 -07002692void* GL2Encoder::s_glMapBufferOES(void* self, GLenum target, GLenum access) {
2693 GL2Encoder* ctx = (GL2Encoder*)self;
2694
2695 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2696
2697 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2698
2699 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2700
2701 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2702 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2703
2704 return ctx->glMapBufferRange(ctx, target, 0, buf->m_size, access);
2705}
2706
2707GLboolean GL2Encoder::s_glUnmapBufferOES(void* self, GLenum target) {
2708 GL2Encoder* ctx = (GL2Encoder*)self;
2709
2710 return ctx->glUnmapBuffer(ctx, target);
2711}
2712
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002713void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2714 GL2Encoder* ctx = (GL2Encoder*)self;
2715 GLClientState* state = ctx->m_state;
2716
2717 // begin validation (lots)
2718
2719 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2720
2721 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2722
2723 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2724
2725 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2726 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2727
2728 GLsizeiptr bufferDataSize = buf->m_size;
2729
2730 RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2731 RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2732 RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2733 RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2734
2735 RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2736 RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2737 RET_AND_SET_ERROR_IF(
2738 (access & GL_MAP_READ_BIT) &&
2739 ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2740 (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2741 (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2742 (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2743
2744 // end validation; actually do stuff now
2745
2746 buf->m_mapped = true;
2747 buf->m_mappedAccess = access;
2748 buf->m_mappedOffset = offset;
2749 buf->m_mappedLength = length;
2750
2751 char* todo = (char*)buf->m_fixedBuffer.ptr() + offset;
2752 ctx->glMapBufferRangeAEMU(
2753 ctx, target,
2754 offset, length,
2755 access,
2756 todo);
2757
2758 return todo;
2759}
2760
2761GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
2762 GL2Encoder* ctx = (GL2Encoder*)self;
2763 GLClientState* state = ctx->m_state;
2764
2765 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
2766
2767 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2768
2769 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
2770
2771 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2772 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
2773 RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
2774
Lingfeng Yang423129e2017-01-18 09:23:12 -08002775 if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
2776 // invalide index range cache here
2777 if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) {
2778 buf->m_indexRangeCache.invalidateRange(0, buf->m_size);
2779 } else {
2780 buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength);
2781 }
2782 }
2783
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002784 GLboolean host_res = GL_TRUE;
2785
2786 ctx->glUnmapBufferAEMU(
2787 ctx, target,
2788 buf->m_mappedOffset,
2789 buf->m_mappedLength,
2790 buf->m_mappedAccess,
2791 (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
2792 &host_res);
2793
2794 buf->m_mapped = false;
2795 buf->m_mappedAccess = 0;
2796 buf->m_mappedOffset = 0;
2797 buf->m_mappedLength = 0;
2798
2799 return host_res;
2800}
2801
2802void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
2803 GL2Encoder* ctx = (GL2Encoder*)self;
2804 GLClientState* state = ctx->m_state;
2805
2806 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2807
2808 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2809 SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
2810
2811 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2812 SET_ERROR_IF(!buf, GL_INVALID_VALUE);
2813 SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
2814 SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
2815
2816 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
2817 SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
2818 SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
2819
2820 GLintptr totalOffset = buf->m_mappedOffset + offset;
Lingfeng Yang423129e2017-01-18 09:23:12 -08002821
2822 buf->m_indexRangeCache.invalidateRange(totalOffset, length);
2823
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002824 ctx->glFlushMappedBufferRangeAEMU(
2825 ctx, target,
2826 totalOffset,
2827 length,
2828 buf->m_mappedAccess,
2829 (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
2830}
2831
2832void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
2833 GL2Encoder* ctx = (GL2Encoder*)self;
2834 GLClientState* state = ctx->m_state;
2835
2836 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2837 // Filter compressed formats support.
2838 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
2839 // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
2840 GLint max_texture_size;
2841 GLint max_cube_map_texture_size;
2842 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2843 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2844 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2845 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2846 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2847 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2848 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2849 SET_ERROR_IF(border, GL_INVALID_VALUE);
2850 // If unpack buffer is nonzero, verify unmapped state.
2851 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2852 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2853 // If unpack buffer is nonzero, verify buffer data fits.
2854 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2855 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2856 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2857 GL_INVALID_OPERATION);
2858 // TODO: Fix:
2859 // If |imageSize| is inconsistent with compressed dimensions.
2860 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
2861
2862 GLenum stateTarget = target;
2863 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2864 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2865 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2866 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2867 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2868 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2869 stateTarget = GL_TEXTURE_CUBE_MAP;
2870 state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
2871 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2872
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002873 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2874 ctx->override2DTextureTarget(target);
2875 }
2876
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002877 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2878 ctx->glCompressedTexImage2DOffsetAEMU(
2879 ctx, target, level, internalformat,
2880 width, height, border,
2881 imageSize, (uintptr_t)data);
2882 } else {
2883 ctx->m_glCompressedTexImage2D_enc(
2884 ctx, target, level, internalformat,
2885 width, height, border,
2886 imageSize, data);
2887 }
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002888
2889 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2890 ctx->restore2DTextureTarget(target);
2891 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002892}
2893
2894void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
2895 GL2Encoder* ctx = (GL2Encoder*)self;
2896 GLClientState* state = ctx->m_state;
2897
2898 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2899 // If unpack buffer is nonzero, verify unmapped state.
2900 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2901 GLint max_texture_size;
2902 GLint max_cube_map_texture_size;
2903 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2904 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2905 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2906 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2907 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2908 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2909 // If unpack buffer is nonzero, verify buffer data fits.
2910 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2911 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2912 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2913 GL_INVALID_OPERATION);
2914 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2915
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002916 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2917 ctx->override2DTextureTarget(target);
2918 }
2919
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002920 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2921 ctx->glCompressedTexSubImage2DOffsetAEMU(
2922 ctx, target, level,
2923 xoffset, yoffset,
2924 width, height, format,
2925 imageSize, (uintptr_t)data);
2926 } else {
2927 ctx->m_glCompressedTexSubImage2D_enc(
2928 ctx, target, level,
2929 xoffset, yoffset,
2930 width, height, format,
2931 imageSize, data);
2932 }
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002933
2934 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2935 ctx->restore2DTextureTarget(target);
2936 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002937}
2938
2939void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
2940 GL2Encoder* ctx = (GL2Encoder*)self;
2941 GLClientState* state = ctx->m_state;
2942
2943 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2944
2945 // Only works with certain targets
2946 SET_ERROR_IF(
2947 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2948 target == GL_SHADER_STORAGE_BUFFER ||
2949 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2950 target == GL_UNIFORM_BUFFER),
2951 GL_INVALID_ENUM);
2952
2953 // Can't exceed range
2954 SET_ERROR_IF(index < 0 ||
2955 index >= state->getMaxIndexedBufferBindings(target),
2956 GL_INVALID_VALUE);
2957 SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
2958 SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
2959 target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
2960 (size % 4 || offset % 4),
2961 GL_INVALID_VALUE);
2962
2963 GLint ssbo_offset_align, ubo_offset_align;
2964 ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
2965 ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
2966 SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
2967 offset % ssbo_offset_align,
2968 GL_INVALID_VALUE);
2969 SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
2970 offset % ubo_offset_align,
2971 GL_INVALID_VALUE);
2972
2973 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002974 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002975 state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0);
2976 ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size);
2977}
2978
2979void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
2980 GL2Encoder* ctx = (GL2Encoder*)self;
2981 GLClientState* state = ctx->m_state;
2982
2983 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2984
2985 // Only works with certain targets
2986 SET_ERROR_IF(
2987 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2988 target == GL_SHADER_STORAGE_BUFFER ||
2989 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2990 target == GL_UNIFORM_BUFFER),
2991 GL_INVALID_ENUM);
2992 // Can't exceed range
2993 SET_ERROR_IF(index < 0 ||
2994 index >= state->getMaxIndexedBufferBindings(target),
2995 GL_INVALID_VALUE);
2996
2997 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002998 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002999 BufferData* buf = ctx->getBufferDataById(buffer);
3000 state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0);
3001 ctx->m_glBindBufferBase_enc(self, target, index, buffer);
3002}
3003
3004void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
3005 GL2Encoder* ctx = (GL2Encoder*)self;
3006 GLClientState* state = ctx->m_state;
3007
3008 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
3009 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
3010 SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
3011 readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
3012 readtarget == GL_DRAW_INDIRECT_BUFFER ||
3013 readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
3014 SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
3015 writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
3016 writetarget == GL_DRAW_INDIRECT_BUFFER ||
3017 writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
3018 SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
3019 SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
3020 SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
3021 SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
3022 SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
3023 SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
3024 SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
3025 SET_ERROR_IF(
3026 ctx->getBufferData(readtarget) &&
3027 (readoffset + size > ctx->getBufferData(readtarget)->m_size),
3028 GL_INVALID_VALUE);
3029 SET_ERROR_IF(
3030 ctx->getBufferData(writetarget) &&
3031 (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
3032 GL_INVALID_VALUE);
3033 SET_ERROR_IF(readtarget == writetarget &&
3034 !((writeoffset >= readoffset + size) ||
3035 (readoffset >= writeoffset + size)),
3036 GL_INVALID_VALUE);
3037
3038 ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
3039}
3040
3041void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
3042 GL2Encoder* ctx = (GL2Encoder*)self;
3043
3044 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3045 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003046 target != GL_ARRAY_BUFFER &&
3047 target != GL_ELEMENT_ARRAY_BUFFER &&
3048 target != GL_COPY_READ_BUFFER &&
3049 target != GL_COPY_WRITE_BUFFER &&
3050 target != GL_PIXEL_PACK_BUFFER &&
3051 target != GL_PIXEL_UNPACK_BUFFER &&
3052 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
3053 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003054 GL_INVALID_ENUM);
3055 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
3056 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003057 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
3058 pname != GL_BUFFER_MAPPED &&
3059 pname != GL_BUFFER_SIZE &&
3060 pname != GL_BUFFER_USAGE &&
3061 pname != GL_BUFFER_MAP_LENGTH &&
3062 pname != GL_BUFFER_MAP_OFFSET,
3063 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003064
3065 if (!params) return;
3066
3067 BufferData* buf = ctx->getBufferData(target);
3068
3069 switch (pname) {
3070 case GL_BUFFER_ACCESS_FLAGS:
3071 *params = buf ? buf->m_mappedAccess : 0;
3072 break;
3073 case GL_BUFFER_MAPPED:
3074 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3075 break;
3076 case GL_BUFFER_SIZE:
3077 *params = buf ? buf->m_size : 0;
3078 break;
3079 case GL_BUFFER_USAGE:
3080 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3081 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003082 case GL_BUFFER_MAP_LENGTH:
3083 *params = buf ? buf->m_mappedLength : 0;
3084 break;
3085 case GL_BUFFER_MAP_OFFSET:
3086 *params = buf ? buf->m_mappedOffset : 0;
3087 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003088 default:
3089 break;
3090 }
3091}
3092
3093void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
3094 GL2Encoder* ctx = (GL2Encoder*)self;
3095
3096 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3097 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003098 target != GL_ARRAY_BUFFER &&
3099 target != GL_ELEMENT_ARRAY_BUFFER &&
3100 target != GL_COPY_READ_BUFFER &&
3101 target != GL_COPY_WRITE_BUFFER &&
3102 target != GL_PIXEL_PACK_BUFFER &&
3103 target != GL_PIXEL_UNPACK_BUFFER &&
3104 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
3105 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003106 GL_INVALID_ENUM);
3107 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
3108 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003109 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
3110 pname != GL_BUFFER_MAPPED &&
3111 pname != GL_BUFFER_SIZE &&
3112 pname != GL_BUFFER_USAGE &&
3113 pname != GL_BUFFER_MAP_LENGTH &&
3114 pname != GL_BUFFER_MAP_OFFSET,
3115 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003116
3117 if (!params) return;
3118
3119 BufferData* buf = ctx->getBufferData(target);
3120
3121 switch (pname) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003122 case GL_BUFFER_ACCESS_FLAGS:
3123 *params = buf ? buf->m_mappedAccess : 0;
3124 break;
3125 case GL_BUFFER_MAPPED:
3126 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3127 break;
3128 case GL_BUFFER_SIZE:
3129 *params = buf ? buf->m_size : 0;
3130 break;
3131 case GL_BUFFER_USAGE:
3132 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3133 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003134 case GL_BUFFER_MAP_LENGTH:
3135 *params = buf ? buf->m_mappedLength : 0;
3136 break;
3137 case GL_BUFFER_MAP_OFFSET:
3138 *params = buf ? buf->m_mappedOffset : 0;
3139 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003140 default:
3141 break;
3142 }
3143}
3144
3145void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
3146 GL2Encoder* ctx = (GL2Encoder*)self;
3147 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3148 SET_ERROR_IF(
3149 target == GL_ATOMIC_COUNTER_BUFFER ||
3150 target == GL_DISPATCH_INDIRECT_BUFFER ||
3151 target == GL_DRAW_INDIRECT_BUFFER ||
3152 target == GL_SHADER_STORAGE_BUFFER,
3153 GL_INVALID_ENUM);
3154 SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
3155 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
3156 if (!params) return;
3157
3158 BufferData* buf = ctx->getBufferData(target);
3159
3160 if (!buf || !buf->m_mapped) { *params = NULL; return; }
3161
3162 *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
3163}
3164
3165static const char* const kNameDelimiter = ";";
3166
3167static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
3168
3169#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
3170
3171 std::string packed;
3172 // validate the array of char[]'s
3173 const char* currName;
3174 for (GLsizei i = 0; i < count; i++) {
3175 currName = names[i];
3176 VALIDATE(!currName, GL_INVALID_OPERATION);
3177 // check if has reasonable size
3178 size_t len = strlen(currName);
3179 VALIDATE(!len, GL_INVALID_OPERATION);
3180 // check for our delimiter, which if present
3181 // in the name, means an invalid name anyway.
3182 VALIDATE(strstr(currName, kNameDelimiter),
3183 GL_INVALID_OPERATION);
3184 packed += currName;
3185 packed += ";";
3186 }
3187
3188 *err_out = GL_NO_ERROR;
3189 return packed;
3190}
3191
3192void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
3193 GL2Encoder* ctx = (GL2Encoder*)self;
3194
3195 if (!uniformCount) return;
3196
3197 GLint err = GL_NO_ERROR;
3198 std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
3199 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3200
3201 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
3202 std::vector<int> arrIndices;
3203 for (size_t i = 0; i < uniformCount; i++) {
3204 int err;
3205 arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
3206 if (err) {
3207 ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
3208 return;
3209 }
3210 }
3211
3212 ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
3213
3214 for (int i = 0; i < uniformCount; i++) {
3215 if (uniformIndices[i] >= 0 && needLocationWAR) {
3216 uniformIndices[i] =
3217 ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
3218 }
3219 }
3220}
3221
3222void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
3223 GL2Encoder *ctx = (GL2Encoder*)self;
3224 GLClientState* state = ctx->m_state;
3225 GLSharedGroupPtr shared = ctx->m_shared;
3226
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003227 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003228 ctx->m_glUniform1ui_enc(self, hostLoc, v0);
3229
3230 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003231 if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003232 GLenum origActiveTexture = state->getActiveTextureUnit();
3233 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
3234 ctx->m_glActiveTexture_enc(self, origActiveTexture);
3235 }
3236 state->setActiveTextureUnit(origActiveTexture);
3237 }
3238}
3239
3240void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) {
3241 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003242 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003243 ctx->m_glUniform2ui_enc(self, hostLoc, v0, v1);
3244}
3245
3246void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) {
3247 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003248 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003249 ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2);
3250}
3251
3252void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) {
3253 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003254 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003255 ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3);
3256}
3257
3258void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3259 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003260 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003261 ctx->m_glUniform1uiv_enc(self, hostLoc, count, value);
3262}
3263
3264void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3265 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003266 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003267 ctx->m_glUniform2uiv_enc(self, hostLoc, count, value);
3268}
3269
3270void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3271 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003272 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003273 ctx->m_glUniform3uiv_enc(self, hostLoc, count, value);
3274}
3275
3276void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3277 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003278 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003279 ctx->m_glUniform4uiv_enc(self, hostLoc, count, value);
3280}
3281
3282void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3283 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003284 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003285 ctx->m_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value);
3286}
3287
3288void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3289 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003290 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003291 ctx->m_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value);
3292}
3293
3294void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3295 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003296 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003297 ctx->m_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value);
3298}
3299
3300void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3301 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003302 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003303 ctx->m_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value);
3304}
3305
3306void GL2Encoder::s_glUniformMatrix3x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3307 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003308 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003309 ctx->m_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value);
3310}
3311
3312void GL2Encoder::s_glUniformMatrix4x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3313 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003314 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003315 ctx->m_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value);
3316}
3317
3318void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3319 GL2Encoder *ctx = (GL2Encoder*)self;
3320 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3321 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3322 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3323 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3324 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3325 ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3326}
3327
3328void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3329 GL2Encoder* ctx = (GL2Encoder*)self;
3330 GLClientState* state = ctx->m_state;
3331
3332 // refresh client state's # active uniforms in this block
3333 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3334 // TODO if worth it: cache uniform count and other params,
3335 // invalidate on program relinking.
3336 GLint numActiveUniforms;
3337 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3338 program, uniformBlockIndex,
3339 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3340 &numActiveUniforms);
3341 ctx->m_state->setNumActiveUniformsInUniformBlock(
3342 program, uniformBlockIndex, numActiveUniforms);
3343 }
3344
3345 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3346 program, uniformBlockIndex,
3347 pname, params);
3348}
3349
3350void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3351 GL2Encoder *ctx = (GL2Encoder *)self;
3352 assert(ctx->m_state);
3353 GLint maxIndex;
3354 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3355 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3356
3357 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3358 ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3359 }
3360}
3361
3362void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3363 GL2Encoder *ctx = (GL2Encoder *)self;
3364 assert(ctx->m_state);
3365 GLint maxIndex;
3366 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3367 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3368
3369 if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3370 ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3371 }
3372}
3373
3374void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3375 GL2Encoder *ctx = (GL2Encoder *)self;
3376 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003377 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003378 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
3379 SET_ERROR_IF(
3380 !(type == GL_BYTE ||
3381 type == GL_UNSIGNED_BYTE ||
3382 type == GL_SHORT ||
3383 type == GL_UNSIGNED_SHORT ||
3384 type == GL_INT ||
3385 type == GL_UNSIGNED_INT),
3386 GL_INVALID_ENUM);
3387 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
3388
3389 ctx->m_state->setVertexAttribBinding(index, index);
3390 ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true);
3391 GLsizei effectiveStride = stride;
3392 if (stride == 0) {
3393 effectiveStride = glSizeof(type) * size;
3394 }
3395 ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride);
3396
3397 if (ctx->m_state->currentArrayVbo() != 0) {
3398 ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer);
3399 } else {
3400 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION);
3401 // wait for client-array handler
3402 }
3403}
3404
3405void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) {
3406 GL2Encoder *ctx = (GL2Encoder *)self;
3407 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003408 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003409 ctx->m_state->setVertexAttribBinding(index, index);
3410 ctx->m_state->setVertexBindingDivisor(index, divisor);
3411 ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor);
3412}
3413
3414void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3415 GLenum target, GLsizei samples, GLenum internalformat,
3416 GLsizei width, GLsizei height) {
3417 GL2Encoder *ctx = (GL2Encoder *)self;
3418 GLClientState* state = ctx->m_state;
3419
3420 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3421 SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3422
3423 GLint max_samples;
3424 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3425 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3426
3427 state->setBoundRenderbufferFormat(internalformat);
3428 state->setBoundRenderbufferSamples(samples);
3429 ctx->m_glRenderbufferStorageMultisample_enc(
3430 self, target, samples, internalformat, width, height);
3431}
3432
3433void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3434 GL2Encoder* ctx = (GL2Encoder*)self;
3435 SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3436 SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3437 for (int i = 0; i < n; i++) {
3438 SET_ERROR_IF(
3439 bufs[i] != GL_NONE &&
3440 bufs[i] != GL_BACK &&
3441 glUtilsColorAttachmentIndex(bufs[i]) == -1,
3442 GL_INVALID_ENUM);
3443 SET_ERROR_IF(
3444 !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3445 glUtilsColorAttachmentIndex(bufs[i]) != -1,
3446 GL_INVALID_OPERATION);
3447 SET_ERROR_IF(
3448 ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3449 ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3450 glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3451 (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3452 bufs[i] != GL_NONE)),
3453 GL_INVALID_OPERATION);
3454 }
3455
3456 ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3457}
3458
3459void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3460 GL2Encoder* ctx = (GL2Encoder*)self;
3461
3462 SET_ERROR_IF(
3463 glUtilsColorAttachmentIndex(src) != -1 &&
3464 (glUtilsColorAttachmentIndex(src) >=
3465 ctx->m_state->getMaxColorAttachments()),
3466 GL_INVALID_OPERATION);
3467 SET_ERROR_IF(
3468 src != GL_NONE &&
3469 src != GL_BACK &&
3470 src > GL_COLOR_ATTACHMENT0 &&
3471 src < GL_DEPTH_ATTACHMENT &&
3472 (src - GL_COLOR_ATTACHMENT0) >
3473 ctx->m_state->getMaxColorAttachments(),
3474 GL_INVALID_OPERATION);
3475 SET_ERROR_IF(
3476 src != GL_NONE &&
3477 src != GL_BACK &&
3478 glUtilsColorAttachmentIndex(src) == -1,
3479 GL_INVALID_ENUM);
3480 SET_ERROR_IF(
3481 !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3482 src != GL_NONE &&
3483 src != GL_BACK,
3484 GL_INVALID_OPERATION);
3485 SET_ERROR_IF(
3486 ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3487 src != GL_NONE &&
3488 glUtilsColorAttachmentIndex(src) == -1,
3489 GL_INVALID_OPERATION);
3490
3491 ctx->m_glReadBuffer_enc(ctx, src);
3492}
3493
3494void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3495 GL2Encoder* ctx = (GL2Encoder*)self;
3496 GLClientState* state = ctx->m_state;
3497
3498 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3499 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3500 GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3501 SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3502 lastBoundTarget != GL_TEXTURE_3D,
3503 GL_INVALID_OPERATION);
3504 state->attachTextureObject(target, attachment, texture);
3505
3506 GLint max3DTextureSize;
3507 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3508 SET_ERROR_IF(
3509 layer >= max3DTextureSize,
3510 GL_INVALID_VALUE);
3511
3512 ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3513}
3514
3515void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3516 GL2Encoder* ctx = (GL2Encoder*)self;
3517 GLClientState* state = ctx->m_state;
3518
3519 SET_ERROR_IF(
3520 target != GL_TEXTURE_2D &&
3521 target != GL_TEXTURE_CUBE_MAP,
3522 GL_INVALID_ENUM);
3523 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3524 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3525 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3526 SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3527 GL_INVALID_OPERATION);
3528 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3529
3530 state->setBoundTextureInternalFormat(target, internalformat);
3531 state->setBoundTextureDims(target, -1, width, height, 1);
3532 state->setBoundTextureImmutableFormat(target);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003533
3534 if (target == GL_TEXTURE_2D) {
3535 ctx->override2DTextureTarget(target);
3536 }
3537
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003538 ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003539
3540 if (target == GL_TEXTURE_2D) {
3541 ctx->restore2DTextureTarget(target);
3542 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003543}
3544
3545void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3546 GL2Encoder* ctx = (GL2Encoder*)self;
3547
3548 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3549
3550 GLint maxCount = 0;
3551 ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3552
3553 SET_ERROR_IF(
3554 bufferMode == GL_SEPARATE_ATTRIBS &&
3555 maxCount < count,
3556 GL_INVALID_VALUE);
3557 SET_ERROR_IF(
3558 bufferMode != GL_INTERLEAVED_ATTRIBS &&
3559 bufferMode != GL_SEPARATE_ATTRIBS,
3560 GL_INVALID_ENUM);
3561
3562 if (!count) return;
3563
3564 GLint err = GL_NO_ERROR;
3565 std::string packed = packVarNames(count, varyings, &err);
3566 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3567
3568 ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3569}
3570
3571void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3572 GL2Encoder* ctx = (GL2Encoder*)self;
3573 GLClientState* state = ctx->m_state;
3574 ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3575 state->setTransformFeedbackActiveUnpaused(true);
3576}
3577
3578void GL2Encoder::s_glEndTransformFeedback(void* self) {
3579 GL2Encoder* ctx = (GL2Encoder*)self;
3580 GLClientState* state = ctx->m_state;
3581 ctx->m_glEndTransformFeedback_enc(ctx);
3582 state->setTransformFeedbackActiveUnpaused(false);
3583}
3584
3585void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3586 GL2Encoder* ctx = (GL2Encoder*)self;
3587 GLClientState* state = ctx->m_state;
3588 ctx->m_glPauseTransformFeedback_enc(ctx);
3589 state->setTransformFeedbackActiveUnpaused(false);
3590}
3591
3592void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3593 GL2Encoder* ctx = (GL2Encoder*)self;
3594 GLClientState* state = ctx->m_state;
3595 ctx->m_glResumeTransformFeedback_enc(ctx);
3596 state->setTransformFeedbackActiveUnpaused(true);
3597}
3598
3599void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3600 GLsizei width, GLsizei height, GLsizei depth,
3601 GLint border, GLenum format, GLenum type, const GLvoid* data) {
3602 GL2Encoder* ctx = (GL2Encoder*)self;
3603 GLClientState* state = ctx->m_state;
3604
3605 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3606 target != GL_TEXTURE_2D_ARRAY,
3607 GL_INVALID_ENUM);
3608 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3609 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3610
3611 // If unpack buffer is nonzero, verify unmapped state.
3612 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3613
3614 GLint max_texture_size;
3615 GLint max_3d_texture_size;
3616 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3617 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3618 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3619 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3620 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3621
3622 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3623 SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3624 SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3625 SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3626 SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3627 SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3628 SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3629 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3630 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3631 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3632 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3633 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3634 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3635 GL_INVALID_OPERATION);
3636 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3637 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3638 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3639 glSizeof(type)),
3640 GL_INVALID_OPERATION);
3641 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3642
3643 state->setBoundTextureInternalFormat(target, internalFormat);
3644 state->setBoundTextureFormat(target, format);
3645 state->setBoundTextureType(target, type);
3646 state->setBoundTextureDims(target, level, width, height, depth);
3647
3648 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3649 ctx->glTexImage3DOffsetAEMU(
3650 ctx, target, level, internalFormat,
3651 width, height, depth,
3652 border, format, type, (uintptr_t)data);
3653 } else {
3654 ctx->m_glTexImage3D_enc(ctx,
3655 target, level, internalFormat,
3656 width, height, depth,
3657 border, format, type, data);
3658 }
3659}
3660
3661void 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) {
3662 GL2Encoder* ctx = (GL2Encoder*)self;
3663 GLClientState* state = ctx->m_state;
3664
3665 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3666 target != GL_TEXTURE_2D_ARRAY,
3667 GL_INVALID_ENUM);
3668 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3669 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3670 // If unpack buffer is nonzero, verify unmapped state.
3671 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3672 GLint max_texture_size;
3673 GLint max_3d_texture_size;
3674 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3675 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3676 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3677 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3678 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3679 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3680 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3681 GLuint tex = state->getBoundTexture(target);
3682 GLsizei neededWidth = xoffset + width;
3683 GLsizei neededHeight = yoffset + height;
3684 GLsizei neededDepth = zoffset + depth;
3685
3686 SET_ERROR_IF(tex &&
3687 (neededWidth > state->queryTexWidth(level, tex) ||
3688 neededHeight > state->queryTexHeight(level, tex) ||
3689 neededDepth > state->queryTexDepth(level, tex)),
3690 GL_INVALID_VALUE);
3691 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3692 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3693 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3694 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3695 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3696 GL_INVALID_OPERATION);
3697 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3698 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3699 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3700 glSizeof(type)),
3701 GL_INVALID_OPERATION);
3702 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
3703 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3704
3705 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3706 ctx->glTexSubImage3DOffsetAEMU(ctx,
3707 target, level,
3708 xoffset, yoffset, zoffset,
3709 width, height, depth,
3710 format, type, (uintptr_t)data);
3711 } else {
3712 ctx->m_glTexSubImage3D_enc(ctx,
3713 target, level,
3714 xoffset, yoffset, zoffset,
3715 width, height, depth,
3716 format, type, data);
3717 }
3718}
3719
3720void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
3721 GL2Encoder* ctx = (GL2Encoder*)self;
3722 GLClientState* state = ctx->m_state;
3723
3724 // Filter compressed formats support.
3725 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3726 // If unpack buffer is nonzero, verify unmapped state.
3727 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3728 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3729 SET_ERROR_IF(border, GL_INVALID_VALUE);
3730 // If unpack buffer is nonzero, verify buffer data fits.
3731 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3732 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3733 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3734 GL_INVALID_OPERATION);
3735 // TODO: Fix:
3736 // If |imageSize| is too small for compressed dimensions.
3737 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
3738 state->setBoundTextureInternalFormat(target, (GLint)internalformat);
3739 state->setBoundTextureDims(target, level, width, height, depth);
3740
3741 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3742 ctx->glCompressedTexImage3DOffsetAEMU(
3743 ctx, target, level, internalformat,
3744 width, height, depth, border,
3745 imageSize, (uintptr_t)data);
3746 } else {
3747 ctx->m_glCompressedTexImage3D_enc(
3748 ctx, target, level, internalformat,
3749 width, height, depth, border,
3750 imageSize, data);
3751 }
3752}
3753
3754void 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) {
3755 GL2Encoder* ctx = (GL2Encoder*)self;
3756 GLClientState* state = ctx->m_state;
3757
3758 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3759 // If unpack buffer is nonzero, verify unmapped state.
3760 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3761 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3762 // If unpack buffer is nonzero, verify buffer data fits.
3763 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3764 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3765 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3766 GL_INVALID_OPERATION);
3767 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3768
3769 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3770 ctx->glCompressedTexSubImage3DOffsetAEMU(
3771 ctx, target, level,
3772 xoffset, yoffset, zoffset,
3773 width, height, depth,
3774 format, imageSize, (uintptr_t)data);
3775 } else {
3776 ctx->m_glCompressedTexSubImage3D_enc(
3777 ctx, target, level,
3778 xoffset, yoffset, zoffset,
3779 width, height, depth,
3780 format, imageSize, data);
3781
3782 }
3783}
3784
3785void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
3786 GL2Encoder* ctx = (GL2Encoder*)self;
3787 GLClientState* state = ctx->m_state;
3788 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3789 target != GL_TEXTURE_2D_ARRAY,
3790 GL_INVALID_ENUM);
3791 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3792 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3793 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3794 SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
3795 GL_INVALID_OPERATION);
3796 SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
3797 GL_INVALID_OPERATION);
3798 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3799
3800 state->setBoundTextureInternalFormat(target, internalformat);
3801 state->setBoundTextureDims(target, -1, width, height, depth);
3802 state->setBoundTextureImmutableFormat(target);
3803 ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
3804 state->setBoundTextureImmutableFormat(target);
3805}
3806
3807void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
3808 GL2Encoder *ctx = (GL2Encoder *)self;
3809 assert(ctx->m_state != NULL);
3810 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3811 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3812
3813 bool has_client_vertex_arrays = false;
3814 bool has_indirect_arrays = false;
3815 ctx->getVBOUsage(&has_client_vertex_arrays,
3816 &has_indirect_arrays);
3817
3818 if (has_client_vertex_arrays ||
3819 (!has_client_vertex_arrays &&
3820 !has_indirect_arrays)) {
3821 ctx->sendVertexAttributes(first, count, true, primcount);
3822 ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
3823 } else {
3824 ctx->sendVertexAttributes(0, count, false, primcount);
3825 ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
3826 }
3827 ctx->m_stream->flush();
3828}
3829
3830void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
3831{
3832
3833 GL2Encoder *ctx = (GL2Encoder *)self;
3834 assert(ctx->m_state != NULL);
3835 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3836 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3837 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3838 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3839
3840 bool has_client_vertex_arrays = false;
3841 bool has_indirect_arrays = false;
3842 int nLocations = ctx->m_state->nLocations();
3843 GLintptr offset = 0;
3844
3845 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3846
3847 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3848 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3849 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3850 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3851 }
3852
3853 BufferData* buf = NULL;
3854 int minIndex = 0, maxIndex = 0;
3855
3856 // For validation/immediate index array purposes,
3857 // we need the min/max vertex index of the index array.
3858 // If the VBO != 0, this may not be the first time we have
3859 // used this particular index buffer. getBufferIndexRange
3860 // can more quickly get min/max vertex index by
3861 // caching previous results.
3862 if (ctx->m_state->currentIndexVbo() != 0) {
3863 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3864 offset = (GLintptr)indices;
3865 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3866 ctx->getBufferIndexRange(buf,
3867 indices,
3868 type,
3869 (size_t)count,
3870 (size_t)offset,
3871 &minIndex, &maxIndex);
3872 } else {
3873 // In this case, the |indices| field holds a real
3874 // array, so calculate the indices now. They will
3875 // also be needed to know how much data to
3876 // transfer to host.
3877 ctx->calcIndexRange(indices,
3878 type,
3879 count,
3880 &minIndex,
3881 &maxIndex);
3882 }
3883
Lingfeng Yang26e629a2018-10-13 20:00:12 -07003884 if (count == 0) return;
3885
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003886 bool adjustIndices = true;
3887 if (ctx->m_state->currentIndexVbo() != 0) {
3888 if (!has_client_vertex_arrays) {
3889 ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
3890 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3891 ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
3892 ctx->flushDrawCall();
3893 adjustIndices = false;
3894 } else {
3895 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3896 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3897 }
3898 }
3899 if (adjustIndices) {
3900 void *adjustedIndices =
3901 ctx->recenterIndices(indices,
3902 type,
3903 count,
3904 minIndex);
3905
3906 if (has_indirect_arrays || 1) {
3907 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
3908 ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
3909 ctx->m_stream->flush();
3910 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3911 if(!has_indirect_arrays) {
3912 //ALOGD("unoptimized drawelements !!!\n");
3913 }
3914 } else {
3915 // we are all direct arrays and immidate mode index array -
3916 // rebuild the arrays and the index array;
3917 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3918 }
3919 }
3920}
3921
3922void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
3923{
3924
3925 GL2Encoder *ctx = (GL2Encoder *)self;
3926 assert(ctx->m_state != NULL);
3927 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3928 SET_ERROR_IF(end < start, GL_INVALID_VALUE);
3929 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3930 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3931 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3932
3933 bool has_client_vertex_arrays = false;
3934 bool has_indirect_arrays = false;
3935 int nLocations = ctx->m_state->nLocations();
3936 GLintptr offset = 0;
3937
3938 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3939
3940 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3941 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3942 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3943 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3944 }
3945
3946 BufferData* buf = NULL;
3947 int minIndex = 0, maxIndex = 0;
3948
3949 // For validation/immediate index array purposes,
3950 // we need the min/max vertex index of the index array.
3951 // If the VBO != 0, this may not be the first time we have
3952 // used this particular index buffer. getBufferIndexRange
3953 // can more quickly get min/max vertex index by
3954 // caching previous results.
3955 if (ctx->m_state->currentIndexVbo() != 0) {
3956 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3957 offset = (GLintptr)indices;
3958 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3959 ctx->getBufferIndexRange(buf,
3960 indices,
3961 type,
3962 (size_t)count,
3963 (size_t)offset,
3964 &minIndex, &maxIndex);
3965 } else {
3966 // In this case, the |indices| field holds a real
3967 // array, so calculate the indices now. They will
3968 // also be needed to know how much data to
3969 // transfer to host.
3970 ctx->calcIndexRange(indices,
3971 type,
3972 count,
3973 &minIndex,
3974 &maxIndex);
3975 }
3976
Lingfeng Yang26e629a2018-10-13 20:00:12 -07003977 if (count == 0) return;
3978
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003979 bool adjustIndices = true;
3980 if (ctx->m_state->currentIndexVbo() != 0) {
3981 if (!has_client_vertex_arrays) {
3982 ctx->sendVertexAttributes(0, maxIndex + 1, false);
3983 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3984 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
3985 ctx->flushDrawCall();
3986 adjustIndices = false;
3987 } else {
3988 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3989 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3990 }
3991 }
3992 if (adjustIndices) {
3993 void *adjustedIndices =
3994 ctx->recenterIndices(indices,
3995 type,
3996 count,
3997 minIndex);
3998
3999 if (has_indirect_arrays || 1) {
4000 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
4001 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
4002 ctx->m_stream->flush();
4003 // XXX - OPTIMIZATION (see the other else branch) should be implemented
4004 if(!has_indirect_arrays) {
4005 //ALOGD("unoptimized drawelements !!!\n");
4006 }
4007 } else {
4008 // we are all direct arrays and immidate mode index array -
4009 // rebuild the arrays and the index array;
4010 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
4011 }
4012 }
4013}
4014
4015// struct GLStringKey {
4016// GLenum name;
4017// GLuint index;
4018// };
4019//
4020// struct GLStringKeyCompare {
4021// bool operator() (const GLStringKey& a,
4022// const GLStringKey& b) const {
4023// if (a.name != b.name) return a.name < b.name;
4024// if (a.index != b.index) return a.index < b.index;
4025// return false;
4026// }
4027// };
4028//
4029// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
4030//
4031// static GLStringStore sGLStringStore;
4032// bool sGLStringStoreInitialized = false;
4033
4034const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
4035 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004036 const GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004037
4038 RET_AND_SET_ERROR_IF(
4039 name != GL_VENDOR &&
4040 name != GL_RENDERER &&
4041 name != GL_VERSION &&
4042 name != GL_EXTENSIONS,
4043 GL_INVALID_ENUM,
4044 retval);
4045
4046 RET_AND_SET_ERROR_IF(
Lingfeng Yang44209df2018-09-21 10:04:17 -07004047 (name == GL_VENDOR ||
4048 name == GL_RENDERER ||
4049 name == GL_VERSION) &&
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004050 index != 0,
4051 GL_INVALID_VALUE,
4052 retval);
4053
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004054 RET_AND_SET_ERROR_IF(
4055 name == GL_EXTENSIONS &&
4056 index >= ctx->m_currExtensionsArray.size(),
4057 GL_INVALID_VALUE,
4058 retval);
4059
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004060 switch (name) {
4061 case GL_VENDOR:
4062 retval = gVendorString;
4063 break;
4064 case GL_RENDERER:
4065 retval = gRendererString;
4066 break;
4067 case GL_VERSION:
4068 retval = gVersionString;
4069 break;
4070 case GL_EXTENSIONS:
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004071 retval = (const GLubyte*)(ctx->m_currExtensionsArray[index].c_str());
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004072 break;
4073 }
4074
4075 return retval;
4076}
4077
4078void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
4079 GL2Encoder *ctx = (GL2Encoder *)self;
4080
4081 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
4082
4083 GLint linkStatus = 0;
4084 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
4085 GLint properLength = 0;
4086 ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
4087
4088 SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
4089 SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
4090
4091 ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
4092}
4093
4094void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
4095 GL2Encoder *ctx = (GL2Encoder *)self;
4096
4097 SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
4098 SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
4099 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
4100 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
4101 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
4102 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
4103 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
4104 ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
4105 GL_INVALID_OPERATION);
4106 /*
4107GL_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.
4108
4109GL_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.
4110
4111GL_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.
4112
4113GL_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.
4114*/
4115
4116 FboFormatInfo fbo_format_info;
4117 ctx->m_state->getBoundFramebufferFormat(
4118 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
4119 SET_ERROR_IF(
4120 fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4121 !GLESv2Validation::readPixelsFboFormatMatch(
4122 format, type, fbo_format_info.tex_type),
4123 GL_INVALID_OPERATION);
4124
4125 if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
4126 ctx->glReadPixelsOffsetAEMU(
4127 ctx, x, y, width, height,
4128 format, type, (uintptr_t)pixels);
4129 } else {
4130 ctx->m_glReadPixels_enc(
4131 ctx, x, y, width, height,
4132 format, type, pixels);
4133 }
4134}
4135
4136// Track enabled state for some things like:
4137// - Primitive restart
4138void GL2Encoder::s_glEnable(void* self, GLenum what) {
4139 GL2Encoder *ctx = (GL2Encoder *)self;
4140
4141 switch (what) {
4142 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4143 ctx->m_primitiveRestartEnabled = true;
4144 break;
4145 }
4146
4147 ctx->m_glEnable_enc(ctx, what);
4148}
4149
4150void GL2Encoder::s_glDisable(void* self, GLenum what) {
4151 GL2Encoder *ctx = (GL2Encoder *)self;
4152
4153 switch (what) {
4154 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4155 ctx->m_primitiveRestartEnabled = false;
4156 break;
4157 }
4158
4159 ctx->m_glDisable_enc(ctx, what);
4160}
4161
4162void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
4163 GL2Encoder *ctx = (GL2Encoder *)self;
4164
4165 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4166
4167 ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
4168}
4169
4170void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
4171 GL2Encoder *ctx = (GL2Encoder *)self;
4172
4173 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4174
4175 ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
4176}
4177
4178void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
4179 GL2Encoder *ctx = (GL2Encoder *)self;
4180
4181 SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4182
4183 ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
4184}
4185
4186void 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) {
4187 GL2Encoder *ctx = (GL2Encoder *)self;
4188 GLClientState* state = ctx->m_state;
4189
4190 bool validateColor = mask | GL_COLOR_BUFFER_BIT;
4191 bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
4192 bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
4193
4194 FboFormatInfo read_fbo_format_info;
4195 FboFormatInfo draw_fbo_format_info;
4196 if (validateColor) {
4197 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4198 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4199
4200 if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4201 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
4202 SET_ERROR_IF(
4203 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4204 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4205 !GLESv2Validation::blitFramebufferFormat(
4206 read_fbo_format_info.tex_type,
4207 draw_fbo_format_info.tex_type),
4208 GL_INVALID_OPERATION);
4209 }
4210 }
4211
4212 if (validateDepth) {
4213 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
4214 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
4215
4216 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4217 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4218 SET_ERROR_IF(
4219 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4220 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4221 !GLESv2Validation::blitFramebufferFormat(
4222 read_fbo_format_info.rb_format,
4223 draw_fbo_format_info.rb_format),
4224 GL_INVALID_OPERATION);
4225 }
4226 }
4227
4228 if (validateStencil) {
4229 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
4230 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
4231
4232 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4233 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4234 SET_ERROR_IF(
4235 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4236 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4237 !GLESv2Validation::blitFramebufferFormat(
4238 read_fbo_format_info.rb_format,
4239 draw_fbo_format_info.rb_format),
4240 GL_INVALID_OPERATION);
4241 }
4242 }
4243
4244 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4245 SET_ERROR_IF(
4246 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4247 draw_fbo_format_info.rb_multisamples > 0,
4248 GL_INVALID_OPERATION);
4249 SET_ERROR_IF(
4250 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4251 draw_fbo_format_info.tex_multisamples > 0,
4252 GL_INVALID_OPERATION);
4253
4254 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4255 SET_ERROR_IF(
4256 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4257 read_fbo_format_info.rb_multisamples > 0 &&
4258 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4259 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4260 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4261 (read_fbo_format_info.rb_format !=
4262 draw_fbo_format_info.rb_format),
4263 GL_INVALID_OPERATION);
4264 SET_ERROR_IF(
4265 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4266 read_fbo_format_info.rb_multisamples > 0 &&
4267 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4268 (srcX0 != dstX0 || srcY0 != dstY0 ||
4269 srcX1 != dstX1 || srcY1 != dstY1),
4270 GL_INVALID_OPERATION);
4271
4272 ctx->m_glBlitFramebuffer_enc(ctx,
4273 srcX0, srcY0, srcX1, srcY1,
4274 dstX0, dstY0, dstX1, dstY1,
4275 mask, filter);
4276}
4277
4278void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
4279 GL2Encoder *ctx = (GL2Encoder *)self;
4280
4281 SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
4282 pname != GL_SAMPLES,
4283 GL_INVALID_ENUM);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004284 SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004285 SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004286 !GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4287 !GLESv2Validation::depthRenderableFormat(ctx, internalformat) &&
4288 !GLESv2Validation::stencilRenderableFormat(ctx, internalformat),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004289 GL_INVALID_ENUM);
4290 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4291
4292 if (bufSize < 1) return;
4293
4294 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
4295 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
4296 switch (pname) {
4297 case GL_NUM_SAMPLE_COUNTS:
4298 *params = 3;
4299 break;
4300 case GL_SAMPLES:
4301 params[0] = 4;
4302 if (bufSize > 1) params[1] = 2;
4303 if (bufSize > 2) params[2] = 1;
4304 break;
4305 default:
4306 break;
4307 }
4308}
4309
4310void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
4311 GL2Encoder *ctx = (GL2Encoder *)self;
4312 GLClientState* state = ctx->m_state;
4313
4314 SET_ERROR_IF(target != GL_TEXTURE_2D &&
4315 target != GL_TEXTURE_3D &&
Yahan Zhou53c64582018-04-16 15:46:17 -07004316 target != GL_TEXTURE_CUBE_MAP &&
4317 target != GL_TEXTURE_2D_ARRAY,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004318 GL_INVALID_ENUM);
4319
4320 GLuint tex = state->getBoundTexture(target);
4321 GLenum internalformat = state->queryTexInternalFormat(tex);
4322 GLenum format = state->queryTexFormat(tex);
4323
4324 SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
4325 GL_INVALID_OPERATION);
4326 SET_ERROR_IF(tex &&
4327 !GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004328 !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4329 GLESv2Validation::filterableTexFormat(ctx, internalformat)),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004330 GL_INVALID_OPERATION);
4331
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08004332 if (target == GL_TEXTURE_2D) {
4333 ctx->override2DTextureTarget(target);
4334 }
4335
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004336 ctx->m_glGenerateMipmap_enc(ctx, target);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08004337
4338 if (target == GL_TEXTURE_2D) {
4339 ctx->restore2DTextureTarget(target);
4340 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004341}
4342
4343void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4344 GL2Encoder *ctx = (GL2Encoder *)self;
4345 GLint maxCombinedUnits;
4346 ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4347 SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4348
4349 ctx->m_glBindSampler_enc(ctx, unit, sampler);
4350}
4351
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004352GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4353 GL2Encoder *ctx = (GL2Encoder *)self;
4354 uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4355 return (GLsync)(uintptr_t)syncHandle;
4356}
4357
4358GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4359 GL2Encoder *ctx = (GL2Encoder *)self;
4360 return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4361}
4362
4363void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4364 GL2Encoder *ctx = (GL2Encoder *)self;
4365 ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4366}
4367
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004368void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) {
4369 GL2Encoder *ctx = (GL2Encoder *)self;
4370
4371 if (!sync) return;
4372
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004373 ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4374}
4375
4376GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4377 GL2Encoder *ctx = (GL2Encoder *)self;
4378 return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4379}
4380
4381void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4382 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004383
4384 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4385
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004386 return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004387}
4388
4389#define LIMIT_CASE(target, lim) \
4390 case target: \
4391 ctx->glGetIntegerv(ctx, lim, &limit); \
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004392 SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004393 break; \
4394
4395void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) {
4396 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004397 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004398
4399 GLint limit;
4400
4401 switch (target) {
4402 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4403 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4404 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4405 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4406 default:
4407 break;
4408 }
4409
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004410 const GLClientState::VertexAttribBindingVector& currBindings =
4411 state->currentVertexBufferBindings();
4412
4413 switch (target) {
4414 case GL_VERTEX_BINDING_DIVISOR:
4415 case GL_VERTEX_BINDING_OFFSET:
4416 case GL_VERTEX_BINDING_STRIDE:
4417 case GL_VERTEX_BINDING_BUFFER:
4418 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4419 break;
4420 default:
4421 break;
4422 }
4423
4424 switch (target) {
4425 case GL_VERTEX_BINDING_DIVISOR:
4426 *params = currBindings[index].divisor;
4427 return;
4428 case GL_VERTEX_BINDING_OFFSET:
4429 *params = currBindings[index].offset;
4430 return;
4431 case GL_VERTEX_BINDING_STRIDE:
4432 *params = currBindings[index].effectiveStride;
4433 return;
4434 case GL_VERTEX_BINDING_BUFFER:
4435 *params = currBindings[index].buffer;
4436 return;
4437 default:
4438 break;
4439 }
4440
Lingfeng Yang80a36332017-07-09 10:58:07 -07004441 ctx->safe_glGetIntegeri_v(target, index, params);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004442}
4443
4444void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
4445 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004446 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004447
4448 GLint limit;
4449
4450 switch (target) {
4451 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4452 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4453 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4454 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4455 default:
4456 break;
4457 }
4458
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004459 const GLClientState::VertexAttribBindingVector& currBindings =
4460 state->currentVertexBufferBindings();
4461
4462 switch (target) {
4463 case GL_VERTEX_BINDING_DIVISOR:
4464 case GL_VERTEX_BINDING_OFFSET:
4465 case GL_VERTEX_BINDING_STRIDE:
4466 case GL_VERTEX_BINDING_BUFFER:
4467 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4468 break;
4469 default:
4470 break;
4471 }
4472
4473 switch (target) {
4474 case GL_VERTEX_BINDING_DIVISOR:
4475 *params = currBindings[index].divisor;
4476 return;
4477 case GL_VERTEX_BINDING_OFFSET:
4478 *params = currBindings[index].offset;
4479 return;
4480 case GL_VERTEX_BINDING_STRIDE:
4481 *params = currBindings[index].effectiveStride;
4482 return;
4483 case GL_VERTEX_BINDING_BUFFER:
4484 *params = currBindings[index].buffer;
4485 return;
4486 default:
4487 break;
4488 }
4489
Lingfeng Yang80a36332017-07-09 10:58:07 -07004490 ctx->safe_glGetInteger64i_v(target, index, params);
4491}
4492
4493void GL2Encoder::s_glGetInteger64v(void* self, GLenum param, GLint64* val) {
4494 GL2Encoder *ctx = (GL2Encoder *)self;
4495 ctx->safe_glGetInteger64v(param, val);
4496}
4497
4498void GL2Encoder::s_glGetBooleani_v(void* self, GLenum param, GLuint index, GLboolean* val) {
4499 GL2Encoder *ctx = (GL2Encoder *)self;
4500 ctx->safe_glGetBooleani_v(param, index, val);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004501}
4502
4503void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4504 GL2Encoder *ctx = (GL2Encoder *)self;
4505 ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4506 if (pname == GL_SHADER_SOURCE_LENGTH) {
4507 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4508 if (shaderData) {
4509 int totalLen = 0;
4510 for (int i = 0; i < shaderData->sources.size(); i++) {
4511 totalLen += shaderData->sources[i].size();
4512 }
4513 if (totalLen != 0) {
4514 *params = totalLen + 1; // account for null terminator
4515 }
4516 }
4517 }
4518}
4519
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004520void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) {
4521 GL2Encoder *ctx = (GL2Encoder*)self;
4522 GLClientState* state = ctx->m_state;
4523 GLSharedGroupPtr shared = ctx->m_shared;
4524
4525 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4526 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4527 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4528
4529 ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program);
4530 if (!state->currentProgram()) {
4531 state->setCurrentShaderProgram(program);
4532 }
4533}
4534
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004535GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4536
4537 GLint* length = NULL;
4538 GL2Encoder* ctx = (GL2Encoder*)self;
4539
4540 int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
4541 char *str = new char[len + 1];
4542 glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
4543
4544 // Do GLSharedGroup and location WorkARound-specific initialization
4545 // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4546 uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4547 ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004548
Lingfeng Yang44209df2018-09-21 10:04:17 -07004549 if (!replaceSamplerExternalWith2D(str, &spData->shaderData)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004550 delete [] str;
4551 ctx->setError(GL_OUT_OF_MEMORY);
4552 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4553 return -1;
4554 }
4555
4556 GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
4557 delete [] str;
4558
4559 // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4560 GLint linkStatus = 0;
4561 ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4562 if (!linkStatus) {
4563 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4564 return -1;
4565 }
4566
4567 ctx->m_shared->associateGLShaderProgram(res, spDataId);
4568
4569 GLint numUniforms = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07004570 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORMS, &numUniforms);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004571 ctx->m_shared->initShaderProgramData(res, numUniforms);
4572
4573 GLint maxLength=0;
4574 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4575
4576 GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4577
4578 for (GLint i = 0; i < numUniforms; ++i) {
4579 ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4580 GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4581 ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4582 }
4583
4584 ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4585
4586 delete [] name;
4587
4588 return res;
4589}
4590
4591void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4592{
4593 GL2Encoder *ctx = (GL2Encoder*)self;
4594 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4595 ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4596}
4597
4598void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4599{
4600 GL2Encoder *ctx = (GL2Encoder*)self;
4601 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4602 ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4603}
4604
4605void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4606{
4607 GL2Encoder *ctx = (GL2Encoder*)self;
4608 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004609 ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004610
4611 GLClientState* state = ctx->m_state;
4612 GLSharedGroupPtr shared = ctx->m_shared;
4613 GLenum target;
4614
4615 if (shared->setSamplerUniform(program, location, v0, &target)) {
4616 GLenum origActiveTexture = state->getActiveTextureUnit();
4617 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4618 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4619 }
4620 state->setActiveTextureUnit(origActiveTexture);
4621 }
4622}
4623
4624void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4625{
4626 GL2Encoder *ctx = (GL2Encoder*)self;
4627 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4628 ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4629}
4630
4631void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4632{
4633 GL2Encoder *ctx = (GL2Encoder*)self;
4634 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4635 ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4636
4637 GLClientState* state = ctx->m_state;
4638 GLSharedGroupPtr shared = ctx->m_shared;
4639 GLenum target;
4640
4641 if (shared->setSamplerUniform(program, location, v0, &target)) {
4642 GLenum origActiveTexture = state->getActiveTextureUnit();
4643 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4644 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4645 }
4646 state->setActiveTextureUnit(origActiveTexture);
4647 }
4648}
4649
4650void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4651{
4652 GL2Encoder *ctx = (GL2Encoder*)self;
4653 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4654 ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
4655}
4656
4657void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
4658{
4659 GL2Encoder *ctx = (GL2Encoder*)self;
4660 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4661 ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
4662}
4663
4664void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4665{
4666 GL2Encoder *ctx = (GL2Encoder*)self;
4667 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4668 ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
4669}
4670
4671void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
4672{
4673 GL2Encoder *ctx = (GL2Encoder*)self;
4674 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4675 ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
4676}
4677
4678void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4679{
4680 GL2Encoder *ctx = (GL2Encoder*)self;
4681 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4682 ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
4683}
4684
4685void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
4686{
4687 GL2Encoder *ctx = (GL2Encoder*)self;
4688 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4689 ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
4690}
4691
4692void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4693{
4694 GL2Encoder *ctx = (GL2Encoder*)self;
4695 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4696 ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
4697}
4698
4699void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
4700{
4701 GL2Encoder *ctx = (GL2Encoder*)self;
4702 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4703 ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
4704}
4705
4706void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4707{
4708 GL2Encoder *ctx = (GL2Encoder*)self;
4709 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4710 ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
4711}
4712
4713void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
4714{
4715 GL2Encoder *ctx = (GL2Encoder*)self;
4716 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4717 ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
4718}
4719
4720void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4721{
4722 GL2Encoder *ctx = (GL2Encoder*)self;
4723 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4724 ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
4725}
4726
4727void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
4728{
4729 GL2Encoder *ctx = (GL2Encoder*)self;
4730 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4731 ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
4732}
4733
4734void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4735{
4736 GL2Encoder *ctx = (GL2Encoder*)self;
4737 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4738 ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
4739}
4740
4741void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
4742{
4743 GL2Encoder *ctx = (GL2Encoder*)self;
4744 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4745 ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
4746}
4747
4748void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4749{
4750 GL2Encoder *ctx = (GL2Encoder*)self;
4751 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4752 ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
4753}
4754
4755void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
4756{
4757 GL2Encoder *ctx = (GL2Encoder*)self;
4758 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4759 ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
4760}
4761
4762void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4763{
4764 GL2Encoder *ctx = (GL2Encoder*)self;
4765 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4766 ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
4767}
4768
4769void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
4770{
4771 GL2Encoder *ctx = (GL2Encoder*)self;
4772 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4773 ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
4774}
4775
4776void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4777{
4778 GL2Encoder *ctx = (GL2Encoder*)self;
4779 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4780 ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
4781}
4782
4783void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4784{
4785 GL2Encoder *ctx = (GL2Encoder*)self;
4786 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4787 ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
4788}
4789
4790void GL2Encoder::s_glProgramUniformMatrix2x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4791{
4792 GL2Encoder *ctx = (GL2Encoder*)self;
4793 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4794 ctx->m_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
4795}
4796
4797void GL2Encoder::s_glProgramUniformMatrix2x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4798{
4799 GL2Encoder *ctx = (GL2Encoder*)self;
4800 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4801 ctx->m_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
4802}
4803
4804void GL2Encoder::s_glProgramUniformMatrix3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4805{
4806 GL2Encoder *ctx = (GL2Encoder*)self;
4807 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4808 ctx->m_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
4809}
4810
4811void GL2Encoder::s_glProgramUniformMatrix3x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4812{
4813 GL2Encoder *ctx = (GL2Encoder*)self;
4814 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4815 ctx->m_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
4816}
4817
4818void GL2Encoder::s_glProgramUniformMatrix3x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4819{
4820 GL2Encoder *ctx = (GL2Encoder*)self;
4821 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4822 ctx->m_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
4823}
4824
4825void GL2Encoder::s_glProgramUniformMatrix4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4826{
4827 GL2Encoder *ctx = (GL2Encoder*)self;
4828 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4829 ctx->m_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
4830}
4831
4832void GL2Encoder::s_glProgramUniformMatrix4x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4833{
4834 GL2Encoder *ctx = (GL2Encoder*)self;
4835 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4836 ctx->m_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
4837}
4838
4839void GL2Encoder::s_glProgramUniformMatrix4x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4840{
4841 GL2Encoder *ctx = (GL2Encoder*)self;
4842 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4843 ctx->m_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
4844}
4845
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004846void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) {
4847 GL2Encoder* ctx = (GL2Encoder*)self;
4848 ctx->m_glProgramParameteri_enc(self, program, pname, value);
4849}
4850
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004851void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
4852{
4853 GL2Encoder *ctx = (GL2Encoder*)self;
4854 GLClientState* state = ctx->m_state;
4855 GLSharedGroupPtr shared = ctx->m_shared;
4856
4857 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4858 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4859 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4860
4861 ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
4862 state->associateProgramWithPipeline(program, pipeline);
4863
4864 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4865 if (state->currentProgram()) {
4866 return;
4867 }
4868
4869 // Otherwise, update host texture 2D bindings.
4870 ctx->updateHostTexture2DBindingsFromProgramData(program);
4871}
4872
4873void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
4874{
4875 GL2Encoder *ctx = (GL2Encoder*)self;
4876 GLClientState* state = ctx->m_state;
4877
4878 ctx->m_glBindProgramPipeline_enc(self, pipeline);
4879
4880 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4881 if (!pipeline || state->currentProgram()) {
4882 return;
4883 }
4884
4885 GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
4886 for (; it != state->programPipelineEnd(); ++it) {
4887 if (it->second == pipeline) {
4888 ctx->updateHostTexture2DBindingsFromProgramData(it->first);
4889 }
4890 }
4891}
4892
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004893void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
4894 GL2Encoder *ctx = (GL2Encoder*)self;
4895 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4896 if (bufSize == 0) {
4897 if (length) *length = 0;
4898 return;
4899 }
4900
4901 // Avoid modifying |name| if |*length| < bufSize.
4902 GLint* intermediate = new GLint[bufSize];
4903 GLsizei* myLength = length ? length : new GLsizei;
4904 bool needFreeLength = length == NULL;
4905
4906 ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
4907 GLsizei writtenInts = *myLength;
4908 memcpy(params, intermediate, writtenInts * sizeof(GLint));
4909
4910 delete [] intermediate;
4911 if (needFreeLength)
4912 delete myLength;
4913}
4914
4915GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
4916 GL2Encoder *ctx = (GL2Encoder*)self;
4917 return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
4918}
4919
4920GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
4921 GL2Encoder *ctx = (GL2Encoder*)self;
4922 return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
4923}
4924
4925void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
4926 GL2Encoder *ctx = (GL2Encoder*)self;
4927 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4928 if (bufSize == 0) {
4929 if (length) *length = 0;
4930 return;
4931 }
4932
4933 // Avoid modifying |name| if |*length| < bufSize.
4934 char* intermediate = new char[bufSize];
4935 GLsizei* myLength = length ? length : new GLsizei;
4936 bool needFreeLength = length == NULL;
4937
4938 ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
4939 GLsizei writtenStrLen = *myLength;
4940 memcpy(name, intermediate, writtenStrLen + 1);
4941
4942 delete [] intermediate;
4943 if (needFreeLength)
4944 delete myLength;
4945}
4946
4947void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
4948 GL2Encoder *ctx = (GL2Encoder*)self;
4949 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4950 if (bufSize == 0) {
4951 if (length) *length = 0;
4952 return;
4953 }
4954
4955 // Avoid modifying |infoLog| if |*length| < bufSize.
4956 GLchar* intermediate = new GLchar[bufSize];
4957 GLsizei* myLength = length ? length : new GLsizei;
4958 bool needFreeLength = length == NULL;
4959
4960 ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
4961 GLsizei writtenStrLen = *myLength;
4962 memcpy(infoLog, intermediate, writtenStrLen + 1);
4963
4964 delete [] intermediate;
4965 if (needFreeLength)
4966 delete myLength;
4967}
4968
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004969void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
4970 GL2Encoder *ctx = (GL2Encoder*)self;
4971 GLClientState* state = ctx->m_state;
4972
Lingfeng Yang07289902017-01-27 12:26:19 -08004973 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004974 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4975
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004976 state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false);
4977 ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset);
4978}
4979
4980void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
4981 GL2Encoder *ctx = (GL2Encoder*)self;
4982 GLClientState* state = ctx->m_state;
4983
Lingfeng Yang07289902017-01-27 12:26:19 -08004984 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004985 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4986
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004987 state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true);
4988 ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset);
4989}
4990
4991void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004992 GL2Encoder *ctx = (GL2Encoder*)self;
4993 GLClientState* state = ctx->m_state;
4994
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004995 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4996
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004997 state->setVertexBindingDivisor(bindingindex, divisor);
4998 ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor);
4999}
5000
5001void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) {
5002 GL2Encoder *ctx = (GL2Encoder*)self;
5003 GLClientState* state = ctx->m_state;
Lingfeng Yang07289902017-01-27 12:26:19 -08005004 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005005 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005006
5007 state->setVertexAttribBinding(attribindex, bindingindex);
5008 ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex);
5009}
5010
5011void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
5012 GL2Encoder *ctx = (GL2Encoder*)self;
5013 GLClientState* state = ctx->m_state;
5014
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005015 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
5016
5017 GLint maxStride;
5018 ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
5019 SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE);
5020
5021 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5022
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005023 state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride);
5024 ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride);
5025}
5026
5027void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) {
5028 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005029 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005030
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005031 bool hasClientArrays = false;
5032 ctx->getVBOUsage(&hasClientArrays, NULL);
5033
5034 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
5035 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5036 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
5037
5038 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005039 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005040 // BufferData* buf = ctx->getBufferData(target);
5041 // if (buf) {
5042 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
5043 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005044 ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect);
5045 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005046 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
5047 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005048 ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize);
5049 }
5050}
5051
5052void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) {
5053 GL2Encoder *ctx = (GL2Encoder*)self;
5054
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005055 GLClientState* state = ctx->m_state;
5056
5057 bool hasClientArrays = false;
5058 ctx->getVBOUsage(&hasClientArrays, NULL);
5059
5060 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
5061 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5062 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
5063
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005064 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005065
5066 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005067 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005068 // BufferData* buf = ctx->getBufferData(target);
5069 // if (buf) {
5070 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
5071 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005072 ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect);
5073 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005074 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
5075 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005076 ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize);
5077 }
5078
5079}
5080
5081void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
5082 GL2Encoder *ctx = (GL2Encoder*)self;
5083 GLClientState* state = ctx->m_state;
5084
5085 SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
5086 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
5087 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
5088 SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
5089 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005090 GLint max_samples;
5091 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
5092 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005093
5094 state->setBoundTextureInternalFormat(target, internalformat);
5095 state->setBoundTextureDims(target, 0, width, height, 1);
5096 state->setBoundTextureImmutableFormat(target);
5097 state->setBoundTextureSamples(target, samples);
5098
5099 ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
5100}
5101