blob: 4fc1765c5527c8007405827eb1987e4a82c1611f [file] [log] [blame]
keunyoungb85b2752013-03-08 12:28:03 -08001/*
2* Copyright (C) 2011 The Android Open Source Project
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17#include "GL2Encoder.h"
Lingfeng Yang46153ab2017-01-09 13:37:22 -080018#include "GLESv2Validation.h"
19
20#include <string>
21#include <map>
22
keunyoungb85b2752013-03-08 12:28:03 -080023#include <assert.h>
24#include <ctype.h>
25
Lingfeng Yang69066602016-04-12 09:29:11 -070026#include <GLES2/gl2.h>
27#include <GLES2/gl2ext.h>
28#include <GLES2/gl2platform.h>
29
30#include <GLES3/gl3.h>
Lingfeng Yang46153ab2017-01-09 13:37:22 -080031#include <GLES3/gl31.h>
Lingfeng Yang69066602016-04-12 09:29:11 -070032
keunyoungb85b2752013-03-08 12:28:03 -080033#ifndef MIN
34#define MIN(a, b) ((a) < (b) ? (a) : (b))
35#endif
36
37static GLubyte *gVendorString= (GLubyte *) "Android";
Lingfeng Yang46153ab2017-01-09 13:37:22 -080038static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 3.0";
39static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 3.0";
Nicolas Capensfe2d51a2015-11-20 15:10:09 -050040static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external ";
keunyoungb85b2752013-03-08 12:28:03 -080041
Lingfeng Yang07289902017-01-27 12:26:19 -080042#define SET_ERROR_IF(condition, err) if((condition)) { \
keunyoungb85b2752013-03-08 12:28:03 -080043 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
Lingfeng Yang07289902017-01-27 12:26:19 -080044 ctx->setError(err); \
45 return; \
keunyoungb85b2752013-03-08 12:28:03 -080046 }
47
Lingfeng Yang07289902017-01-27 12:26:19 -080048#define SET_ERROR_WITH_MESSAGE_IF(condition, err, generator, genargs) if ((condition)) { \
49 std::string msg = generator genargs; \
50 ALOGE("%s:%s:%d GL error 0x%x\n" \
51 "Info: %s\n", __FILE__, __FUNCTION__, __LINE__, err, msg.c_str()); \
52 ctx->setError(err); \
53 return; \
54 } \
keunyoungb85b2752013-03-08 12:28:03 -080055
Lingfeng Yang07289902017-01-27 12:26:19 -080056#define RET_AND_SET_ERROR_IF(condition, err, ret) if((condition)) { \
keunyoungb85b2752013-03-08 12:28:03 -080057 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
Lingfeng Yang07289902017-01-27 12:26:19 -080058 ctx->setError(err); \
59 return ret; \
60 } \
keunyoungb85b2752013-03-08 12:28:03 -080061
Lingfeng Yang07289902017-01-27 12:26:19 -080062#define RET_AND_SET_ERROR_WITH_MESSAGE_IF(condition, err, ret, generator, genargs) if((condition)) { \
63 std::string msg = generator genargs; \
64 ALOGE("%s:%s:%d GL error 0x%x\n" \
65 "Info: %s\n", __FILE__, __FUNCTION__, __LINE__, err, msg.c_str()); \
66 ctx->setError(err); \
67 return ret; \
68 } \
keunyoungb85b2752013-03-08 12:28:03 -080069
Yahan Zhoub7f09082016-03-10 11:45:02 -080070GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
71 : gl2_encoder_context_t(stream, protocol)
keunyoungb85b2752013-03-08 12:28:03 -080072{
Lingfeng Yange6556dc2017-01-09 12:04:12 -080073 m_currMajorVersion = 2;
74 m_currMinorVersion = 0;
keunyoungb85b2752013-03-08 12:28:03 -080075 m_initialized = false;
Lingfeng Yange980c7a2018-01-12 14:50:18 -080076 m_noHostError = false;
keunyoungb85b2752013-03-08 12:28:03 -080077 m_state = NULL;
78 m_error = GL_NO_ERROR;
79 m_num_compressedTextureFormats = 0;
Lizhe Liue41f4ef2015-05-27 11:13:23 +080080 m_max_cubeMapTextureSize = 0;
81 m_max_renderBufferSize = 0;
82 m_max_textureSize = 0;
Lingfeng Yang46153ab2017-01-09 13:37:22 -080083 m_max_3d_textureSize = 0;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -080084 m_max_vertexAttribStride = 0;
keunyoungb85b2752013-03-08 12:28:03 -080085 m_compressedTextureFormats = NULL;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010086
Lingfeng Yang46153ab2017-01-09 13:37:22 -080087 m_ssbo_offset_align = 0;
88 m_ubo_offset_align = 0;
89
Lingfeng Yangde51dfb2016-10-17 22:48:59 -070090 m_drawCallFlushCount = 0;
91 m_primitiveRestartEnabled = false;
92 m_primitiveRestartIndex = 0;
93
Lingfeng Yang07289902017-01-27 12:26:19 -080094 // overrides
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +010095#define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name
Lingfeng Yange6556dc2017-01-09 12:04:12 -080096#define OVERRIDE_CUSTOM(name) this-> name = &s_##name
97#define OVERRIDEWITH(name, target) do { \
98 m_##target##_enc = this-> target; \
99 this-> target = &s_##name; \
100} while(0)
101#define OVERRIDEOES(name) OVERRIDEWITH(name, name##OES)
bohu56bf82f2014-10-17 15:35:48 -0700102
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100103 OVERRIDE(glFlush);
104 OVERRIDE(glPixelStorei);
105 OVERRIDE(glGetString);
106 OVERRIDE(glBindBuffer);
107 OVERRIDE(glBufferData);
108 OVERRIDE(glBufferSubData);
109 OVERRIDE(glDeleteBuffers);
110 OVERRIDE(glDrawArrays);
111 OVERRIDE(glDrawElements);
112 OVERRIDE(glGetIntegerv);
113 OVERRIDE(glGetFloatv);
114 OVERRIDE(glGetBooleanv);
115 OVERRIDE(glVertexAttribPointer);
116 OVERRIDE(glEnableVertexAttribArray);
117 OVERRIDE(glDisableVertexAttribArray);
118 OVERRIDE(glGetVertexAttribiv);
119 OVERRIDE(glGetVertexAttribfv);
120 OVERRIDE(glGetVertexAttribPointerv);
keunyoungb85b2752013-03-08 12:28:03 -0800121
Bo Hu73568cd2015-01-20 16:29:50 -0800122 this->glShaderBinary = &s_glShaderBinary;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100123 this->glShaderSource = &s_glShaderSource;
124 this->glFinish = &s_glFinish;
keunyoungb85b2752013-03-08 12:28:03 -0800125
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100126 OVERRIDE(glGetError);
127 OVERRIDE(glLinkProgram);
128 OVERRIDE(glDeleteProgram);
129 OVERRIDE(glGetUniformiv);
130 OVERRIDE(glGetUniformfv);
131 OVERRIDE(glCreateProgram);
132 OVERRIDE(glCreateShader);
133 OVERRIDE(glDeleteShader);
134 OVERRIDE(glAttachShader);
135 OVERRIDE(glDetachShader);
136 OVERRIDE(glGetAttachedShaders);
137 OVERRIDE(glGetShaderSource);
138 OVERRIDE(glGetShaderInfoLog);
139 OVERRIDE(glGetProgramInfoLog);
140
141 OVERRIDE(glGetUniformLocation);
142 OVERRIDE(glUseProgram);
143
144 OVERRIDE(glUniform1f);
145 OVERRIDE(glUniform1fv);
146 OVERRIDE(glUniform1i);
147 OVERRIDE(glUniform1iv);
148 OVERRIDE(glUniform2f);
149 OVERRIDE(glUniform2fv);
150 OVERRIDE(glUniform2i);
151 OVERRIDE(glUniform2iv);
152 OVERRIDE(glUniform3f);
153 OVERRIDE(glUniform3fv);
154 OVERRIDE(glUniform3i);
155 OVERRIDE(glUniform3iv);
156 OVERRIDE(glUniform4f);
157 OVERRIDE(glUniform4fv);
158 OVERRIDE(glUniform4i);
159 OVERRIDE(glUniform4iv);
160 OVERRIDE(glUniformMatrix2fv);
161 OVERRIDE(glUniformMatrix3fv);
162 OVERRIDE(glUniformMatrix4fv);
163
164 OVERRIDE(glActiveTexture);
165 OVERRIDE(glBindTexture);
166 OVERRIDE(glDeleteTextures);
167 OVERRIDE(glGetTexParameterfv);
168 OVERRIDE(glGetTexParameteriv);
169 OVERRIDE(glTexParameterf);
170 OVERRIDE(glTexParameterfv);
171 OVERRIDE(glTexParameteri);
172 OVERRIDE(glTexParameteriv);
bohu26a92982014-11-25 16:50:37 -0800173 OVERRIDE(glTexImage2D);
Yahan Zhou2a208292016-06-22 15:36:04 -0700174 OVERRIDE(glTexSubImage2D);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -0700175 OVERRIDE(glCopyTexImage2D);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700176
177 OVERRIDE(glGenRenderbuffers);
178 OVERRIDE(glDeleteRenderbuffers);
179 OVERRIDE(glBindRenderbuffer);
Lingfeng Yang69066602016-04-12 09:29:11 -0700180 OVERRIDE(glRenderbufferStorage);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700181 OVERRIDE(glFramebufferRenderbuffer);
182
183 OVERRIDE(glGenFramebuffers);
184 OVERRIDE(glDeleteFramebuffers);
185 OVERRIDE(glBindFramebuffer);
186 OVERRIDE(glFramebufferTexture2D);
187 OVERRIDE(glFramebufferTexture3DOES);
188 OVERRIDE(glGetFramebufferAttachmentParameteriv);
Lingfeng Yang69066602016-04-12 09:29:11 -0700189
190 OVERRIDE(glCheckFramebufferStatus);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800191
192 OVERRIDE(glGenVertexArrays);
193 OVERRIDE(glDeleteVertexArrays);
194 OVERRIDE(glBindVertexArray);
195 OVERRIDEOES(glGenVertexArrays);
196 OVERRIDEOES(glDeleteVertexArrays);
197 OVERRIDEOES(glBindVertexArray);
198
Lingfeng Yangfb3d2bb2017-09-07 15:02:04 -0700199 OVERRIDE_CUSTOM(glMapBufferOES);
200 OVERRIDE_CUSTOM(glUnmapBufferOES);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800201 OVERRIDE_CUSTOM(glMapBufferRange);
202 OVERRIDE_CUSTOM(glUnmapBuffer);
203 OVERRIDE_CUSTOM(glFlushMappedBufferRange);
204
205 OVERRIDE(glCompressedTexImage2D);
206 OVERRIDE(glCompressedTexSubImage2D);
207
208 OVERRIDE(glBindBufferRange);
209 OVERRIDE(glBindBufferBase);
210
211 OVERRIDE(glCopyBufferSubData);
212
213 OVERRIDE(glGetBufferParameteriv);
214 OVERRIDE(glGetBufferParameteri64v);
215 OVERRIDE(glGetBufferPointerv);
216
217 OVERRIDE_CUSTOM(glGetUniformIndices);
218
219 OVERRIDE(glUniform1ui);
220 OVERRIDE(glUniform2ui);
221 OVERRIDE(glUniform3ui);
222 OVERRIDE(glUniform4ui);
223 OVERRIDE(glUniform1uiv);
224 OVERRIDE(glUniform2uiv);
225 OVERRIDE(glUniform3uiv);
226 OVERRIDE(glUniform4uiv);
227 OVERRIDE(glUniformMatrix2x3fv);
228 OVERRIDE(glUniformMatrix3x2fv);
229 OVERRIDE(glUniformMatrix2x4fv);
230 OVERRIDE(glUniformMatrix4x2fv);
231 OVERRIDE(glUniformMatrix3x4fv);
232 OVERRIDE(glUniformMatrix4x3fv);
233
234 OVERRIDE(glGetUniformuiv);
235 OVERRIDE(glGetActiveUniformBlockiv);
236
237 OVERRIDE(glGetVertexAttribIiv);
238 OVERRIDE(glGetVertexAttribIuiv);
239
240 OVERRIDE_CUSTOM(glVertexAttribIPointer);
241
242 OVERRIDE(glVertexAttribDivisor);
243
244 OVERRIDE(glRenderbufferStorageMultisample);
245 OVERRIDE(glDrawBuffers);
246 OVERRIDE(glReadBuffer);
247 OVERRIDE(glFramebufferTextureLayer);
248 OVERRIDE(glTexStorage2D);
249
250 OVERRIDE_CUSTOM(glTransformFeedbackVaryings);
251 OVERRIDE(glBeginTransformFeedback);
252 OVERRIDE(glEndTransformFeedback);
253 OVERRIDE(glPauseTransformFeedback);
254 OVERRIDE(glResumeTransformFeedback);
255
256 OVERRIDE(glTexImage3D);
257 OVERRIDE(glTexSubImage3D);
258 OVERRIDE(glTexStorage3D);
259 OVERRIDE(glCompressedTexImage3D);
260 OVERRIDE(glCompressedTexSubImage3D);
261
262 OVERRIDE(glDrawArraysInstanced);
263 OVERRIDE_CUSTOM(glDrawElementsInstanced);
264 OVERRIDE_CUSTOM(glDrawRangeElements);
265
266 OVERRIDE_CUSTOM(glGetStringi);
267 OVERRIDE(glGetProgramBinary);
268 OVERRIDE(glReadPixels);
269
270 OVERRIDE(glEnable);
271 OVERRIDE(glDisable);
272 OVERRIDE(glClearBufferiv);
273 OVERRIDE(glClearBufferuiv);
274 OVERRIDE(glClearBufferfv);
275 OVERRIDE(glBlitFramebuffer);
276 OVERRIDE_CUSTOM(glGetInternalformativ);
277
278 OVERRIDE(glGenerateMipmap);
279
280 OVERRIDE(glBindSampler);
281
Lingfeng Yangf000ab42017-01-11 18:31:38 -0800282 OVERRIDE_CUSTOM(glFenceSync);
283 OVERRIDE_CUSTOM(glClientWaitSync);
284 OVERRIDE_CUSTOM(glWaitSync);
285 OVERRIDE_CUSTOM(glDeleteSync);
286 OVERRIDE_CUSTOM(glIsSync);
287 OVERRIDE_CUSTOM(glGetSynciv);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800288
289 OVERRIDE(glGetIntegeri_v);
290 OVERRIDE(glGetInteger64i_v);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700291 OVERRIDE(glGetInteger64v);
292 OVERRIDE(glGetBooleani_v);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800293
294 OVERRIDE(glGetShaderiv);
295
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800296 OVERRIDE(glActiveShaderProgram);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800297 OVERRIDE_CUSTOM(glCreateShaderProgramv);
298 OVERRIDE(glProgramUniform1f);
299 OVERRIDE(glProgramUniform1fv);
300 OVERRIDE(glProgramUniform1i);
301 OVERRIDE(glProgramUniform1iv);
302 OVERRIDE(glProgramUniform1ui);
303 OVERRIDE(glProgramUniform1uiv);
304 OVERRIDE(glProgramUniform2f);
305 OVERRIDE(glProgramUniform2fv);
306 OVERRIDE(glProgramUniform2i);
307 OVERRIDE(glProgramUniform2iv);
308 OVERRIDE(glProgramUniform2ui);
309 OVERRIDE(glProgramUniform2uiv);
310 OVERRIDE(glProgramUniform3f);
311 OVERRIDE(glProgramUniform3fv);
312 OVERRIDE(glProgramUniform3i);
313 OVERRIDE(glProgramUniform3iv);
314 OVERRIDE(glProgramUniform3ui);
315 OVERRIDE(glProgramUniform3uiv);
316 OVERRIDE(glProgramUniform4f);
317 OVERRIDE(glProgramUniform4fv);
318 OVERRIDE(glProgramUniform4i);
319 OVERRIDE(glProgramUniform4iv);
320 OVERRIDE(glProgramUniform4ui);
321 OVERRIDE(glProgramUniform4uiv);
322 OVERRIDE(glProgramUniformMatrix2fv);
323 OVERRIDE(glProgramUniformMatrix2x3fv);
324 OVERRIDE(glProgramUniformMatrix2x4fv);
325 OVERRIDE(glProgramUniformMatrix3fv);
326 OVERRIDE(glProgramUniformMatrix3x2fv);
327 OVERRIDE(glProgramUniformMatrix3x4fv);
328 OVERRIDE(glProgramUniformMatrix4fv);
329 OVERRIDE(glProgramUniformMatrix4x2fv);
330 OVERRIDE(glProgramUniformMatrix4x3fv);
331
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800332 OVERRIDE(glProgramParameteri);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800333 OVERRIDE(glUseProgramStages);
334 OVERRIDE(glBindProgramPipeline);
335
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800336 OVERRIDE(glGetProgramResourceiv);
337 OVERRIDE(glGetProgramResourceIndex);
338 OVERRIDE(glGetProgramResourceLocation);
339 OVERRIDE(glGetProgramResourceName);
340 OVERRIDE(glGetProgramPipelineInfoLog);
341
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800342 OVERRIDE(glVertexAttribFormat);
343 OVERRIDE(glVertexAttribIFormat);
344 OVERRIDE(glVertexBindingDivisor);
345 OVERRIDE(glVertexAttribBinding);
346 OVERRIDE(glBindVertexBuffer);
347
348 OVERRIDE_CUSTOM(glDrawArraysIndirect);
349 OVERRIDE_CUSTOM(glDrawElementsIndirect);
350
351 OVERRIDE(glTexStorage2DMultisample);
keunyoungb85b2752013-03-08 12:28:03 -0800352}
353
354GL2Encoder::~GL2Encoder()
355{
356 delete m_compressedTextureFormats;
357}
358
359GLenum GL2Encoder::s_glGetError(void * self)
360{
361 GL2Encoder *ctx = (GL2Encoder *)self;
362 GLenum err = ctx->getError();
363 if(err != GL_NO_ERROR) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700364 ctx->m_glGetError_enc(ctx); // also clear host error
keunyoungb85b2752013-03-08 12:28:03 -0800365 ctx->setError(GL_NO_ERROR);
366 return err;
367 }
368
Lingfeng Yange980c7a2018-01-12 14:50:18 -0800369 if (ctx->m_noHostError) {
370 return GL_NO_ERROR;
371 } else {
372 return ctx->m_glGetError_enc(self);
373 }
Lingfeng Yang80a36332017-07-09 10:58:07 -0700374}
Yahan Zhouae30fe82016-08-10 21:15:45 +0000375
Lingfeng Yang80a36332017-07-09 10:58:07 -0700376class GL2Encoder::ErrorUpdater {
377public:
378 ErrorUpdater(GL2Encoder* ctx) :
379 mCtx(ctx),
380 guest_error(ctx->getError()),
381 host_error(ctx->m_glGetError_enc(ctx)) {
382 // Preserve any existing GL error in the guest:
383 // OpenGL ES 3.0.5 spec:
384 // The command enum GetError( void ); is used to obtain error information.
385 // Each detectable error is assigned a numeric code. When an error is
386 // detected, a flag is set and the code is recorded. Further errors, if
387 // they occur, do not affect this recorded code. When GetError is called,
388 // the code is returned and the flag is cleared, so that a further error
389 // will again record its code. If a call to GetError returns NO_ERROR, then
390 // there has been no detectable error since the last call to GetError (or
391 // since the GL was initialized).
392 if (guest_error == GL_NO_ERROR) {
393 guest_error = host_error;
394 }
395 }
396
397 GLenum getHostErrorAndUpdate() {
398 host_error = mCtx->m_glGetError_enc(mCtx);
399 if (guest_error == GL_NO_ERROR) {
400 guest_error = host_error;
401 }
402 return host_error;
403 }
404
405 void updateGuestErrorState() {
406 mCtx->setError(guest_error);
407 }
408
409private:
410 GL2Encoder* mCtx;
411 GLenum guest_error;
412 GLenum host_error;
413};
414
415template<class T>
416class GL2Encoder::ScopedQueryUpdate {
417public:
418 ScopedQueryUpdate(GL2Encoder* ctx, uint32_t bytes, T* target) :
419 mCtx(ctx),
420 mBuf(bytes, 0),
421 mTarget(target),
422 mErrorUpdater(ctx) {
423 }
424 T* hostStagingBuffer() {
425 return (T*)&mBuf[0];
426 }
427 ~ScopedQueryUpdate() {
428 GLint hostError = mErrorUpdater.getHostErrorAndUpdate();
429 if (hostError == GL_NO_ERROR) {
430 memcpy(mTarget, &mBuf[0], mBuf.size());
431 }
432 mErrorUpdater.updateGuestErrorState();
433 }
434private:
435 GL2Encoder* mCtx;
436 std::vector<char> mBuf;
437 T* mTarget;
438 ErrorUpdater mErrorUpdater;
439};
440
441void GL2Encoder::safe_glGetBooleanv(GLenum param, GLboolean* val) {
442 ScopedQueryUpdate<GLboolean> query(this, glUtilsParamSize(param) * sizeof(GLboolean), val);
443 m_glGetBooleanv_enc(this, param, query.hostStagingBuffer());
444}
445
446void GL2Encoder::safe_glGetFloatv(GLenum param, GLfloat* val) {
447 ScopedQueryUpdate<GLfloat> query(this, glUtilsParamSize(param) * sizeof(GLfloat), val);
448 m_glGetFloatv_enc(this, param, query.hostStagingBuffer());
449}
450
451void GL2Encoder::safe_glGetIntegerv(GLenum param, GLint* val) {
452 ScopedQueryUpdate<GLint> query(this, glUtilsParamSize(param) * sizeof(GLint), val);
453 m_glGetIntegerv_enc(this, param, query.hostStagingBuffer());
454}
455
456void GL2Encoder::safe_glGetInteger64v(GLenum param, GLint64* val) {
457 ScopedQueryUpdate<GLint64> query(this, glUtilsParamSize(param) * sizeof(GLint64), val);
458 m_glGetInteger64v_enc(this, param, query.hostStagingBuffer());
459}
460
461void GL2Encoder::safe_glGetIntegeri_v(GLenum param, GLuint index, GLint* val) {
462 ScopedQueryUpdate<GLint> query(this, sizeof(GLint), val);
463 m_glGetIntegeri_v_enc(this, param, index, query.hostStagingBuffer());
464}
465
466void GL2Encoder::safe_glGetInteger64i_v(GLenum param, GLuint index, GLint64* val) {
467 ScopedQueryUpdate<GLint64> query(this, sizeof(GLint64), val);
468 m_glGetInteger64i_v_enc(this, param, index, query.hostStagingBuffer());
469}
470
471void GL2Encoder::safe_glGetBooleani_v(GLenum param, GLuint index, GLboolean* val) {
472 ScopedQueryUpdate<GLboolean> query(this, sizeof(GLboolean), val);
473 m_glGetBooleani_v_enc(this, param, index, query.hostStagingBuffer());
keunyoungb85b2752013-03-08 12:28:03 -0800474}
475
476void GL2Encoder::s_glFlush(void *self)
477{
478 GL2Encoder *ctx = (GL2Encoder *) self;
479 ctx->m_glFlush_enc(self);
480 ctx->m_stream->flush();
481}
482
483const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
484{
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800485 GL2Encoder *ctx = (GL2Encoder *)self;
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100486
keunyoungb85b2752013-03-08 12:28:03 -0800487 GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800488 RET_AND_SET_ERROR_IF(
489 name != GL_VENDOR &&
490 name != GL_RENDERER &&
491 name != GL_VERSION &&
492 name != GL_EXTENSIONS,
493 GL_INVALID_ENUM,
494 retval);
keunyoungb85b2752013-03-08 12:28:03 -0800495 switch(name) {
496 case GL_VENDOR:
497 retval = gVendorString;
498 break;
499 case GL_RENDERER:
500 retval = gRendererString;
501 break;
502 case GL_VERSION:
503 retval = gVersionString;
504 break;
505 case GL_EXTENSIONS:
506 retval = gExtensionsString;
507 break;
508 }
509 return retval;
510}
511
512void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
513{
514 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800515 SET_ERROR_IF(!GLESv2Validation::pixelStoreParam(ctx, param), GL_INVALID_ENUM);
516 SET_ERROR_IF(!GLESv2Validation::pixelStoreValue(param, value), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800517 ctx->m_glPixelStorei_enc(ctx, param, value);
518 assert(ctx->m_state != NULL);
519 ctx->m_state->setPixelStore(param, value);
520}
keunyoungb85b2752013-03-08 12:28:03 -0800521void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
522{
523 GL2Encoder *ctx = (GL2Encoder *) self;
524 assert(ctx->m_state != NULL);
525 ctx->m_state->bindBuffer(target, id);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800526 ctx->m_state->addBuffer(id);
keunyoungb85b2752013-03-08 12:28:03 -0800527 // TODO set error state if needed;
528 ctx->m_glBindBuffer_enc(self, target, id);
529}
530
531void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
532{
533 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800534 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800535 GLuint bufferId = ctx->m_state->getBuffer(target);
536 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
537 SET_ERROR_IF(size<0, GL_INVALID_VALUE);
538
Roman Kiryanovfb903d62018-09-19 13:38:53 -0700539 ctx->m_shared->updateBufferData(bufferId, size, data);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800540 ctx->m_shared->setBufferUsage(bufferId, usage);
keunyoungb85b2752013-03-08 12:28:03 -0800541 ctx->m_glBufferData_enc(self, target, size, data, usage);
542}
543
544void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
545{
546 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800547 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800548 GLuint bufferId = ctx->m_state->getBuffer(target);
549 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800550 SET_ERROR_IF(ctx->isBufferTargetMapped(target), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800551
Roman Kiryanovfb903d62018-09-19 13:38:53 -0700552 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, data);
keunyoungb85b2752013-03-08 12:28:03 -0800553 SET_ERROR_IF(res, res);
554
555 ctx->m_glBufferSubData_enc(self, target, offset, size, data);
556}
557
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800558void GL2Encoder::s_glGenBuffers(void* self, GLsizei n, GLuint* buffers) {
559 GL2Encoder *ctx = (GL2Encoder *) self;
560 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
561 ctx->m_glGenBuffers_enc(self, n, buffers);
562 for (int i = 0; i < n; i++) {
563 ctx->m_state->addBuffer(buffers[i]);
564 }
565}
566
keunyoungb85b2752013-03-08 12:28:03 -0800567void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
568{
569 GL2Encoder *ctx = (GL2Encoder *) self;
570 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
571 for (int i=0; i<n; i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800572 // Technically if the buffer is mapped, we should unmap it, but we won't
573 // use it anymore after this :)
keunyoungb85b2752013-03-08 12:28:03 -0800574 ctx->m_shared->deleteBufferData(buffers[i]);
bohub0f0cdf2014-11-06 18:08:07 -0800575 ctx->m_state->unBindBuffer(buffers[i]);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800576 ctx->m_state->removeBuffer(buffers[i]);
keunyoungb85b2752013-03-08 12:28:03 -0800577 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
578 }
579}
580
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700581static bool isValidVertexAttribIndex(void *self, GLuint indx)
582{
Lingfeng Yang07289902017-01-27 12:26:19 -0800583 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700584 GLint maxIndex;
585 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
586 return indx < maxIndex;
587}
588
Lingfeng Yang07289902017-01-27 12:26:19 -0800589#define VALIDATE_VERTEX_ATTRIB_INDEX(index) \
590 SET_ERROR_WITH_MESSAGE_IF( \
591 !isValidVertexAttribIndex(self, index), GL_INVALID_VALUE, \
592 GLESv2Validation::vertexAttribIndexRangeErrorMsg, (ctx, index)); \
593
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100594void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
keunyoungb85b2752013-03-08 12:28:03 -0800595{
596 GL2Encoder *ctx = (GL2Encoder *)self;
597 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -0800598 VALIDATE_VERTEX_ATTRIB_INDEX(indx);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700599 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800600 SET_ERROR_IF(!GLESv2Validation::vertexAttribType(ctx, type), GL_INVALID_ENUM);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700601 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800602 SET_ERROR_IF((type == GL_INT_2_10_10_10_REV ||
603 type == GL_UNSIGNED_INT_2_10_10_10_REV) &&
604 size != 4,
605 GL_INVALID_OPERATION);
606 ctx->m_state->setVertexAttribBinding(indx, indx);
607 ctx->m_state->setVertexAttribFormat(indx, size, type, normalized, 0, false);
608
609 GLsizei effectiveStride = stride;
610 if (stride == 0) {
611 effectiveStride = glSizeof(type) * size;
612 switch (type) {
613 case GL_INT_2_10_10_10_REV:
614 case GL_UNSIGNED_INT_2_10_10_10_REV:
615 effectiveStride /= 4;
616 break;
617 default:
618 break;
619 }
620 }
621
622 ctx->m_state->bindIndexedBuffer(0, indx, ctx->m_state->currentArrayVbo(), (uintptr_t)ptr, 0, stride, effectiveStride);
623
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800624 if (ctx->m_state->currentArrayVbo() != 0) {
625 ctx->glVertexAttribPointerOffset(ctx, indx, size, type, normalized, stride, (uintptr_t)ptr);
626 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800627 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && ptr, GL_INVALID_OPERATION);
628 // wait for client-array handler
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800629 }
keunyoungb85b2752013-03-08 12:28:03 -0800630}
631
632void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
633{
634 GL2Encoder *ctx = (GL2Encoder *) self;
635 assert(ctx->m_state != NULL);
636 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:
666 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
667 case GL_MAX_TEXTURE_IMAGE_UNITS:
Lingfeng Yang80a36332017-07-09 10:58:07 -0700668 ctx->safe_glGetIntegerv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800669 *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
670 break;
671
672 case GL_TEXTURE_BINDING_2D:
673 *ptr = state->getBoundTexture(GL_TEXTURE_2D);
674 break;
675 case GL_TEXTURE_BINDING_EXTERNAL_OES:
676 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
677 break;
678
Lingfeng Yangb0176982016-03-01 21:27:49 -0800679 case GL_MAX_VERTEX_ATTRIBS:
680 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700681 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangb0176982016-03-01 21:27:49 -0800682 ctx->m_state->setMaxVertexAttribs(*ptr);
Yahan Zhoua5c36842016-06-01 12:49:39 -0700683 }
684 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800685 case GL_MAX_VERTEX_ATTRIB_STRIDE:
686 if (ctx->m_max_vertexAttribStride != 0) {
687 *ptr = ctx->m_max_vertexAttribStride;
688 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700689 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800690 ctx->m_max_vertexAttribStride = *ptr;
691 }
692 break;
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800693 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
694 if (ctx->m_max_cubeMapTextureSize != 0) {
695 *ptr = ctx->m_max_cubeMapTextureSize;
696 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700697 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800698 ctx->m_max_cubeMapTextureSize = *ptr;
699 }
700 break;
701 case GL_MAX_RENDERBUFFER_SIZE:
702 if (ctx->m_max_renderBufferSize != 0) {
703 *ptr = ctx->m_max_renderBufferSize;
704 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700705 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800706 ctx->m_max_renderBufferSize = *ptr;
707 }
708 break;
709 case GL_MAX_TEXTURE_SIZE:
710 if (ctx->m_max_textureSize != 0) {
711 *ptr = ctx->m_max_textureSize;
712 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700713 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800714 ctx->m_max_textureSize = *ptr;
Lingfeng Yangb0176982016-03-01 21:27:49 -0800715 }
716 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800717 case GL_MAX_3D_TEXTURE_SIZE:
718 if (ctx->m_max_3d_textureSize != 0) {
719 *ptr = ctx->m_max_3d_textureSize;
720 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700721 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800722 ctx->m_max_3d_textureSize = *ptr;
723 }
724 break;
725 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
726 if (ctx->m_ssbo_offset_align != 0) {
727 *ptr = ctx->m_ssbo_offset_align;
728 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700729 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800730 ctx->m_ssbo_offset_align = *ptr;
731 }
732 break;
733 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
734 if (ctx->m_ubo_offset_align != 0) {
735 *ptr = ctx->m_ubo_offset_align;
736 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700737 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800738 ctx->m_ubo_offset_align = *ptr;
739 }
740 break;
741 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
742 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
743 case GL_MAX_SAMPLES:
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800744 case GL_MAX_COLOR_TEXTURE_SAMPLES:
745 case GL_MAX_INTEGER_SAMPLES:
746 case GL_MAX_DEPTH_TEXTURE_SAMPLES:
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800747 *ptr = 4;
748 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700749 // Checks for version-incompatible enums.
750 // Not allowed in vanilla ES 2.0.
751 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
752 case GL_MAX_UNIFORM_BUFFER_BINDINGS:
753 SET_ERROR_IF(ctx->majorVersion() < 3, GL_INVALID_ENUM);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700754 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700755 break;
756 case GL_MAX_COLOR_ATTACHMENTS:
757 case GL_MAX_DRAW_BUFFERS:
758 SET_ERROR_IF(ctx->majorVersion() < 3 &&
759 !ctx->hasExtension("GL_EXT_draw_buffers"), GL_INVALID_ENUM);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700760 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700761 break;
762 // Not allowed in ES 3.0.
763 case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
764 case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
765 case GL_MAX_VERTEX_ATTRIB_BINDINGS:
766 SET_ERROR_IF(ctx->majorVersion() < 3 ||
767 (ctx->majorVersion() == 3 &&
768 ctx->minorVersion() == 0), GL_INVALID_ENUM);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700769 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700770 break;
keunyoungb85b2752013-03-08 12:28:03 -0800771 default:
772 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700773 ctx->safe_glGetIntegerv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800774 }
775 break;
776 }
777}
778
779
780void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
781{
782 GL2Encoder *ctx = (GL2Encoder *)self;
783 assert(ctx->m_state != NULL);
784 GLClientState* state = ctx->m_state;
785
786 switch (param) {
787 case GL_NUM_SHADER_BINARY_FORMATS:
788 *ptr = 0;
789 break;
790 case GL_SHADER_BINARY_FORMATS:
791 // do nothing
792 break;
793
794 case GL_COMPRESSED_TEXTURE_FORMATS: {
795 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
796 if (ctx->m_num_compressedTextureFormats > 0 &&
797 compressedTextureFormats != NULL) {
798 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
799 ptr[i] = (GLfloat) compressedTextureFormats[i];
800 }
801 }
802 break;
803 }
804
805 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
806 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
807 case GL_MAX_TEXTURE_IMAGE_UNITS:
Lingfeng Yang80a36332017-07-09 10:58:07 -0700808 ctx->safe_glGetFloatv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800809 *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
810 break;
811
812 case GL_TEXTURE_BINDING_2D:
813 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
814 break;
815 case GL_TEXTURE_BINDING_EXTERNAL_OES:
816 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
817 break;
818
819 default:
820 if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700821 ctx->safe_glGetFloatv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800822 }
823 break;
824 }
825}
826
827
828void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
829{
830 GL2Encoder *ctx = (GL2Encoder *)self;
831 assert(ctx->m_state != NULL);
832 GLClientState* state = ctx->m_state;
833
834 switch (param) {
835 case GL_NUM_SHADER_BINARY_FORMATS:
836 *ptr = GL_FALSE;
837 break;
838 case GL_SHADER_BINARY_FORMATS:
839 // do nothing
840 break;
841
842 case GL_COMPRESSED_TEXTURE_FORMATS: {
843 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
844 if (ctx->m_num_compressedTextureFormats > 0 &&
845 compressedTextureFormats != NULL) {
846 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
847 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
848 }
849 }
850 break;
851 }
852
853 case GL_TEXTURE_BINDING_2D:
854 *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
855 break;
856 case GL_TEXTURE_BINDING_EXTERNAL_OES:
857 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
858 ? GL_TRUE : GL_FALSE;
859 break;
860
861 default:
862 if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700863 ctx->safe_glGetBooleanv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800864 }
bohu05101d22014-11-17 16:28:42 -0800865 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
keunyoungb85b2752013-03-08 12:28:03 -0800866 break;
867 }
868}
869
870
871void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
872{
873 GL2Encoder *ctx = (GL2Encoder *)self;
874 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -0800875 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800876 ctx->m_glEnableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800877 ctx->m_state->enable(index, 1);
878}
879
880void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
881{
882 GL2Encoder *ctx = (GL2Encoder *)self;
883 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -0800884 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800885 ctx->m_glDisableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -0800886 ctx->m_state->enable(index, 0);
887}
888
889
890void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
891{
892 GL2Encoder *ctx = (GL2Encoder *)self;
893 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700894 GLint maxIndex;
895 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
896 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800897
898 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
899 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
900 }
901}
902
903void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
904{
905 GL2Encoder *ctx = (GL2Encoder *)self;
906 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -0700907 GLint maxIndex;
908 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
909 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800910
911 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
912 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
913 }
914}
915
916void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
917{
918 GL2Encoder *ctx = (GL2Encoder *)self;
919 if (ctx->m_state == NULL) return;
Lingfeng Yang5e100432016-04-08 12:46:42 -0700920 GLint maxIndex;
921 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
922 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
923 SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100924 (void)pname;
925
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800926 *pointer = (GLvoid*)(ctx->m_state->getCurrAttributeBindingInfo(index).offset);
keunyoungb85b2752013-03-08 12:28:03 -0800927}
928
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700929void GL2Encoder::calcIndexRange(const void* indices,
930 GLenum type,
931 GLsizei count,
932 int* minIndex_out,
933 int* maxIndex_out) {
934 switch(type) {
935 case GL_BYTE:
936 case GL_UNSIGNED_BYTE:
937 GLUtils::minmaxExcept(
938 (unsigned char *)indices, count,
939 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800940 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned char>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700941 break;
942 case GL_SHORT:
943 case GL_UNSIGNED_SHORT:
944 GLUtils::minmaxExcept(
945 (unsigned short *)indices, count,
946 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800947 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned short>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700948 break;
949 case GL_INT:
950 case GL_UNSIGNED_INT:
951 GLUtils::minmaxExcept(
952 (unsigned int *)indices, count,
953 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800954 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned int>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700955 break;
956 default:
957 ALOGE("unsupported index buffer type %d\n", type);
958 }
959}
960
961void* GL2Encoder::recenterIndices(const void* src,
962 GLenum type,
963 GLsizei count,
964 int minIndex) {
965
966 void* adjustedIndices = (void*)src;
967
968 if (minIndex != 0) {
969 adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count);
970 switch(type) {
971 case GL_BYTE:
972 case GL_UNSIGNED_BYTE:
973 GLUtils::shiftIndicesExcept(
974 (unsigned char *)src,
975 (unsigned char *)adjustedIndices,
976 count, -minIndex,
977 m_primitiveRestartEnabled,
978 (unsigned char)m_primitiveRestartIndex);
979 break;
980 case GL_SHORT:
981 case GL_UNSIGNED_SHORT:
982 GLUtils::shiftIndicesExcept(
983 (unsigned short *)src,
984 (unsigned short *)adjustedIndices,
985 count, -minIndex,
986 m_primitiveRestartEnabled,
987 (unsigned short)m_primitiveRestartIndex);
988 break;
989 case GL_INT:
990 case GL_UNSIGNED_INT:
991 GLUtils::shiftIndicesExcept(
992 (unsigned int *)src,
993 (unsigned int *)adjustedIndices,
994 count, -minIndex,
995 m_primitiveRestartEnabled,
996 (unsigned int)m_primitiveRestartIndex);
997 break;
998 default:
999 ALOGE("unsupported index buffer type %d\n", type);
1000 }
1001 }
1002
1003 return adjustedIndices;
1004}
1005
1006void GL2Encoder::getBufferIndexRange(BufferData* buf,
1007 const void* dataWithOffset,
1008 GLenum type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001009 size_t count,
1010 size_t offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001011 int* minIndex_out,
1012 int* maxIndex_out) {
1013
1014 if (buf->m_indexRangeCache.findRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001015 type, offset, count,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001016 m_primitiveRestartEnabled,
1017 minIndex_out,
1018 maxIndex_out)) {
1019 return;
1020 }
1021
1022 calcIndexRange(dataWithOffset, type, count, minIndex_out, maxIndex_out);
1023
1024 buf->m_indexRangeCache.addRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001025 type, offset, count, m_primitiveRestartEnabled,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001026 *minIndex_out, *maxIndex_out);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001027
1028 ALOGV("%s: got range [%u %u] pr? %d", __FUNCTION__, *minIndex_out, *maxIndex_out, m_primitiveRestartEnabled);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001029}
keunyoungb85b2752013-03-08 12:28:03 -08001030
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001031// For detecting legacy usage of glVertexAttribPointer
1032void GL2Encoder::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) const {
1033 if (hasClientArrays) *hasClientArrays = false;
1034 if (hasVBOs) *hasVBOs = false;
1035
1036 for (int i = 0; i < m_state->nLocations(); i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001037 const GLClientState::VertexAttribState& state = m_state->getState(i);
1038 if (state.enabled) {
1039 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
1040 GLuint bufferObject = curr_binding.buffer;
1041 if (bufferObject == 0 && curr_binding.offset && hasClientArrays) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001042 *hasClientArrays = true;
1043 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001044 if (bufferObject != 0 && hasVBOs) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001045 *hasVBOs = true;
1046 }
1047 }
1048 }
1049}
1050
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001051void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count, bool hasClientArrays, GLsizei primcount)
keunyoungb85b2752013-03-08 12:28:03 -08001052{
1053 assert(m_state);
1054
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001055 GLuint currentVao = m_state->currentVertexArrayObject();
Lingfeng Yang398162b2016-05-26 14:18:33 -07001056 GLuint lastBoundVbo = m_state->currentArrayVbo();
keunyoungb85b2752013-03-08 12:28:03 -08001057 for (int i = 0; i < m_state->nLocations(); i++) {
1058 bool enableDirty;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001059 const GLClientState::VertexAttribState& state = m_state->getStateAndEnableDirty(i, &enableDirty);
keunyoungb85b2752013-03-08 12:28:03 -08001060
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001061 if (!enableDirty && !state.enabled) {
keunyoungb85b2752013-03-08 12:28:03 -08001062 continue;
1063 }
1064
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001065 if (state.enabled) {
1066 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
1067 GLuint bufferObject = curr_binding.buffer;
1068 if (hasClientArrays && lastBoundVbo != bufferObject) {
1069 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, bufferObject);
1070 lastBoundVbo = bufferObject;
Lingfeng Yang398162b2016-05-26 14:18:33 -07001071 }
keunyoungb85b2752013-03-08 12:28:03 -08001072
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001073 int divisor = curr_binding.divisor;
1074 int stride = curr_binding.stride;
1075 int effectiveStride = curr_binding.effectiveStride;
1076 uintptr_t offset = curr_binding.offset;
Lingfeng Yang4e5446b2017-02-15 08:44:21 -08001077
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001078 int firstIndex = effectiveStride * first;
Lingfeng Yang4e5446b2017-02-15 08:44:21 -08001079 if (firstIndex && divisor && !primcount) {
1080 // If firstIndex != 0 according to effectiveStride * first,
1081 // it needs to be adjusted if a divisor has been specified,
1082 // even if we are not in glDraw***Instanced.
1083 firstIndex = 0;
1084 }
keunyoungb85b2752013-03-08 12:28:03 -08001085
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001086 if (bufferObject == 0) {
1087 unsigned int datalen = state.elementSize * count;
1088 if (divisor && primcount) {
1089 ALOGV("%s: divisor for att %d: %d, w/ stride %d (effective stride %d) size %d type 0x%x) datalen %u",
1090 __FUNCTION__, i, divisor, state.stride, effectiveStride, state.elementSize, state.type, datalen);
1091 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
1092 datalen = state.elementSize * actual_count;
1093 ALOGV("%s: actual datalen %u", __FUNCTION__, datalen);
1094 }
1095 if (state.elementSize == 0) {
Yahan Zhou3f2f1b42016-12-01 13:49:44 -08001096 // The vertex attribute array is uninitialized. Abandon it.
1097 ALOGE("a vertex attribute array is uninitialized. Skipping corresponding vertex attribute.");
1098 this->m_glDisableVertexAttribArray_enc(this, i);
1099 continue;
1100 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001101 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang000cf4c2017-01-25 08:09:02 -08001102
1103 if (datalen && (!offset || !((unsigned char*)offset + firstIndex))) {
1104 ALOGD("%s: bad offset / len!!!!!", __FUNCTION__);
1105 continue;
1106 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001107 if (state.isInt) {
1108 this->glVertexAttribIPointerDataAEMU(this, i, state.size, state.type, stride, (unsigned char *)offset + firstIndex, datalen);
1109 } else {
1110 this->glVertexAttribPointerData(this, i, state.size, state.type, state.normalized, stride, (unsigned char *)offset + firstIndex, datalen);
1111 }
keunyoungb85b2752013-03-08 12:28:03 -08001112 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001113 const BufferData* buf = m_shared->getBufferData(bufferObject);
Yahan Zhou5507c042016-06-01 17:24:28 -07001114 // The following expression actually means bufLen = stride*count;
1115 // But the last element doesn't have to fill up the whole stride.
1116 // So it becomes the current form.
Lingfeng Yang5fe99012017-01-18 09:17:09 -08001117 unsigned int bufLen = effectiveStride * (count ? (count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001118 if (divisor && primcount) {
1119 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
Lingfeng Yang5fe99012017-01-18 09:17:09 -08001120 bufLen = effectiveStride * (actual_count ? (actual_count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001121 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001122 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001123 if (hasClientArrays) {
1124 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001125 if (state.isInt) {
1126 this->glVertexAttribIPointerOffsetAEMU(this, i, state.size, state.type, stride, offset + firstIndex);
1127 } else {
1128 this->glVertexAttribPointerOffset(this, i, state.size, state.type, state.normalized, stride, offset + firstIndex);
1129 }
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001130 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001131 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001132 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=%p", buf);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -08001133 if (buf) {
1134 ALOGE("Out of bounds vertex attribute info: "
1135 "clientArray? %d attribute %d vbo %u allocedBufferSize %u bufferDataSpecified? %d wantedStart %u wantedEnd %u",
Lingfeng Yangddfb4452018-09-24 17:26:07 -07001136 hasClientArrays, i, bufferObject, (unsigned int)buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -08001137 }
1138 m_glDisableVertexAttribArray_enc(this, i);
Yahan Zhou5507c042016-06-01 17:24:28 -07001139 }
keunyoungb85b2752013-03-08 12:28:03 -08001140 }
1141 } else {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001142 if (hasClientArrays) {
1143 this->m_glDisableVertexAttribArray_enc(this, i);
1144 }
keunyoungb85b2752013-03-08 12:28:03 -08001145 }
1146 }
Lingfeng Yang398162b2016-05-26 14:18:33 -07001147
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001148 if (hasClientArrays && lastBoundVbo != m_state->currentArrayVbo()) {
Lingfeng Yang398162b2016-05-26 14:18:33 -07001149 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
1150 }
keunyoungb85b2752013-03-08 12:28:03 -08001151}
1152
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001153void GL2Encoder::flushDrawCall() {
Lingfeng Yang1ebb33c2017-01-19 08:04:48 -08001154 // This used to be every other draw call, but
1155 // now that we are using real GPU buffers on host,
1156 // set this to every 200 draw calls
1157 // (tuned on z840 linux NVIDIA Quadro K2200)
1158 if (m_drawCallFlushCount % 200 == 0) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001159 m_stream->flush();
1160 }
1161 m_drawCallFlushCount++;
1162}
1163
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001164static bool isValidDrawMode(GLenum mode)
1165{
1166 bool retval = false;
1167 switch (mode) {
1168 case GL_POINTS:
1169 case GL_LINE_STRIP:
1170 case GL_LINE_LOOP:
1171 case GL_LINES:
1172 case GL_TRIANGLE_STRIP:
1173 case GL_TRIANGLE_FAN:
1174 case GL_TRIANGLES:
1175 retval = true;
1176 }
1177 return retval;
1178}
1179
keunyoungb85b2752013-03-08 12:28:03 -08001180void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
1181{
1182 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001183 assert(ctx->m_state != NULL);
1184 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1185 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhoud6217a52016-02-10 16:10:46 -08001186
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001187 bool has_client_vertex_arrays = false;
1188 bool has_indirect_arrays = false;
1189 ctx->getVBOUsage(&has_client_vertex_arrays,
1190 &has_indirect_arrays);
1191
1192 if (has_client_vertex_arrays ||
1193 (!has_client_vertex_arrays &&
1194 !has_indirect_arrays)) {
1195 ctx->sendVertexAttributes(first, count, true);
1196 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
1197 } else {
1198 ctx->sendVertexAttributes(0, count, false);
1199 ctx->m_glDrawArrays_enc(ctx, mode, first, count);
1200 }
keunyoungb85b2752013-03-08 12:28:03 -08001201}
1202
1203
1204void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
1205{
1206
1207 GL2Encoder *ctx = (GL2Encoder *)self;
1208 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001209 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1210 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -07001211 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 -08001212 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001213
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001214 bool has_client_vertex_arrays = false;
keunyoungb85b2752013-03-08 12:28:03 -08001215 bool has_indirect_arrays = false;
1216 int nLocations = ctx->m_state->nLocations();
Yahan Zhou5507c042016-06-01 17:24:28 -07001217 GLintptr offset = 0;
keunyoungb85b2752013-03-08 12:28:03 -08001218
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001219 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
keunyoungb85b2752013-03-08 12:28:03 -08001220
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001221 if (!has_client_vertex_arrays && !has_indirect_arrays) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001222 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -07001223 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
1224 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001225 }
1226
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001227 BufferData* buf = NULL;
Yahan Zhou5507c042016-06-01 17:24:28 -07001228 int minIndex = 0, maxIndex = 0;
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001229
1230 // For validation/immediate index array purposes,
1231 // we need the min/max vertex index of the index array.
1232 // If the VBO != 0, this may not be the first time we have
1233 // used this particular index buffer. getBufferIndexRange
1234 // can more quickly get min/max vertex index by
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001235 // caching previous results.
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001236 if (ctx->m_state->currentIndexVbo() != 0) {
1237 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1238 offset = (GLintptr)indices;
1239 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
1240 ctx->getBufferIndexRange(buf,
1241 indices,
1242 type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001243 (size_t)count,
1244 (size_t)offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001245 &minIndex, &maxIndex);
1246 } else {
1247 // In this case, the |indices| field holds a real
1248 // array, so calculate the indices now. They will
1249 // also be needed to know how much data to
1250 // transfer to host.
1251 ctx->calcIndexRange(indices,
1252 type,
1253 count,
1254 &minIndex,
1255 &maxIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -07001256 }
1257
Lingfeng Yang26e629a2018-10-13 20:00:12 -07001258 if (count == 0) return;
1259
keunyoungb85b2752013-03-08 12:28:03 -08001260 bool adjustIndices = true;
1261 if (ctx->m_state->currentIndexVbo() != 0) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001262 if (!has_client_vertex_arrays) {
1263 ctx->sendVertexAttributes(0, maxIndex + 1, false);
keunyoungb85b2752013-03-08 12:28:03 -08001264 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -07001265 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001266 ctx->flushDrawCall();
keunyoungb85b2752013-03-08 12:28:03 -08001267 adjustIndices = false;
1268 } else {
1269 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1270 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001271 }
1272 }
1273 if (adjustIndices) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001274 void *adjustedIndices =
1275 ctx->recenterIndices(indices,
1276 type,
1277 count,
1278 minIndex);
keunyoungb85b2752013-03-08 12:28:03 -08001279
keunyoungb85b2752013-03-08 12:28:03 -08001280 if (has_indirect_arrays || 1) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001281 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
keunyoungb85b2752013-03-08 12:28:03 -08001282 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
1283 count * glSizeof(type));
1284 // XXX - OPTIMIZATION (see the other else branch) should be implemented
1285 if(!has_indirect_arrays) {
1286 //ALOGD("unoptimized drawelements !!!\n");
1287 }
1288 } else {
1289 // we are all direct arrays and immidate mode index array -
1290 // rebuild the arrays and the index array;
1291 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
1292 }
1293 }
1294}
1295
1296
1297GLint * GL2Encoder::getCompressedTextureFormats()
1298{
1299 if (m_compressedTextureFormats == NULL) {
1300 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
1301 &m_num_compressedTextureFormats);
1302 if (m_num_compressedTextureFormats > 0) {
1303 // get number of texture formats;
1304 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
1305 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
1306 }
1307 }
1308 return m_compressedTextureFormats;
1309}
1310
1311// Replace uses of samplerExternalOES with sampler2D, recording the names of
1312// modified shaders in data. Also remove
1313// #extension GL_OES_EGL_image_external : require
1314// statements.
1315//
1316// This implementation assumes the input has already been pre-processed. If not,
1317// a few cases will be mishandled:
1318//
1319// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
1320// the following code:
1321// #if 1
1322// uniform sampler2D mySampler;
1323// #else
1324// uniform samplerExternalOES mySampler;
1325// #endif
1326//
1327// 2. Comments that look like sampler declarations will be incorrectly modified
1328// and recorded:
1329// // samplerExternalOES hahaFooledYou
1330//
1331// 3. However, GLSL ES does not have a concatentation operator, so things like
1332// this (valid in C) are invalid and not a problem:
1333// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
1334// SAMPLER(ExternalOES, mySampler);
1335//
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001336
1337static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
1338static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
1339static const char STR_DEFINE[] = "#define";
1340
1341static std::vector<std::string> getSamplerExternalAliases(char* str) {
1342 std::vector<std::string> res;
1343
1344 res.push_back(STR_SAMPLER_EXTERNAL_OES);
1345
1346 // -- capture #define x samplerExternalOES
1347 char* c = str;
1348 while ((c = strstr(c, STR_DEFINE))) {
1349 // Don't push it if samplerExternalOES is not even there.
1350 char* samplerExternalOES_next = strstr(c, STR_SAMPLER_EXTERNAL_OES);
1351 if (!samplerExternalOES_next) break;
1352
1353 bool prevIdent = false;
1354
1355 std::vector<std::string> idents;
1356 std::string curr;
1357
1358 while (*c != '\0') {
1359
1360 if (isspace(*c)) {
1361 if (prevIdent) {
1362 idents.push_back(curr);
1363 curr = "";
1364 }
1365 }
1366
1367 if (*c == '\n' || idents.size() == 3) break;
1368
1369 if (isalpha(*c) || *c == '_') {
1370 curr.push_back(*c);
1371 prevIdent = true;
1372 }
1373
1374 ++c;
1375 }
1376
1377 if (idents.size() != 3) continue;
1378
1379 const std::string& defineLhs = idents[1];
1380 const std::string& defineRhs = idents[2];
1381
1382 if (defineRhs == STR_SAMPLER_EXTERNAL_OES) {
1383 res.push_back(defineLhs);
1384 }
1385
1386 if (*c == '\0') break;
1387 }
1388
1389 return res;
1390}
1391
1392static bool replaceExternalSamplerUniformDefinition(char* str, const std::string& samplerExternalType, ShaderData* data) {
1393 // -- replace "samplerExternalOES" with "sampler2D" and record name
1394 char* c = str;
1395 while ((c = strstr(c, samplerExternalType.c_str()))) {
1396 // Make sure "samplerExternalOES" isn't a substring of a larger token
1397 if (c == str || !isspace(*(c-1))) {
1398 c++;
1399 continue;
1400 }
1401 char* sampler_start = c;
1402 c += samplerExternalType.size();
1403 if (!isspace(*c) && *c != '\0') {
1404 continue;
1405 }
1406
1407 // capture sampler name
1408 while (isspace(*c) && *c != '\0') {
1409 c++;
1410 }
1411 if (!isalpha(*c) && *c != '_') {
1412 // not an identifier
1413 return false;
1414 }
1415 char* name_start = c;
1416 do {
1417 c++;
1418 } while (isalnum(*c) || *c == '_');
Lingfeng Yang44209df2018-09-21 10:04:17 -07001419
1420 size_t len = (size_t)(c - name_start);
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001421 data->samplerExternalNames.push_back(
Lingfeng Yang44209df2018-09-21 10:04:17 -07001422 std::string(name_start, len));
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001423
1424 // We only need to perform a string replacement for the original
1425 // occurrence of samplerExternalOES if a #define was used.
1426 //
1427 // The important part was to record the name in
1428 // |data->samplerExternalNames|.
1429 if (samplerExternalType == STR_SAMPLER_EXTERNAL_OES) {
1430 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
1431 }
1432 }
1433
1434 return true;
1435}
1436
keunyoungb85b2752013-03-08 12:28:03 -08001437static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
1438{
1439 static const char STR_HASH_EXTENSION[] = "#extension";
1440 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
Lingfeng Yang3546c4d2018-04-10 12:34:30 -07001441 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3[] = "GL_OES_EGL_image_external_essl3";
keunyoungb85b2752013-03-08 12:28:03 -08001442
1443 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
1444 char* c = str;
1445 while ((c = strstr(c, STR_HASH_EXTENSION))) {
1446 char* start = c;
1447 c += sizeof(STR_HASH_EXTENSION)-1;
1448 while (isspace(*c) && *c != '\0') {
1449 c++;
1450 }
Lingfeng Yang3546c4d2018-04-10 12:34:30 -07001451
1452 bool hasBaseImageExternal =
1453 !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
1454 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL) - 1);
1455 bool hasEssl3ImageExternal =
1456 !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3,
1457 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3) - 1);
1458
1459 if (hasBaseImageExternal || hasEssl3ImageExternal)
keunyoungb85b2752013-03-08 12:28:03 -08001460 {
1461 // #extension statements are terminated by end of line
1462 c = start;
1463 while (*c != '\0' && *c != '\r' && *c != '\n') {
1464 *c++ = ' ';
1465 }
1466 }
1467 }
1468
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001469 std::vector<std::string> samplerExternalAliases =
1470 getSamplerExternalAliases(str);
keunyoungb85b2752013-03-08 12:28:03 -08001471
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001472 for (size_t i = 0; i < samplerExternalAliases.size(); i++) {
1473 if (!replaceExternalSamplerUniformDefinition(
1474 str, samplerExternalAliases[i], data))
keunyoungb85b2752013-03-08 12:28:03 -08001475 return false;
keunyoungb85b2752013-03-08 12:28:03 -08001476 }
1477
1478 return true;
1479}
1480
Bo Hu73568cd2015-01-20 16:29:50 -08001481void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
1482{
1483 GL2Encoder* ctx = (GL2Encoder*)self;
1484 // Although it is not supported, need to set proper error code.
1485 SET_ERROR_IF(1, GL_INVALID_ENUM);
1486}
1487
David 'Digit' Turner02fdb692014-10-30 18:07:56 +01001488void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -08001489{
1490 GL2Encoder* ctx = (GL2Encoder*)self;
1491 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001492 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(shader), GL_INVALID_VALUE);
Tina Zhang7a84f652014-12-04 12:37:30 +08001493 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
1494 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001495
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001496 // Track original sources---they may be translated in the backend
1497 std::vector<std::string> orig_sources;
1498 for (int i = 0; i < count; i++) {
1499 orig_sources.push_back(std::string((const char*)(string[i])));
1500 }
1501 shaderData->sources = orig_sources;
1502
keunyoungb85b2752013-03-08 12:28:03 -08001503 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
1504 char *str = new char[len + 1];
1505 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
1506
1507 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
1508 // Perhaps we can borrow Mesa's pre-processor?
1509
1510 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001511 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001512 ctx->setError(GL_OUT_OF_MEMORY);
1513 return;
1514 }
keunyoungb85b2752013-03-08 12:28:03 -08001515 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001516 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001517}
1518
1519void GL2Encoder::s_glFinish(void *self)
1520{
1521 GL2Encoder *ctx = (GL2Encoder *)self;
1522 ctx->glFinishRoundTrip(self);
1523}
1524
1525void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1526{
1527 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -08001528 bool isProgram = ctx->m_shared->isProgram(program);
1529 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
1530 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
1531
keunyoungb85b2752013-03-08 12:28:03 -08001532 ctx->m_glLinkProgram_enc(self, program);
1533
1534 GLint linkStatus = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07001535 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001536 if (!linkStatus) {
keunyoungb85b2752013-03-08 12:28:03 -08001537 return;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001538 }
keunyoungb85b2752013-03-08 12:28:03 -08001539
1540 //get number of active uniforms in the program
1541 GLint numUniforms=0;
1542 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
1543 ctx->m_shared->initProgramData(program,numUniforms);
1544
1545 //get the length of the longest uniform name
1546 GLint maxLength=0;
1547 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
1548
1549 GLint size;
1550 GLenum type;
1551 GLchar *name = new GLchar[maxLength+1];
1552 GLint location;
1553 //for each active uniform, get its size and starting location.
1554 for (GLint i=0 ; i<numUniforms ; ++i)
1555 {
1556 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1557 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1558 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1559 }
1560 ctx->m_shared->setupLocationShiftWAR(program);
1561
1562 delete[] name;
1563}
1564
1565void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1566{
1567 GL2Encoder *ctx = (GL2Encoder*)self;
1568 ctx->m_glDeleteProgram_enc(self, program);
1569
1570 ctx->m_shared->deleteProgramData(program);
1571}
1572
1573void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1574{
1575 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001576 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001577 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001578 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1579 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1580 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1581 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1582}
1583void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1584{
1585 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001586 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001587 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001588 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1589 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1590 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1591 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1592}
1593
1594GLuint GL2Encoder::s_glCreateProgram(void * self)
1595{
1596 GL2Encoder *ctx = (GL2Encoder*)self;
1597 GLuint program = ctx->m_glCreateProgram_enc(self);
1598 if (program!=0)
1599 ctx->m_shared->addProgramData(program);
1600 return program;
1601}
1602
1603GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1604{
1605 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001606 RET_AND_SET_ERROR_IF(!GLESv2Validation::shaderType(ctx, shaderType), GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001607 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1608 if (shader != 0) {
1609 if (!ctx->m_shared->addShaderData(shader)) {
1610 ctx->m_glDeleteShader_enc(self, shader);
1611 return 0;
1612 }
1613 }
1614 return shader;
1615}
1616
bohu56bf82f2014-10-17 15:35:48 -07001617void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1618 GLsizei* count, GLuint* shaders)
1619{
1620 GL2Encoder *ctx = (GL2Encoder*)self;
1621 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1622 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1623}
1624
1625void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1626 GLsizei* length, GLchar* source)
1627{
1628 GL2Encoder *ctx = (GL2Encoder*)self;
1629 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1630 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001631 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
1632 if (shaderData) {
1633 std::string returned;
1634 int curr_len = 0;
1635 for (int i = 0; i < shaderData->sources.size(); i++) {
1636 if (curr_len + shaderData->sources[i].size() < bufsize - 1) {
1637 returned += shaderData->sources[i];
1638 } else {
1639 returned += shaderData->sources[i].substr(0, bufsize - 1 - curr_len);
1640 break;
1641 }
1642 }
1643 memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize);
1644 }
bohu56bf82f2014-10-17 15:35:48 -07001645}
1646
1647void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1648 GLsizei* length, GLchar* infolog)
1649{
1650 GL2Encoder *ctx = (GL2Encoder*)self;
1651 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1652 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1653}
1654
1655void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1656 GLsizei* length, GLchar* infolog)
1657{
1658 GL2Encoder *ctx = (GL2Encoder*)self;
1659 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1660 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1661}
1662
keunyoungb85b2752013-03-08 12:28:03 -08001663void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1664{
1665 GL2Encoder *ctx = (GL2Encoder*)self;
1666 ctx->m_glDeleteShader_enc(self,shader);
1667 ctx->m_shared->unrefShaderData(shader);
1668}
1669
1670void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1671{
1672 GL2Encoder *ctx = (GL2Encoder*)self;
1673 ctx->m_glAttachShader_enc(self, program, shader);
1674 ctx->m_shared->attachShader(program, shader);
1675}
1676
1677void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1678{
1679 GL2Encoder *ctx = (GL2Encoder*)self;
1680 ctx->m_glDetachShader_enc(self, program, shader);
1681 ctx->m_shared->detachShader(program, shader);
1682}
1683
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001684int sArrIndexOfUniformExpr(const char* name, int* err) {
1685 *err = 0;
1686 int arrIndex = 0;
1687 int namelen = strlen(name);
1688 if (name[namelen-1] == ']') {
1689 const char *brace = strrchr(name,'[');
1690 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1691 *err = 1; return 0;
1692 }
1693 }
1694 return arrIndex;
1695}
1696
keunyoungb85b2752013-03-08 12:28:03 -08001697int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1698{
1699 if (!name) return -1;
1700
1701 GL2Encoder *ctx = (GL2Encoder*)self;
1702
1703 // if we need the uniform location WAR
1704 // parse array index from the end of the name string
1705 int arrIndex = 0;
1706 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1707 if (needLocationWAR) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001708 int err;
1709 arrIndex = sArrIndexOfUniformExpr(name, &err);
1710 if (err) return -1;
keunyoungb85b2752013-03-08 12:28:03 -08001711 }
1712
1713 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1714 if (hostLoc >= 0 && needLocationWAR) {
1715 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1716 }
1717 return hostLoc;
1718}
1719
1720bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1721{
1722 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1723 return false;
1724
1725 m_state->setActiveTextureUnit(texUnit);
1726
1727 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1728 if (newTarget != oldTarget) {
1729 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1730 m_state->disableTextureTarget(GL_TEXTURE_2D);
1731 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1732 } else {
1733 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1734 m_state->enableTextureTarget(GL_TEXTURE_2D);
1735 }
1736 m_glActiveTexture_enc(this, texUnit);
1737 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1738 m_state->getBoundTexture(newTarget));
1739 return true;
1740 }
1741
1742 return false;
1743}
1744
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001745void GL2Encoder::updateHostTexture2DBindingsFromProgramData(GLuint program) {
1746 GL2Encoder *ctx = this;
keunyoungb85b2752013-03-08 12:28:03 -08001747 GLClientState* state = ctx->m_state;
1748 GLSharedGroupPtr shared = ctx->m_shared;
1749
keunyoungb85b2752013-03-08 12:28:03 -08001750 GLenum origActiveTexture = state->getActiveTextureUnit();
1751 GLenum hostActiveTexture = origActiveTexture;
1752 GLint samplerIdx = -1;
1753 GLint samplerVal;
1754 GLenum samplerTarget;
1755 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1756 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1757 continue;
1758 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001759 samplerTarget))
keunyoungb85b2752013-03-08 12:28:03 -08001760 {
1761 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1762 }
1763 }
1764 state->setActiveTextureUnit(origActiveTexture);
1765 if (hostActiveTexture != origActiveTexture) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001766 ctx->m_glActiveTexture_enc(ctx, origActiveTexture);
keunyoungb85b2752013-03-08 12:28:03 -08001767 }
1768}
1769
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001770void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1771{
1772 GL2Encoder *ctx = (GL2Encoder*)self;
1773 GLSharedGroupPtr shared = ctx->m_shared;
1774
1775 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
1776 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1777
1778 ctx->m_glUseProgram_enc(self, program);
1779 ctx->m_state->setCurrentProgram(program);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001780 ctx->m_state->setCurrentShaderProgram(program);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001781
1782 ctx->updateHostTexture2DBindingsFromProgramData(program);
1783}
1784
keunyoungb85b2752013-03-08 12:28:03 -08001785void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1786{
1787 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001788 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001789 ctx->m_glUniform1f_enc(self, hostLoc, x);
1790}
1791
1792void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1793{
1794 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001795 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001796 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1797}
1798
1799void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1800{
1801 GL2Encoder *ctx = (GL2Encoder*)self;
1802 GLClientState* state = ctx->m_state;
1803 GLSharedGroupPtr shared = ctx->m_shared;
1804
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001805 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001806 ctx->m_glUniform1i_enc(self, hostLoc, x);
1807
1808 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001809 if (shared->setSamplerUniform(state->currentShaderProgram(), location, x, &target)) {
keunyoungb85b2752013-03-08 12:28:03 -08001810 GLenum origActiveTexture = state->getActiveTextureUnit();
1811 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1812 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1813 }
1814 state->setActiveTextureUnit(origActiveTexture);
1815 }
1816}
1817
1818void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1819{
1820 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001821 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001822 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1823}
1824
1825void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1826{
1827 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001828 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001829 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1830}
1831
1832void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1833{
1834 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001835 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001836 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1837}
1838
1839void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1840{
1841 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001842 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001843 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1844}
1845
1846void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1847{
1848 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001849 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001850 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1851}
1852
1853void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1854{
1855 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001856 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001857 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1858}
1859
1860void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1861{
1862 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001863 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001864 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1865}
1866
1867void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1868{
1869 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001870 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001871 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1872}
1873
1874void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1875{
1876 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001877 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001878 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1879}
1880
1881void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1882{
1883 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001884 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001885 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1886}
1887
1888void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1889{
1890 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001891 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001892 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1893}
1894
1895void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1896{
1897 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001898 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001899 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1900}
1901
1902void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1903{
1904 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001905 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001906 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1907}
1908
1909void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1910{
1911 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001912 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001913 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1914}
1915
1916void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1917{
1918 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001919 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001920 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1921}
1922
1923void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1924{
1925 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001926 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001927 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1928}
1929
1930void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1931{
1932 GL2Encoder* ctx = (GL2Encoder*)self;
1933 GLClientState* state = ctx->m_state;
1934 GLenum err;
1935
1936 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1937
1938 ctx->m_glActiveTexture_enc(ctx, texture);
1939}
1940
1941void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1942{
1943 GL2Encoder* ctx = (GL2Encoder*)self;
1944 GLClientState* state = ctx->m_state;
1945 GLenum err;
1946 GLboolean firstUse;
1947
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001948 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -08001949 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1950
1951 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1952 ctx->m_glBindTexture_enc(ctx, target, texture);
1953 return;
1954 }
1955
1956 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1957
1958 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1959 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1960 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1961 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1962 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1963 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1964 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1965 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1966
1967 if (target != priorityTarget) {
1968 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1969 state->getBoundTexture(GL_TEXTURE_2D));
1970 }
1971 }
1972
1973 if (target == priorityTarget) {
1974 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1975 }
1976}
1977
1978void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1979{
1980 GL2Encoder* ctx = (GL2Encoder*)self;
1981 GLClientState* state = ctx->m_state;
1982
1983 state->deleteTextures(n, textures);
1984 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1985}
1986
1987void GL2Encoder::s_glGetTexParameterfv(void* self,
1988 GLenum target, GLenum pname, GLfloat* params)
1989{
1990 GL2Encoder* ctx = (GL2Encoder*)self;
1991 const GLClientState* state = ctx->m_state;
1992
1993 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1994 ctx->override2DTextureTarget(target);
1995 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001996 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001997 } else {
1998 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1999 }
2000}
2001
2002void GL2Encoder::s_glGetTexParameteriv(void* self,
2003 GLenum target, GLenum pname, GLint* params)
2004{
2005 GL2Encoder* ctx = (GL2Encoder*)self;
2006 const GLClientState* state = ctx->m_state;
2007
2008 switch (pname) {
2009 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
2010 *params = 1;
2011 break;
2012
2013 default:
2014 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2015 ctx->override2DTextureTarget(target);
2016 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002017 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002018 } else {
2019 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
2020 }
2021 break;
2022 }
2023}
2024
2025static bool isValidTextureExternalParam(GLenum pname, GLenum param)
2026{
2027 switch (pname) {
2028 case GL_TEXTURE_MIN_FILTER:
2029 case GL_TEXTURE_MAG_FILTER:
2030 return param == GL_NEAREST || param == GL_LINEAR;
2031
2032 case GL_TEXTURE_WRAP_S:
2033 case GL_TEXTURE_WRAP_T:
2034 return param == GL_CLAMP_TO_EDGE;
2035
2036 default:
2037 return true;
2038 }
2039}
2040
2041void GL2Encoder::s_glTexParameterf(void* self,
2042 GLenum target, GLenum pname, GLfloat param)
2043{
2044 GL2Encoder* ctx = (GL2Encoder*)self;
2045 const GLClientState* state = ctx->m_state;
2046
2047 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2048 !isValidTextureExternalParam(pname, (GLenum)param)),
2049 GL_INVALID_ENUM);
2050
2051 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2052 ctx->override2DTextureTarget(target);
2053 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002054 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002055 } else {
2056 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
2057 }
2058}
2059
2060void GL2Encoder::s_glTexParameterfv(void* self,
2061 GLenum target, GLenum pname, const GLfloat* params)
2062{
2063 GL2Encoder* ctx = (GL2Encoder*)self;
2064 const GLClientState* state = ctx->m_state;
2065
2066 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2067 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2068 GL_INVALID_ENUM);
2069
2070 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2071 ctx->override2DTextureTarget(target);
2072 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002073 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002074 } else {
2075 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
2076 }
2077}
2078
2079void GL2Encoder::s_glTexParameteri(void* self,
2080 GLenum target, GLenum pname, GLint param)
2081{
2082 GL2Encoder* ctx = (GL2Encoder*)self;
2083 const GLClientState* state = ctx->m_state;
2084
2085 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2086 !isValidTextureExternalParam(pname, (GLenum)param)),
2087 GL_INVALID_ENUM);
2088
2089 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2090 ctx->override2DTextureTarget(target);
2091 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002092 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002093 } else {
2094 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
2095 }
2096}
2097
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002098static int ilog2(uint32_t x) {
2099 int p = 0;
2100 while ((1 << p) < x)
2101 p++;
2102 return p;
2103}
2104
bohu26a92982014-11-25 16:50:37 -08002105void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
2106 GLint internalformat, GLsizei width, GLsizei height, GLint border,
2107 GLenum format, GLenum type, const GLvoid* pixels)
2108{
2109 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07002110 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002111
2112 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2113 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2114 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2115 // If unpack buffer is nonzero, verify unmapped state.
2116 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2117
2118 GLint max_texture_size;
2119 GLint max_cube_map_texture_size;
2120 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2121 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2122 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2123 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2124 SET_ERROR_IF((target == GL_TEXTURE_CUBE_MAP) &&
2125 (level > ilog2(max_cube_map_texture_size)), GL_INVALID_VALUE);
2126 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2127 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2128 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2129 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && width > max_cube_map_texture_size, GL_INVALID_VALUE);
2130 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && height > max_cube_map_texture_size, GL_INVALID_VALUE);
2131 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
2132 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2133 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2134 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2135 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 0) >
2136 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2137 GL_INVALID_OPERATION);
2138 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2139 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2140 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2141 glSizeof(type)),
2142 GL_INVALID_OPERATION);
2143 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2144 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2145 ((uintptr_t)pixels % glSizeof(type)),
2146 GL_INVALID_OPERATION);
2147 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
2148
2149 GLenum stateTarget = target;
2150 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2151 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2152 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2153 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2154 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2155 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2156 stateTarget = GL_TEXTURE_CUBE_MAP;
2157
2158 state->setBoundTextureInternalFormat(stateTarget, internalformat);
2159 state->setBoundTextureFormat(stateTarget, format);
2160 state->setBoundTextureType(stateTarget, type);
2161 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2162
bohu26a92982014-11-25 16:50:37 -08002163 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2164 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002165 }
Lingfeng Yang69066602016-04-12 09:29:11 -07002166
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002167 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2168 ctx->glTexImage2DOffsetAEMU(
2169 ctx, target, level, internalformat,
2170 width, height, border,
2171 format, type, (uintptr_t)pixels);
bohu26a92982014-11-25 16:50:37 -08002172 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002173 ctx->m_glTexImage2D_enc(
2174 ctx, target, level, internalformat,
2175 width, height, border,
2176 format, type, pixels);
2177 }
2178
2179 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2180 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08002181 }
2182}
2183
Yahan Zhou2a208292016-06-22 15:36:04 -07002184void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
2185 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
2186 GLenum type, const GLvoid* pixels)
2187{
2188 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002189 GLClientState* state = ctx->m_state;
2190
2191 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2192 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2193 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2194 // If unpack buffer is nonzero, verify unmapped state.
2195 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2196
2197 GLint max_texture_size;
2198 GLint max_cube_map_texture_size;
2199 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2200 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2201 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2202 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2203 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) &&
2204 level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2205 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2206 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2207
2208 GLuint tex = state->getBoundTexture(target);
2209 GLsizei neededWidth = xoffset + width;
2210 GLsizei neededHeight = yoffset + height;
2211 GLsizei neededDepth = 1;
2212
2213 if (tex && !state->queryTexEGLImageBacked(tex)) {
2214 SET_ERROR_IF(
2215 (neededWidth > state->queryTexWidth(level, tex) ||
2216 neededHeight > state->queryTexHeight(level, tex) ||
2217 neededDepth > state->queryTexDepth(level, tex)),
2218 GL_INVALID_VALUE);
2219 }
2220
2221 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2222 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2223 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2224 (state->pboNeededDataSize(width, height, 1, format, type, 0) >
2225 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2226 GL_INVALID_OPERATION);
2227 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2228 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2229 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2230 glSizeof(type)),
2231 GL_INVALID_OPERATION);
2232 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !pixels, GL_INVALID_OPERATION);
Yahan Zhou2a208292016-06-22 15:36:04 -07002233
2234 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2235 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002236 }
2237
2238 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2239 ctx->glTexSubImage2DOffsetAEMU(
2240 ctx, target, level,
2241 xoffset, yoffset, width, height,
2242 format, type, (uintptr_t)pixels);
Yahan Zhou2a208292016-06-22 15:36:04 -07002243 } else {
2244 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
2245 height, format, type, pixels);
2246 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002247
2248 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2249 ctx->restore2DTextureTarget(target);
2250 }
Yahan Zhou2a208292016-06-22 15:36:04 -07002251}
bohu26a92982014-11-25 16:50:37 -08002252
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002253void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
2254 GLenum internalformat, GLint x, GLint y,
2255 GLsizei width, GLsizei height, GLint border)
2256{
2257 GL2Encoder* ctx = (GL2Encoder*)self;
2258 GLClientState* state = ctx->m_state;
2259
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002260 SET_ERROR_IF(ctx->glCheckFramebufferStatus(ctx, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
2261 GL_INVALID_FRAMEBUFFER_OPERATION);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002262 // This is needed to work around underlying OpenGL drivers
2263 // (such as those feeding some some AMD GPUs) that expect
2264 // positive components of cube maps to be defined _before_
2265 // the negative components (otherwise a segfault occurs).
2266 GLenum extraTarget =
2267 state->copyTexImageLuminanceCubeMapAMDWorkaround
2268 (target, level, internalformat);
2269
2270 if (extraTarget) {
2271 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
2272 x, y, width, height, border);
2273 }
2274
2275 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
2276 x, y, width, height, border);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002277
2278 state->setBoundTextureInternalFormat(target, internalformat);
2279 state->setBoundTextureDims(target, level, width, height, 1);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002280}
2281
keunyoungb85b2752013-03-08 12:28:03 -08002282void GL2Encoder::s_glTexParameteriv(void* self,
2283 GLenum target, GLenum pname, const GLint* params)
2284{
2285 GL2Encoder* ctx = (GL2Encoder*)self;
2286 const GLClientState* state = ctx->m_state;
2287
2288 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2289 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2290 GL_INVALID_ENUM);
2291
2292 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2293 ctx->override2DTextureTarget(target);
2294 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002295 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002296 } else {
2297 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
2298 }
2299}
2300
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002301bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
2302 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
2303 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2304}
2305
keunyoungb85b2752013-03-08 12:28:03 -08002306void GL2Encoder::override2DTextureTarget(GLenum target)
2307{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002308 if (texture2DNeedsOverride(target)) {
2309 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2310 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08002311 }
2312}
2313
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002314void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08002315{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002316 if (texture2DNeedsOverride(target)) {
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002317 GLuint priorityEnabledBoundTexture =
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002318 m_state->getBoundTexture(
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002319 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D));
2320 GLuint texture2DBoundTexture =
2321 m_state->getBoundTexture(GL_TEXTURE_2D);
2322 if (!priorityEnabledBoundTexture) {
2323 m_glBindTexture_enc(this, GL_TEXTURE_2D, texture2DBoundTexture);
2324 } else {
2325 m_glBindTexture_enc(this, GL_TEXTURE_2D, priorityEnabledBoundTexture);
2326 }
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002327 }
keunyoungb85b2752013-03-08 12:28:03 -08002328}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002329
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002330void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2331 m_state->setBoundEGLImage(target, eglImage);
2332}
2333
2334
2335GLuint GL2Encoder::boundBuffer(GLenum target) const {
2336 return m_state->getBuffer(target);
2337}
2338
2339BufferData* GL2Encoder::getBufferData(GLenum target) const {
2340 GLuint bufferId = m_state->getBuffer(target);
2341 if (!bufferId) return NULL;
2342 return m_shared->getBufferData(bufferId);
2343}
2344
2345BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2346 if (!bufferId) return NULL;
2347 return m_shared->getBufferData(bufferId);
2348}
2349
2350bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2351 return m_shared->getBufferData(buffer)->m_mapped;
2352}
2353
2354bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2355 BufferData* buf = getBufferData(target);
2356 if (!buf) return false;
2357 return buf->m_mapped;
2358}
2359
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002360void GL2Encoder::s_glGenRenderbuffers(void* self,
2361 GLsizei n, GLuint* renderbuffers) {
2362 GL2Encoder* ctx = (GL2Encoder*)self;
2363 GLClientState* state = ctx->m_state;
2364
2365 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2366
2367 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2368 state->addRenderbuffers(n, renderbuffers);
2369}
2370
2371void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2372 GLsizei n, const GLuint* renderbuffers) {
2373 GL2Encoder* ctx = (GL2Encoder*)self;
2374 GLClientState* state = ctx->m_state;
2375
2376 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2377
2378 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002379
2380 // Nope, lets just leak those for now.
2381 // The spec has an *amazingly* convoluted set of conditions for when
2382 // render buffers are actually deleted:
2383 // 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.
2384 //
2385 // 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***
2386 //
2387 // So, just detach this one from the bound FBO, and ignore the rest.
2388 for (int i = 0; i < n; i++) {
2389 state->detachRbo(renderbuffers[i]);
2390 }
2391 // state->removeRenderbuffers(n, renderbuffers);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002392}
2393
2394void GL2Encoder::s_glBindRenderbuffer(void* self,
2395 GLenum target, GLuint renderbuffer) {
2396 GL2Encoder* ctx = (GL2Encoder*)self;
2397 GLClientState* state = ctx->m_state;
2398
2399 SET_ERROR_IF((target != GL_RENDERBUFFER),
2400 GL_INVALID_ENUM);
2401
2402 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2403 state->bindRenderbuffer(target, renderbuffer);
2404}
2405
Lingfeng Yang69066602016-04-12 09:29:11 -07002406void GL2Encoder::s_glRenderbufferStorage(void* self,
2407 GLenum target, GLenum internalformat,
2408 GLsizei width, GLsizei height) {
2409 GL2Encoder* ctx = (GL2Encoder*) self;
2410 GLClientState* state = ctx->m_state;
2411
2412 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002413 SET_ERROR_IF(
2414 !GLESv2Validation::rboFormat(ctx, internalformat),
2415 GL_INVALID_ENUM);
Lingfeng Yang69066602016-04-12 09:29:11 -07002416
2417 state->setBoundRenderbufferFormat(internalformat);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002418 state->setBoundRenderbufferSamples(0);
2419
Lingfeng Yang69066602016-04-12 09:29:11 -07002420 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
2421 width, height);
2422}
2423
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002424void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
2425 GLenum target, GLenum attachment,
2426 GLenum renderbuffertarget, GLuint renderbuffer) {
2427 GL2Encoder* ctx = (GL2Encoder*)self;
2428 GLClientState* state = ctx->m_state;
2429
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002430 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2431 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2432 state->attachRbo(target, attachment, renderbuffer);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002433
2434 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
2435}
2436
2437void GL2Encoder::s_glGenFramebuffers(void* self,
2438 GLsizei n, GLuint* framebuffers) {
2439 GL2Encoder* ctx = (GL2Encoder*)self;
2440 GLClientState* state = ctx->m_state;
2441
2442 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2443
2444 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2445 state->addFramebuffers(n, framebuffers);
2446}
2447
2448void GL2Encoder::s_glDeleteFramebuffers(void* self,
2449 GLsizei n, const GLuint* framebuffers) {
2450 GL2Encoder* ctx = (GL2Encoder*)self;
2451 GLClientState* state = ctx->m_state;
2452
2453 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2454
2455 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2456 state->removeFramebuffers(n, framebuffers);
2457}
2458
2459void GL2Encoder::s_glBindFramebuffer(void* self,
2460 GLenum target, GLuint framebuffer) {
2461 GL2Encoder* ctx = (GL2Encoder*)self;
2462 GLClientState* state = ctx->m_state;
2463
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002464 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002465
2466 state->bindFramebuffer(target, framebuffer);
2467
2468 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
2469}
2470
2471void GL2Encoder::s_glFramebufferTexture2D(void* self,
2472 GLenum target, GLenum attachment,
2473 GLenum textarget, GLuint texture, GLint level) {
2474 GL2Encoder* ctx = (GL2Encoder*)self;
2475 GLClientState* state = ctx->m_state;
2476
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002477 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2478 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2479 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002480
2481 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
2482}
2483
2484void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2485 GLenum target, GLenum attachment,
2486 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2487 GL2Encoder* ctx = (GL2Encoder*)self;
2488 GLClientState* state = ctx->m_state;
2489
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002490 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002491
2492 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2493}
2494
2495void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2496 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2497 GL2Encoder* ctx = (GL2Encoder*)self;
2498 const GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002499 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2500 SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2501 pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE &&
2502 !state->attachmentHasObject(target, attachment),
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002503 GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002504 SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL ||
2505 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE ||
2506 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) &&
2507 (!state->attachmentHasObject(target, attachment) ||
2508 state->getBoundFramebufferAttachmentType(target, attachment) !=
2509 FBO_ATTACHMENT_TEXTURE),
2510 !state->attachmentHasObject(target, attachment) ?
2511 GL_INVALID_OPERATION : GL_INVALID_ENUM);
2512 SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2513 pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2514 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
2515 state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
2516 GL_INVALID_OPERATION);
2517 SET_ERROR_IF(state->boundFramebuffer(target) &&
2518 (attachment == GL_BACK ||
2519 attachment == GL_FRONT),
2520 GL_INVALID_OPERATION);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002521 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
2522}
Lingfeng Yang69066602016-04-12 09:29:11 -07002523
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002524bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state,
Lingfeng Yang69066602016-04-12 09:29:11 -07002525 GLenum attachment) const {
2526 FboFormatInfo fbo_format_info;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002527 state->getBoundFramebufferFormat(target, attachment, &fbo_format_info);
Lingfeng Yang69066602016-04-12 09:29:11 -07002528
2529 bool res;
2530 switch (fbo_format_info.type) {
2531 case FBO_ATTACHMENT_RENDERBUFFER:
2532 switch (fbo_format_info.rb_format) {
2533 case GL_R16F:
2534 case GL_RG16F:
Lingfeng Yang69066602016-04-12 09:29:11 -07002535 case GL_RGBA16F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002536 case GL_R32F:
2537 case GL_RG32F:
2538 case GL_RGBA32F:
2539 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002540 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002541 break;
2542 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002543 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang69066602016-04-12 09:29:11 -07002544 break;
2545 case GL_STENCIL_INDEX8:
2546 if (attachment == GL_STENCIL_ATTACHMENT) {
2547 res = true;
2548 } else {
2549 res = false;
2550 }
2551 break;
2552 default:
2553 res = true;
2554 }
2555 break;
2556 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002557 switch (fbo_format_info.tex_internalformat) {
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002558 case GL_R16F:
2559 case GL_RG16F:
2560 case GL_RGBA16F:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002561 case GL_R32F:
2562 case GL_RG32F:
2563 case GL_RGBA32F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002564 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002565 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002566 break;
2567 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002568 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002569 break;
2570 case GL_RED:
2571 case GL_RG:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002572 case GL_SRGB8:
2573 case GL_RGB32UI:
2574 case GL_RGB16UI:
2575 case GL_RGB8UI:
2576 case GL_RGB32I:
2577 case GL_RGB16I:
2578 case GL_RGB8I:
2579 case GL_R8_SNORM:
2580 case GL_RG8_SNORM:
2581 case GL_RGB8_SNORM:
2582 case GL_RGBA8_SNORM:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002583 res = false;
2584 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07002585 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002586 case GL_RGB:
2587 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07002588 switch (fbo_format_info.tex_type) {
2589 case GL_FLOAT:
2590 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002591 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002592 case GL_UNSIGNED_INT_2_10_10_10_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07002593 res = false;
2594 break;
2595 default:
2596 res = true;
2597 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002598 break;
2599 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07002600 res = true;
2601 }
2602 break;
2603 case FBO_ATTACHMENT_NONE:
2604 res = true;
2605 break;
2606 default:
2607 res = true;
2608 }
2609 return res;
2610}
2611
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002612bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const {
2613 bool res = true;
2614
2615 for (int i = 0; i < state->getMaxColorAttachments(); i++) {
2616 res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i));
2617 }
2618
2619 res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT);
2620 res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT);
2621
2622 return res;
2623}
2624
Lingfeng Yang69066602016-04-12 09:29:11 -07002625GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
2626 GL2Encoder* ctx = (GL2Encoder*)self;
2627 GLClientState* state = ctx->m_state;
2628
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002629 bool fboCompleteByCodec =
2630 ctx->checkFramebufferCompleteness(target, state);
2631
2632 if (!fboCompleteByCodec) {
2633 state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
Lingfeng Yang69066602016-04-12 09:29:11 -07002634 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2635 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002636 // double check with underlying opengl to avoid craziness.
Lingfeng Yang69066602016-04-12 09:29:11 -07002637 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002638 state->setCheckFramebufferStatus(target, host_checkstatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002639 if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE;
Lingfeng Yang69066602016-04-12 09:29:11 -07002640 return host_checkstatus;
2641 }
2642}
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002643
2644void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2645 GL2Encoder* ctx = (GL2Encoder*)self;
2646 GLClientState* state = ctx->m_state;
2647 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2648
2649 ctx->m_glGenVertexArrays_enc(self, n, arrays);
2650 for (int i = 0; i < n; i++) {
2651 ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2652 }
2653 state->addVertexArrayObjects(n, arrays);
2654}
2655
2656void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2657 GL2Encoder* ctx = (GL2Encoder*)self;
2658 GLClientState* state = ctx->m_state;
2659 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2660
2661 ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2662 for (int i = 0; i < n; i++) {
2663 ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2664 }
2665 state->removeVertexArrayObjects(n, arrays);
2666}
2667
2668void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2669 ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2670 GL2Encoder* ctx = (GL2Encoder*)self;
2671 GLClientState* state = ctx->m_state;
2672 SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2673 ctx->m_glBindVertexArray_enc(self, array);
2674 state->setVertexArrayObject(array);
2675}
2676
Lingfeng Yangfb3d2bb2017-09-07 15:02:04 -07002677void* GL2Encoder::s_glMapBufferOES(void* self, GLenum target, GLenum access) {
2678 GL2Encoder* ctx = (GL2Encoder*)self;
2679
2680 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2681
2682 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2683
2684 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2685
2686 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2687 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2688
2689 return ctx->glMapBufferRange(ctx, target, 0, buf->m_size, access);
2690}
2691
2692GLboolean GL2Encoder::s_glUnmapBufferOES(void* self, GLenum target) {
2693 GL2Encoder* ctx = (GL2Encoder*)self;
2694
2695 return ctx->glUnmapBuffer(ctx, target);
2696}
2697
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002698void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2699 GL2Encoder* ctx = (GL2Encoder*)self;
2700 GLClientState* state = ctx->m_state;
2701
2702 // begin validation (lots)
2703
2704 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2705
2706 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2707
2708 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2709
2710 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2711 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2712
2713 GLsizeiptr bufferDataSize = buf->m_size;
2714
2715 RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2716 RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2717 RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2718 RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2719
2720 RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2721 RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2722 RET_AND_SET_ERROR_IF(
2723 (access & GL_MAP_READ_BIT) &&
2724 ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2725 (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2726 (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2727 (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2728
2729 // end validation; actually do stuff now
2730
2731 buf->m_mapped = true;
2732 buf->m_mappedAccess = access;
2733 buf->m_mappedOffset = offset;
2734 buf->m_mappedLength = length;
2735
2736 char* todo = (char*)buf->m_fixedBuffer.ptr() + offset;
2737 ctx->glMapBufferRangeAEMU(
2738 ctx, target,
2739 offset, length,
2740 access,
2741 todo);
2742
2743 return todo;
2744}
2745
2746GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
2747 GL2Encoder* ctx = (GL2Encoder*)self;
2748 GLClientState* state = ctx->m_state;
2749
2750 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
2751
2752 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2753
2754 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
2755
2756 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2757 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
2758 RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
2759
Lingfeng Yang423129e2017-01-18 09:23:12 -08002760 if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
2761 // invalide index range cache here
2762 if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) {
2763 buf->m_indexRangeCache.invalidateRange(0, buf->m_size);
2764 } else {
2765 buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength);
2766 }
2767 }
2768
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002769 GLboolean host_res = GL_TRUE;
2770
2771 ctx->glUnmapBufferAEMU(
2772 ctx, target,
2773 buf->m_mappedOffset,
2774 buf->m_mappedLength,
2775 buf->m_mappedAccess,
2776 (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
2777 &host_res);
2778
2779 buf->m_mapped = false;
2780 buf->m_mappedAccess = 0;
2781 buf->m_mappedOffset = 0;
2782 buf->m_mappedLength = 0;
2783
2784 return host_res;
2785}
2786
2787void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
2788 GL2Encoder* ctx = (GL2Encoder*)self;
2789 GLClientState* state = ctx->m_state;
2790
2791 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2792
2793 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2794 SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
2795
2796 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2797 SET_ERROR_IF(!buf, GL_INVALID_VALUE);
2798 SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
2799 SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
2800
2801 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
2802 SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
2803 SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
2804
2805 GLintptr totalOffset = buf->m_mappedOffset + offset;
Lingfeng Yang423129e2017-01-18 09:23:12 -08002806
2807 buf->m_indexRangeCache.invalidateRange(totalOffset, length);
2808
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002809 ctx->glFlushMappedBufferRangeAEMU(
2810 ctx, target,
2811 totalOffset,
2812 length,
2813 buf->m_mappedAccess,
2814 (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
2815}
2816
2817void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
2818 GL2Encoder* ctx = (GL2Encoder*)self;
2819 GLClientState* state = ctx->m_state;
2820
2821 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2822 // Filter compressed formats support.
2823 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
2824 // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
2825 GLint max_texture_size;
2826 GLint max_cube_map_texture_size;
2827 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2828 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2829 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2830 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2831 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2832 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2833 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2834 SET_ERROR_IF(border, GL_INVALID_VALUE);
2835 // If unpack buffer is nonzero, verify unmapped state.
2836 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2837 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2838 // If unpack buffer is nonzero, verify buffer data fits.
2839 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2840 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2841 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2842 GL_INVALID_OPERATION);
2843 // TODO: Fix:
2844 // If |imageSize| is inconsistent with compressed dimensions.
2845 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
2846
2847 GLenum stateTarget = target;
2848 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2849 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2850 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2851 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2852 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2853 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2854 stateTarget = GL_TEXTURE_CUBE_MAP;
2855 state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
2856 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2857
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002858 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2859 ctx->override2DTextureTarget(target);
2860 }
2861
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002862 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2863 ctx->glCompressedTexImage2DOffsetAEMU(
2864 ctx, target, level, internalformat,
2865 width, height, border,
2866 imageSize, (uintptr_t)data);
2867 } else {
2868 ctx->m_glCompressedTexImage2D_enc(
2869 ctx, target, level, internalformat,
2870 width, height, border,
2871 imageSize, data);
2872 }
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002873
2874 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2875 ctx->restore2DTextureTarget(target);
2876 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002877}
2878
2879void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
2880 GL2Encoder* ctx = (GL2Encoder*)self;
2881 GLClientState* state = ctx->m_state;
2882
2883 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2884 // If unpack buffer is nonzero, verify unmapped state.
2885 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2886 GLint max_texture_size;
2887 GLint max_cube_map_texture_size;
2888 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2889 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2890 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2891 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2892 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2893 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2894 // If unpack buffer is nonzero, verify buffer data fits.
2895 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2896 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2897 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2898 GL_INVALID_OPERATION);
2899 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2900
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002901 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2902 ctx->override2DTextureTarget(target);
2903 }
2904
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002905 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2906 ctx->glCompressedTexSubImage2DOffsetAEMU(
2907 ctx, target, level,
2908 xoffset, yoffset,
2909 width, height, format,
2910 imageSize, (uintptr_t)data);
2911 } else {
2912 ctx->m_glCompressedTexSubImage2D_enc(
2913 ctx, target, level,
2914 xoffset, yoffset,
2915 width, height, format,
2916 imageSize, data);
2917 }
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002918
2919 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2920 ctx->restore2DTextureTarget(target);
2921 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002922}
2923
2924void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
2925 GL2Encoder* ctx = (GL2Encoder*)self;
2926 GLClientState* state = ctx->m_state;
2927
2928 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2929
2930 // Only works with certain targets
2931 SET_ERROR_IF(
2932 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2933 target == GL_SHADER_STORAGE_BUFFER ||
2934 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2935 target == GL_UNIFORM_BUFFER),
2936 GL_INVALID_ENUM);
2937
2938 // Can't exceed range
2939 SET_ERROR_IF(index < 0 ||
2940 index >= state->getMaxIndexedBufferBindings(target),
2941 GL_INVALID_VALUE);
2942 SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
2943 SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
2944 target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
2945 (size % 4 || offset % 4),
2946 GL_INVALID_VALUE);
2947
2948 GLint ssbo_offset_align, ubo_offset_align;
2949 ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
2950 ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
2951 SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
2952 offset % ssbo_offset_align,
2953 GL_INVALID_VALUE);
2954 SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
2955 offset % ubo_offset_align,
2956 GL_INVALID_VALUE);
2957
2958 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002959 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002960 state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0);
2961 ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size);
2962}
2963
2964void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
2965 GL2Encoder* ctx = (GL2Encoder*)self;
2966 GLClientState* state = ctx->m_state;
2967
2968 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2969
2970 // Only works with certain targets
2971 SET_ERROR_IF(
2972 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2973 target == GL_SHADER_STORAGE_BUFFER ||
2974 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2975 target == GL_UNIFORM_BUFFER),
2976 GL_INVALID_ENUM);
2977 // Can't exceed range
2978 SET_ERROR_IF(index < 0 ||
2979 index >= state->getMaxIndexedBufferBindings(target),
2980 GL_INVALID_VALUE);
2981
2982 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002983 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002984 BufferData* buf = ctx->getBufferDataById(buffer);
2985 state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0);
2986 ctx->m_glBindBufferBase_enc(self, target, index, buffer);
2987}
2988
2989void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
2990 GL2Encoder* ctx = (GL2Encoder*)self;
2991 GLClientState* state = ctx->m_state;
2992
2993 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
2994 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
2995 SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
2996 readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
2997 readtarget == GL_DRAW_INDIRECT_BUFFER ||
2998 readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2999 SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
3000 writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
3001 writetarget == GL_DRAW_INDIRECT_BUFFER ||
3002 writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
3003 SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
3004 SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
3005 SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
3006 SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
3007 SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
3008 SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
3009 SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
3010 SET_ERROR_IF(
3011 ctx->getBufferData(readtarget) &&
3012 (readoffset + size > ctx->getBufferData(readtarget)->m_size),
3013 GL_INVALID_VALUE);
3014 SET_ERROR_IF(
3015 ctx->getBufferData(writetarget) &&
3016 (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
3017 GL_INVALID_VALUE);
3018 SET_ERROR_IF(readtarget == writetarget &&
3019 !((writeoffset >= readoffset + size) ||
3020 (readoffset >= writeoffset + size)),
3021 GL_INVALID_VALUE);
3022
3023 ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
3024}
3025
3026void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
3027 GL2Encoder* ctx = (GL2Encoder*)self;
3028
3029 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3030 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003031 target != GL_ARRAY_BUFFER &&
3032 target != GL_ELEMENT_ARRAY_BUFFER &&
3033 target != GL_COPY_READ_BUFFER &&
3034 target != GL_COPY_WRITE_BUFFER &&
3035 target != GL_PIXEL_PACK_BUFFER &&
3036 target != GL_PIXEL_UNPACK_BUFFER &&
3037 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
3038 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003039 GL_INVALID_ENUM);
3040 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
3041 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003042 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
3043 pname != GL_BUFFER_MAPPED &&
3044 pname != GL_BUFFER_SIZE &&
3045 pname != GL_BUFFER_USAGE &&
3046 pname != GL_BUFFER_MAP_LENGTH &&
3047 pname != GL_BUFFER_MAP_OFFSET,
3048 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003049
3050 if (!params) return;
3051
3052 BufferData* buf = ctx->getBufferData(target);
3053
3054 switch (pname) {
3055 case GL_BUFFER_ACCESS_FLAGS:
3056 *params = buf ? buf->m_mappedAccess : 0;
3057 break;
3058 case GL_BUFFER_MAPPED:
3059 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3060 break;
3061 case GL_BUFFER_SIZE:
3062 *params = buf ? buf->m_size : 0;
3063 break;
3064 case GL_BUFFER_USAGE:
3065 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3066 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003067 case GL_BUFFER_MAP_LENGTH:
3068 *params = buf ? buf->m_mappedLength : 0;
3069 break;
3070 case GL_BUFFER_MAP_OFFSET:
3071 *params = buf ? buf->m_mappedOffset : 0;
3072 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003073 default:
3074 break;
3075 }
3076}
3077
3078void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
3079 GL2Encoder* ctx = (GL2Encoder*)self;
3080
3081 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3082 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003083 target != GL_ARRAY_BUFFER &&
3084 target != GL_ELEMENT_ARRAY_BUFFER &&
3085 target != GL_COPY_READ_BUFFER &&
3086 target != GL_COPY_WRITE_BUFFER &&
3087 target != GL_PIXEL_PACK_BUFFER &&
3088 target != GL_PIXEL_UNPACK_BUFFER &&
3089 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
3090 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003091 GL_INVALID_ENUM);
3092 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
3093 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003094 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
3095 pname != GL_BUFFER_MAPPED &&
3096 pname != GL_BUFFER_SIZE &&
3097 pname != GL_BUFFER_USAGE &&
3098 pname != GL_BUFFER_MAP_LENGTH &&
3099 pname != GL_BUFFER_MAP_OFFSET,
3100 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003101
3102 if (!params) return;
3103
3104 BufferData* buf = ctx->getBufferData(target);
3105
3106 switch (pname) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003107 case GL_BUFFER_ACCESS_FLAGS:
3108 *params = buf ? buf->m_mappedAccess : 0;
3109 break;
3110 case GL_BUFFER_MAPPED:
3111 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3112 break;
3113 case GL_BUFFER_SIZE:
3114 *params = buf ? buf->m_size : 0;
3115 break;
3116 case GL_BUFFER_USAGE:
3117 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3118 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003119 case GL_BUFFER_MAP_LENGTH:
3120 *params = buf ? buf->m_mappedLength : 0;
3121 break;
3122 case GL_BUFFER_MAP_OFFSET:
3123 *params = buf ? buf->m_mappedOffset : 0;
3124 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003125 default:
3126 break;
3127 }
3128}
3129
3130void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
3131 GL2Encoder* ctx = (GL2Encoder*)self;
3132 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3133 SET_ERROR_IF(
3134 target == GL_ATOMIC_COUNTER_BUFFER ||
3135 target == GL_DISPATCH_INDIRECT_BUFFER ||
3136 target == GL_DRAW_INDIRECT_BUFFER ||
3137 target == GL_SHADER_STORAGE_BUFFER,
3138 GL_INVALID_ENUM);
3139 SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
3140 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
3141 if (!params) return;
3142
3143 BufferData* buf = ctx->getBufferData(target);
3144
3145 if (!buf || !buf->m_mapped) { *params = NULL; return; }
3146
3147 *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
3148}
3149
3150static const char* const kNameDelimiter = ";";
3151
3152static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
3153
3154#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
3155
3156 std::string packed;
3157 // validate the array of char[]'s
3158 const char* currName;
3159 for (GLsizei i = 0; i < count; i++) {
3160 currName = names[i];
3161 VALIDATE(!currName, GL_INVALID_OPERATION);
3162 // check if has reasonable size
3163 size_t len = strlen(currName);
3164 VALIDATE(!len, GL_INVALID_OPERATION);
3165 // check for our delimiter, which if present
3166 // in the name, means an invalid name anyway.
3167 VALIDATE(strstr(currName, kNameDelimiter),
3168 GL_INVALID_OPERATION);
3169 packed += currName;
3170 packed += ";";
3171 }
3172
3173 *err_out = GL_NO_ERROR;
3174 return packed;
3175}
3176
3177void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
3178 GL2Encoder* ctx = (GL2Encoder*)self;
3179
3180 if (!uniformCount) return;
3181
3182 GLint err = GL_NO_ERROR;
3183 std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
3184 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3185
3186 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
3187 std::vector<int> arrIndices;
3188 for (size_t i = 0; i < uniformCount; i++) {
3189 int err;
3190 arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
3191 if (err) {
3192 ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
3193 return;
3194 }
3195 }
3196
3197 ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
3198
3199 for (int i = 0; i < uniformCount; i++) {
3200 if (uniformIndices[i] >= 0 && needLocationWAR) {
3201 uniformIndices[i] =
3202 ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
3203 }
3204 }
3205}
3206
3207void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
3208 GL2Encoder *ctx = (GL2Encoder*)self;
3209 GLClientState* state = ctx->m_state;
3210 GLSharedGroupPtr shared = ctx->m_shared;
3211
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003212 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003213 ctx->m_glUniform1ui_enc(self, hostLoc, v0);
3214
3215 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003216 if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003217 GLenum origActiveTexture = state->getActiveTextureUnit();
3218 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
3219 ctx->m_glActiveTexture_enc(self, origActiveTexture);
3220 }
3221 state->setActiveTextureUnit(origActiveTexture);
3222 }
3223}
3224
3225void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) {
3226 GL2Encoder *ctx = (GL2Encoder*)self;
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_glUniform2ui_enc(self, hostLoc, v0, v1);
3229}
3230
3231void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) {
3232 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003233 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003234 ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2);
3235}
3236
3237void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) {
3238 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003239 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003240 ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3);
3241}
3242
3243void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3244 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003245 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003246 ctx->m_glUniform1uiv_enc(self, hostLoc, count, value);
3247}
3248
3249void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3250 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003251 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003252 ctx->m_glUniform2uiv_enc(self, hostLoc, count, value);
3253}
3254
3255void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3256 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003257 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003258 ctx->m_glUniform3uiv_enc(self, hostLoc, count, value);
3259}
3260
3261void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3262 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003263 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003264 ctx->m_glUniform4uiv_enc(self, hostLoc, count, value);
3265}
3266
3267void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3268 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003269 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003270 ctx->m_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value);
3271}
3272
3273void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3274 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003275 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003276 ctx->m_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value);
3277}
3278
3279void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3280 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003281 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003282 ctx->m_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value);
3283}
3284
3285void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3286 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003287 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003288 ctx->m_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value);
3289}
3290
3291void GL2Encoder::s_glUniformMatrix3x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3292 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003293 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003294 ctx->m_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value);
3295}
3296
3297void GL2Encoder::s_glUniformMatrix4x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3298 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003299 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003300 ctx->m_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value);
3301}
3302
3303void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3304 GL2Encoder *ctx = (GL2Encoder*)self;
3305 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3306 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3307 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3308 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3309 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3310 ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3311}
3312
3313void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3314 GL2Encoder* ctx = (GL2Encoder*)self;
3315 GLClientState* state = ctx->m_state;
3316
3317 // refresh client state's # active uniforms in this block
3318 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3319 // TODO if worth it: cache uniform count and other params,
3320 // invalidate on program relinking.
3321 GLint numActiveUniforms;
3322 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3323 program, uniformBlockIndex,
3324 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3325 &numActiveUniforms);
3326 ctx->m_state->setNumActiveUniformsInUniformBlock(
3327 program, uniformBlockIndex, numActiveUniforms);
3328 }
3329
3330 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3331 program, uniformBlockIndex,
3332 pname, params);
3333}
3334
3335void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3336 GL2Encoder *ctx = (GL2Encoder *)self;
3337 assert(ctx->m_state);
3338 GLint maxIndex;
3339 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3340 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3341
3342 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3343 ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3344 }
3345}
3346
3347void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3348 GL2Encoder *ctx = (GL2Encoder *)self;
3349 assert(ctx->m_state);
3350 GLint maxIndex;
3351 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3352 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3353
3354 if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3355 ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3356 }
3357}
3358
3359void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3360 GL2Encoder *ctx = (GL2Encoder *)self;
3361 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003362 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003363 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
3364 SET_ERROR_IF(
3365 !(type == GL_BYTE ||
3366 type == GL_UNSIGNED_BYTE ||
3367 type == GL_SHORT ||
3368 type == GL_UNSIGNED_SHORT ||
3369 type == GL_INT ||
3370 type == GL_UNSIGNED_INT),
3371 GL_INVALID_ENUM);
3372 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
3373
3374 ctx->m_state->setVertexAttribBinding(index, index);
3375 ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true);
3376 GLsizei effectiveStride = stride;
3377 if (stride == 0) {
3378 effectiveStride = glSizeof(type) * size;
3379 }
3380 ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride);
3381
3382 if (ctx->m_state->currentArrayVbo() != 0) {
3383 ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer);
3384 } else {
3385 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION);
3386 // wait for client-array handler
3387 }
3388}
3389
3390void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) {
3391 GL2Encoder *ctx = (GL2Encoder *)self;
3392 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003393 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003394 ctx->m_state->setVertexAttribBinding(index, index);
3395 ctx->m_state->setVertexBindingDivisor(index, divisor);
3396 ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor);
3397}
3398
3399void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3400 GLenum target, GLsizei samples, GLenum internalformat,
3401 GLsizei width, GLsizei height) {
3402 GL2Encoder *ctx = (GL2Encoder *)self;
3403 GLClientState* state = ctx->m_state;
3404
3405 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3406 SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3407
3408 GLint max_samples;
3409 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3410 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3411
3412 state->setBoundRenderbufferFormat(internalformat);
3413 state->setBoundRenderbufferSamples(samples);
3414 ctx->m_glRenderbufferStorageMultisample_enc(
3415 self, target, samples, internalformat, width, height);
3416}
3417
3418void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3419 GL2Encoder* ctx = (GL2Encoder*)self;
3420 SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3421 SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3422 for (int i = 0; i < n; i++) {
3423 SET_ERROR_IF(
3424 bufs[i] != GL_NONE &&
3425 bufs[i] != GL_BACK &&
3426 glUtilsColorAttachmentIndex(bufs[i]) == -1,
3427 GL_INVALID_ENUM);
3428 SET_ERROR_IF(
3429 !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3430 glUtilsColorAttachmentIndex(bufs[i]) != -1,
3431 GL_INVALID_OPERATION);
3432 SET_ERROR_IF(
3433 ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3434 ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3435 glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3436 (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3437 bufs[i] != GL_NONE)),
3438 GL_INVALID_OPERATION);
3439 }
3440
3441 ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3442}
3443
3444void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3445 GL2Encoder* ctx = (GL2Encoder*)self;
3446
3447 SET_ERROR_IF(
3448 glUtilsColorAttachmentIndex(src) != -1 &&
3449 (glUtilsColorAttachmentIndex(src) >=
3450 ctx->m_state->getMaxColorAttachments()),
3451 GL_INVALID_OPERATION);
3452 SET_ERROR_IF(
3453 src != GL_NONE &&
3454 src != GL_BACK &&
3455 src > GL_COLOR_ATTACHMENT0 &&
3456 src < GL_DEPTH_ATTACHMENT &&
3457 (src - GL_COLOR_ATTACHMENT0) >
3458 ctx->m_state->getMaxColorAttachments(),
3459 GL_INVALID_OPERATION);
3460 SET_ERROR_IF(
3461 src != GL_NONE &&
3462 src != GL_BACK &&
3463 glUtilsColorAttachmentIndex(src) == -1,
3464 GL_INVALID_ENUM);
3465 SET_ERROR_IF(
3466 !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3467 src != GL_NONE &&
3468 src != GL_BACK,
3469 GL_INVALID_OPERATION);
3470 SET_ERROR_IF(
3471 ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3472 src != GL_NONE &&
3473 glUtilsColorAttachmentIndex(src) == -1,
3474 GL_INVALID_OPERATION);
3475
3476 ctx->m_glReadBuffer_enc(ctx, src);
3477}
3478
3479void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3480 GL2Encoder* ctx = (GL2Encoder*)self;
3481 GLClientState* state = ctx->m_state;
3482
3483 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3484 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3485 GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3486 SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3487 lastBoundTarget != GL_TEXTURE_3D,
3488 GL_INVALID_OPERATION);
3489 state->attachTextureObject(target, attachment, texture);
3490
3491 GLint max3DTextureSize;
3492 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3493 SET_ERROR_IF(
3494 layer >= max3DTextureSize,
3495 GL_INVALID_VALUE);
3496
3497 ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3498}
3499
3500void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3501 GL2Encoder* ctx = (GL2Encoder*)self;
3502 GLClientState* state = ctx->m_state;
3503
3504 SET_ERROR_IF(
3505 target != GL_TEXTURE_2D &&
3506 target != GL_TEXTURE_CUBE_MAP,
3507 GL_INVALID_ENUM);
3508 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3509 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3510 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3511 SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3512 GL_INVALID_OPERATION);
3513 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3514
3515 state->setBoundTextureInternalFormat(target, internalformat);
3516 state->setBoundTextureDims(target, -1, width, height, 1);
3517 state->setBoundTextureImmutableFormat(target);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003518
3519 if (target == GL_TEXTURE_2D) {
3520 ctx->override2DTextureTarget(target);
3521 }
3522
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003523 ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003524
3525 if (target == GL_TEXTURE_2D) {
3526 ctx->restore2DTextureTarget(target);
3527 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003528}
3529
3530void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3531 GL2Encoder* ctx = (GL2Encoder*)self;
3532
3533 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3534
3535 GLint maxCount = 0;
3536 ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3537
3538 SET_ERROR_IF(
3539 bufferMode == GL_SEPARATE_ATTRIBS &&
3540 maxCount < count,
3541 GL_INVALID_VALUE);
3542 SET_ERROR_IF(
3543 bufferMode != GL_INTERLEAVED_ATTRIBS &&
3544 bufferMode != GL_SEPARATE_ATTRIBS,
3545 GL_INVALID_ENUM);
3546
3547 if (!count) return;
3548
3549 GLint err = GL_NO_ERROR;
3550 std::string packed = packVarNames(count, varyings, &err);
3551 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3552
3553 ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3554}
3555
3556void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3557 GL2Encoder* ctx = (GL2Encoder*)self;
3558 GLClientState* state = ctx->m_state;
3559 ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3560 state->setTransformFeedbackActiveUnpaused(true);
3561}
3562
3563void GL2Encoder::s_glEndTransformFeedback(void* self) {
3564 GL2Encoder* ctx = (GL2Encoder*)self;
3565 GLClientState* state = ctx->m_state;
3566 ctx->m_glEndTransformFeedback_enc(ctx);
3567 state->setTransformFeedbackActiveUnpaused(false);
3568}
3569
3570void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3571 GL2Encoder* ctx = (GL2Encoder*)self;
3572 GLClientState* state = ctx->m_state;
3573 ctx->m_glPauseTransformFeedback_enc(ctx);
3574 state->setTransformFeedbackActiveUnpaused(false);
3575}
3576
3577void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3578 GL2Encoder* ctx = (GL2Encoder*)self;
3579 GLClientState* state = ctx->m_state;
3580 ctx->m_glResumeTransformFeedback_enc(ctx);
3581 state->setTransformFeedbackActiveUnpaused(true);
3582}
3583
3584void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3585 GLsizei width, GLsizei height, GLsizei depth,
3586 GLint border, GLenum format, GLenum type, const GLvoid* data) {
3587 GL2Encoder* ctx = (GL2Encoder*)self;
3588 GLClientState* state = ctx->m_state;
3589
3590 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3591 target != GL_TEXTURE_2D_ARRAY,
3592 GL_INVALID_ENUM);
3593 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3594 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3595
3596 // If unpack buffer is nonzero, verify unmapped state.
3597 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3598
3599 GLint max_texture_size;
3600 GLint max_3d_texture_size;
3601 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3602 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3603 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3604 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3605 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3606
3607 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3608 SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3609 SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3610 SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3611 SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3612 SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3613 SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3614 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3615 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3616 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3617 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3618 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3619 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3620 GL_INVALID_OPERATION);
3621 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3622 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3623 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3624 glSizeof(type)),
3625 GL_INVALID_OPERATION);
3626 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3627
3628 state->setBoundTextureInternalFormat(target, internalFormat);
3629 state->setBoundTextureFormat(target, format);
3630 state->setBoundTextureType(target, type);
3631 state->setBoundTextureDims(target, level, width, height, depth);
3632
3633 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3634 ctx->glTexImage3DOffsetAEMU(
3635 ctx, target, level, internalFormat,
3636 width, height, depth,
3637 border, format, type, (uintptr_t)data);
3638 } else {
3639 ctx->m_glTexImage3D_enc(ctx,
3640 target, level, internalFormat,
3641 width, height, depth,
3642 border, format, type, data);
3643 }
3644}
3645
3646void 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) {
3647 GL2Encoder* ctx = (GL2Encoder*)self;
3648 GLClientState* state = ctx->m_state;
3649
3650 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3651 target != GL_TEXTURE_2D_ARRAY,
3652 GL_INVALID_ENUM);
3653 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3654 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3655 // If unpack buffer is nonzero, verify unmapped state.
3656 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3657 GLint max_texture_size;
3658 GLint max_3d_texture_size;
3659 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3660 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3661 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3662 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3663 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3664 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3665 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3666 GLuint tex = state->getBoundTexture(target);
3667 GLsizei neededWidth = xoffset + width;
3668 GLsizei neededHeight = yoffset + height;
3669 GLsizei neededDepth = zoffset + depth;
3670
3671 SET_ERROR_IF(tex &&
3672 (neededWidth > state->queryTexWidth(level, tex) ||
3673 neededHeight > state->queryTexHeight(level, tex) ||
3674 neededDepth > state->queryTexDepth(level, tex)),
3675 GL_INVALID_VALUE);
3676 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3677 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3678 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3679 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3680 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3681 GL_INVALID_OPERATION);
3682 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3683 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3684 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3685 glSizeof(type)),
3686 GL_INVALID_OPERATION);
3687 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
3688 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3689
3690 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3691 ctx->glTexSubImage3DOffsetAEMU(ctx,
3692 target, level,
3693 xoffset, yoffset, zoffset,
3694 width, height, depth,
3695 format, type, (uintptr_t)data);
3696 } else {
3697 ctx->m_glTexSubImage3D_enc(ctx,
3698 target, level,
3699 xoffset, yoffset, zoffset,
3700 width, height, depth,
3701 format, type, data);
3702 }
3703}
3704
3705void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
3706 GL2Encoder* ctx = (GL2Encoder*)self;
3707 GLClientState* state = ctx->m_state;
3708
3709 // Filter compressed formats support.
3710 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3711 // If unpack buffer is nonzero, verify unmapped state.
3712 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3713 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3714 SET_ERROR_IF(border, GL_INVALID_VALUE);
3715 // If unpack buffer is nonzero, verify buffer data fits.
3716 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3717 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3718 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3719 GL_INVALID_OPERATION);
3720 // TODO: Fix:
3721 // If |imageSize| is too small for compressed dimensions.
3722 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
3723 state->setBoundTextureInternalFormat(target, (GLint)internalformat);
3724 state->setBoundTextureDims(target, level, width, height, depth);
3725
3726 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3727 ctx->glCompressedTexImage3DOffsetAEMU(
3728 ctx, target, level, internalformat,
3729 width, height, depth, border,
3730 imageSize, (uintptr_t)data);
3731 } else {
3732 ctx->m_glCompressedTexImage3D_enc(
3733 ctx, target, level, internalformat,
3734 width, height, depth, border,
3735 imageSize, data);
3736 }
3737}
3738
3739void 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) {
3740 GL2Encoder* ctx = (GL2Encoder*)self;
3741 GLClientState* state = ctx->m_state;
3742
3743 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3744 // If unpack buffer is nonzero, verify unmapped state.
3745 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3746 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3747 // If unpack buffer is nonzero, verify buffer data fits.
3748 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3749 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3750 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3751 GL_INVALID_OPERATION);
3752 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3753
3754 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3755 ctx->glCompressedTexSubImage3DOffsetAEMU(
3756 ctx, target, level,
3757 xoffset, yoffset, zoffset,
3758 width, height, depth,
3759 format, imageSize, (uintptr_t)data);
3760 } else {
3761 ctx->m_glCompressedTexSubImage3D_enc(
3762 ctx, target, level,
3763 xoffset, yoffset, zoffset,
3764 width, height, depth,
3765 format, imageSize, data);
3766
3767 }
3768}
3769
3770void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
3771 GL2Encoder* ctx = (GL2Encoder*)self;
3772 GLClientState* state = ctx->m_state;
3773 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3774 target != GL_TEXTURE_2D_ARRAY,
3775 GL_INVALID_ENUM);
3776 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3777 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3778 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3779 SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
3780 GL_INVALID_OPERATION);
3781 SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
3782 GL_INVALID_OPERATION);
3783 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3784
3785 state->setBoundTextureInternalFormat(target, internalformat);
3786 state->setBoundTextureDims(target, -1, width, height, depth);
3787 state->setBoundTextureImmutableFormat(target);
3788 ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
3789 state->setBoundTextureImmutableFormat(target);
3790}
3791
3792void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
3793 GL2Encoder *ctx = (GL2Encoder *)self;
3794 assert(ctx->m_state != NULL);
3795 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3796 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3797
3798 bool has_client_vertex_arrays = false;
3799 bool has_indirect_arrays = false;
3800 ctx->getVBOUsage(&has_client_vertex_arrays,
3801 &has_indirect_arrays);
3802
3803 if (has_client_vertex_arrays ||
3804 (!has_client_vertex_arrays &&
3805 !has_indirect_arrays)) {
3806 ctx->sendVertexAttributes(first, count, true, primcount);
3807 ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
3808 } else {
3809 ctx->sendVertexAttributes(0, count, false, primcount);
3810 ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
3811 }
3812 ctx->m_stream->flush();
3813}
3814
3815void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
3816{
3817
3818 GL2Encoder *ctx = (GL2Encoder *)self;
3819 assert(ctx->m_state != NULL);
3820 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3821 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3822 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3823 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3824
3825 bool has_client_vertex_arrays = false;
3826 bool has_indirect_arrays = false;
3827 int nLocations = ctx->m_state->nLocations();
3828 GLintptr offset = 0;
3829
3830 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3831
3832 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3833 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3834 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3835 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3836 }
3837
3838 BufferData* buf = NULL;
3839 int minIndex = 0, maxIndex = 0;
3840
3841 // For validation/immediate index array purposes,
3842 // we need the min/max vertex index of the index array.
3843 // If the VBO != 0, this may not be the first time we have
3844 // used this particular index buffer. getBufferIndexRange
3845 // can more quickly get min/max vertex index by
3846 // caching previous results.
3847 if (ctx->m_state->currentIndexVbo() != 0) {
3848 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3849 offset = (GLintptr)indices;
3850 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3851 ctx->getBufferIndexRange(buf,
3852 indices,
3853 type,
3854 (size_t)count,
3855 (size_t)offset,
3856 &minIndex, &maxIndex);
3857 } else {
3858 // In this case, the |indices| field holds a real
3859 // array, so calculate the indices now. They will
3860 // also be needed to know how much data to
3861 // transfer to host.
3862 ctx->calcIndexRange(indices,
3863 type,
3864 count,
3865 &minIndex,
3866 &maxIndex);
3867 }
3868
Lingfeng Yang26e629a2018-10-13 20:00:12 -07003869 if (count == 0) return;
3870
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003871 bool adjustIndices = true;
3872 if (ctx->m_state->currentIndexVbo() != 0) {
3873 if (!has_client_vertex_arrays) {
3874 ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
3875 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3876 ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
3877 ctx->flushDrawCall();
3878 adjustIndices = false;
3879 } else {
3880 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3881 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3882 }
3883 }
3884 if (adjustIndices) {
3885 void *adjustedIndices =
3886 ctx->recenterIndices(indices,
3887 type,
3888 count,
3889 minIndex);
3890
3891 if (has_indirect_arrays || 1) {
3892 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
3893 ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
3894 ctx->m_stream->flush();
3895 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3896 if(!has_indirect_arrays) {
3897 //ALOGD("unoptimized drawelements !!!\n");
3898 }
3899 } else {
3900 // we are all direct arrays and immidate mode index array -
3901 // rebuild the arrays and the index array;
3902 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3903 }
3904 }
3905}
3906
3907void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
3908{
3909
3910 GL2Encoder *ctx = (GL2Encoder *)self;
3911 assert(ctx->m_state != NULL);
3912 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3913 SET_ERROR_IF(end < start, GL_INVALID_VALUE);
3914 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3915 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3916 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3917
3918 bool has_client_vertex_arrays = false;
3919 bool has_indirect_arrays = false;
3920 int nLocations = ctx->m_state->nLocations();
3921 GLintptr offset = 0;
3922
3923 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3924
3925 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3926 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3927 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3928 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3929 }
3930
3931 BufferData* buf = NULL;
3932 int minIndex = 0, maxIndex = 0;
3933
3934 // For validation/immediate index array purposes,
3935 // we need the min/max vertex index of the index array.
3936 // If the VBO != 0, this may not be the first time we have
3937 // used this particular index buffer. getBufferIndexRange
3938 // can more quickly get min/max vertex index by
3939 // caching previous results.
3940 if (ctx->m_state->currentIndexVbo() != 0) {
3941 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3942 offset = (GLintptr)indices;
3943 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3944 ctx->getBufferIndexRange(buf,
3945 indices,
3946 type,
3947 (size_t)count,
3948 (size_t)offset,
3949 &minIndex, &maxIndex);
3950 } else {
3951 // In this case, the |indices| field holds a real
3952 // array, so calculate the indices now. They will
3953 // also be needed to know how much data to
3954 // transfer to host.
3955 ctx->calcIndexRange(indices,
3956 type,
3957 count,
3958 &minIndex,
3959 &maxIndex);
3960 }
3961
Lingfeng Yang26e629a2018-10-13 20:00:12 -07003962 if (count == 0) return;
3963
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003964 bool adjustIndices = true;
3965 if (ctx->m_state->currentIndexVbo() != 0) {
3966 if (!has_client_vertex_arrays) {
3967 ctx->sendVertexAttributes(0, maxIndex + 1, false);
3968 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3969 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
3970 ctx->flushDrawCall();
3971 adjustIndices = false;
3972 } else {
3973 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3974 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3975 }
3976 }
3977 if (adjustIndices) {
3978 void *adjustedIndices =
3979 ctx->recenterIndices(indices,
3980 type,
3981 count,
3982 minIndex);
3983
3984 if (has_indirect_arrays || 1) {
3985 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
3986 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
3987 ctx->m_stream->flush();
3988 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3989 if(!has_indirect_arrays) {
3990 //ALOGD("unoptimized drawelements !!!\n");
3991 }
3992 } else {
3993 // we are all direct arrays and immidate mode index array -
3994 // rebuild the arrays and the index array;
3995 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3996 }
3997 }
3998}
3999
4000// struct GLStringKey {
4001// GLenum name;
4002// GLuint index;
4003// };
4004//
4005// struct GLStringKeyCompare {
4006// bool operator() (const GLStringKey& a,
4007// const GLStringKey& b) const {
4008// if (a.name != b.name) return a.name < b.name;
4009// if (a.index != b.index) return a.index < b.index;
4010// return false;
4011// }
4012// };
4013//
4014// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
4015//
4016// static GLStringStore sGLStringStore;
4017// bool sGLStringStoreInitialized = false;
4018
4019const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
4020 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004021 const GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004022
4023 RET_AND_SET_ERROR_IF(
4024 name != GL_VENDOR &&
4025 name != GL_RENDERER &&
4026 name != GL_VERSION &&
4027 name != GL_EXTENSIONS,
4028 GL_INVALID_ENUM,
4029 retval);
4030
4031 RET_AND_SET_ERROR_IF(
Lingfeng Yang44209df2018-09-21 10:04:17 -07004032 (name == GL_VENDOR ||
4033 name == GL_RENDERER ||
4034 name == GL_VERSION) &&
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004035 index != 0,
4036 GL_INVALID_VALUE,
4037 retval);
4038
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004039 RET_AND_SET_ERROR_IF(
4040 name == GL_EXTENSIONS &&
4041 index >= ctx->m_currExtensionsArray.size(),
4042 GL_INVALID_VALUE,
4043 retval);
4044
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004045 switch (name) {
4046 case GL_VENDOR:
4047 retval = gVendorString;
4048 break;
4049 case GL_RENDERER:
4050 retval = gRendererString;
4051 break;
4052 case GL_VERSION:
4053 retval = gVersionString;
4054 break;
4055 case GL_EXTENSIONS:
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004056 retval = (const GLubyte*)(ctx->m_currExtensionsArray[index].c_str());
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004057 break;
4058 }
4059
4060 return retval;
4061}
4062
4063void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
4064 GL2Encoder *ctx = (GL2Encoder *)self;
4065
4066 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
4067
4068 GLint linkStatus = 0;
4069 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
4070 GLint properLength = 0;
4071 ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
4072
4073 SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
4074 SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
4075
4076 ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
4077}
4078
4079void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
4080 GL2Encoder *ctx = (GL2Encoder *)self;
4081
4082 SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
4083 SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
4084 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
4085 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
4086 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
4087 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
4088 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
4089 ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
4090 GL_INVALID_OPERATION);
4091 /*
4092GL_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.
4093
4094GL_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.
4095
4096GL_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.
4097
4098GL_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.
4099*/
4100
4101 FboFormatInfo fbo_format_info;
4102 ctx->m_state->getBoundFramebufferFormat(
4103 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
4104 SET_ERROR_IF(
4105 fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4106 !GLESv2Validation::readPixelsFboFormatMatch(
4107 format, type, fbo_format_info.tex_type),
4108 GL_INVALID_OPERATION);
4109
4110 if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
4111 ctx->glReadPixelsOffsetAEMU(
4112 ctx, x, y, width, height,
4113 format, type, (uintptr_t)pixels);
4114 } else {
4115 ctx->m_glReadPixels_enc(
4116 ctx, x, y, width, height,
4117 format, type, pixels);
4118 }
4119}
4120
4121// Track enabled state for some things like:
4122// - Primitive restart
4123void GL2Encoder::s_glEnable(void* self, GLenum what) {
4124 GL2Encoder *ctx = (GL2Encoder *)self;
4125
4126 switch (what) {
4127 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4128 ctx->m_primitiveRestartEnabled = true;
4129 break;
4130 }
4131
4132 ctx->m_glEnable_enc(ctx, what);
4133}
4134
4135void GL2Encoder::s_glDisable(void* self, GLenum what) {
4136 GL2Encoder *ctx = (GL2Encoder *)self;
4137
4138 switch (what) {
4139 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4140 ctx->m_primitiveRestartEnabled = false;
4141 break;
4142 }
4143
4144 ctx->m_glDisable_enc(ctx, what);
4145}
4146
4147void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
4148 GL2Encoder *ctx = (GL2Encoder *)self;
4149
4150 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4151
4152 ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
4153}
4154
4155void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
4156 GL2Encoder *ctx = (GL2Encoder *)self;
4157
4158 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4159
4160 ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
4161}
4162
4163void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
4164 GL2Encoder *ctx = (GL2Encoder *)self;
4165
4166 SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4167
4168 ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
4169}
4170
4171void 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) {
4172 GL2Encoder *ctx = (GL2Encoder *)self;
4173 GLClientState* state = ctx->m_state;
4174
4175 bool validateColor = mask | GL_COLOR_BUFFER_BIT;
4176 bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
4177 bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
4178
4179 FboFormatInfo read_fbo_format_info;
4180 FboFormatInfo draw_fbo_format_info;
4181 if (validateColor) {
4182 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4183 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4184
4185 if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4186 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
4187 SET_ERROR_IF(
4188 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4189 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4190 !GLESv2Validation::blitFramebufferFormat(
4191 read_fbo_format_info.tex_type,
4192 draw_fbo_format_info.tex_type),
4193 GL_INVALID_OPERATION);
4194 }
4195 }
4196
4197 if (validateDepth) {
4198 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
4199 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
4200
4201 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4202 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4203 SET_ERROR_IF(
4204 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4205 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4206 !GLESv2Validation::blitFramebufferFormat(
4207 read_fbo_format_info.rb_format,
4208 draw_fbo_format_info.rb_format),
4209 GL_INVALID_OPERATION);
4210 }
4211 }
4212
4213 if (validateStencil) {
4214 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
4215 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
4216
4217 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4218 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4219 SET_ERROR_IF(
4220 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4221 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4222 !GLESv2Validation::blitFramebufferFormat(
4223 read_fbo_format_info.rb_format,
4224 draw_fbo_format_info.rb_format),
4225 GL_INVALID_OPERATION);
4226 }
4227 }
4228
4229 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4230 SET_ERROR_IF(
4231 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4232 draw_fbo_format_info.rb_multisamples > 0,
4233 GL_INVALID_OPERATION);
4234 SET_ERROR_IF(
4235 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4236 draw_fbo_format_info.tex_multisamples > 0,
4237 GL_INVALID_OPERATION);
4238
4239 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4240 SET_ERROR_IF(
4241 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4242 read_fbo_format_info.rb_multisamples > 0 &&
4243 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4244 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4245 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4246 (read_fbo_format_info.rb_format !=
4247 draw_fbo_format_info.rb_format),
4248 GL_INVALID_OPERATION);
4249 SET_ERROR_IF(
4250 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4251 read_fbo_format_info.rb_multisamples > 0 &&
4252 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4253 (srcX0 != dstX0 || srcY0 != dstY0 ||
4254 srcX1 != dstX1 || srcY1 != dstY1),
4255 GL_INVALID_OPERATION);
4256
4257 ctx->m_glBlitFramebuffer_enc(ctx,
4258 srcX0, srcY0, srcX1, srcY1,
4259 dstX0, dstY0, dstX1, dstY1,
4260 mask, filter);
4261}
4262
4263void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
4264 GL2Encoder *ctx = (GL2Encoder *)self;
4265
4266 SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
4267 pname != GL_SAMPLES,
4268 GL_INVALID_ENUM);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004269 SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004270 SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004271 !GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4272 !GLESv2Validation::depthRenderableFormat(ctx, internalformat) &&
4273 !GLESv2Validation::stencilRenderableFormat(ctx, internalformat),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004274 GL_INVALID_ENUM);
4275 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4276
4277 if (bufSize < 1) return;
4278
4279 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
4280 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
4281 switch (pname) {
4282 case GL_NUM_SAMPLE_COUNTS:
4283 *params = 3;
4284 break;
4285 case GL_SAMPLES:
4286 params[0] = 4;
4287 if (bufSize > 1) params[1] = 2;
4288 if (bufSize > 2) params[2] = 1;
4289 break;
4290 default:
4291 break;
4292 }
4293}
4294
4295void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
4296 GL2Encoder *ctx = (GL2Encoder *)self;
4297 GLClientState* state = ctx->m_state;
4298
4299 SET_ERROR_IF(target != GL_TEXTURE_2D &&
4300 target != GL_TEXTURE_3D &&
Yahan Zhou53c64582018-04-16 15:46:17 -07004301 target != GL_TEXTURE_CUBE_MAP &&
4302 target != GL_TEXTURE_2D_ARRAY,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004303 GL_INVALID_ENUM);
4304
4305 GLuint tex = state->getBoundTexture(target);
4306 GLenum internalformat = state->queryTexInternalFormat(tex);
4307 GLenum format = state->queryTexFormat(tex);
4308
4309 SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
4310 GL_INVALID_OPERATION);
4311 SET_ERROR_IF(tex &&
4312 !GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004313 !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4314 GLESv2Validation::filterableTexFormat(ctx, internalformat)),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004315 GL_INVALID_OPERATION);
4316
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08004317 if (target == GL_TEXTURE_2D) {
4318 ctx->override2DTextureTarget(target);
4319 }
4320
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004321 ctx->m_glGenerateMipmap_enc(ctx, target);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08004322
4323 if (target == GL_TEXTURE_2D) {
4324 ctx->restore2DTextureTarget(target);
4325 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004326}
4327
4328void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4329 GL2Encoder *ctx = (GL2Encoder *)self;
4330 GLint maxCombinedUnits;
4331 ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4332 SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4333
4334 ctx->m_glBindSampler_enc(ctx, unit, sampler);
4335}
4336
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004337GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4338 GL2Encoder *ctx = (GL2Encoder *)self;
4339 uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4340 return (GLsync)(uintptr_t)syncHandle;
4341}
4342
4343GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4344 GL2Encoder *ctx = (GL2Encoder *)self;
4345 return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4346}
4347
4348void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4349 GL2Encoder *ctx = (GL2Encoder *)self;
4350 ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4351}
4352
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004353void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) {
4354 GL2Encoder *ctx = (GL2Encoder *)self;
4355
4356 if (!sync) return;
4357
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004358 ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4359}
4360
4361GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4362 GL2Encoder *ctx = (GL2Encoder *)self;
4363 return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4364}
4365
4366void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4367 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004368
4369 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4370
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004371 return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004372}
4373
4374#define LIMIT_CASE(target, lim) \
4375 case target: \
4376 ctx->glGetIntegerv(ctx, lim, &limit); \
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004377 SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004378 break; \
4379
4380void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) {
4381 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004382 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004383
4384 GLint limit;
4385
4386 switch (target) {
4387 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4388 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4389 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4390 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4391 default:
4392 break;
4393 }
4394
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004395 const GLClientState::VertexAttribBindingVector& currBindings =
4396 state->currentVertexBufferBindings();
4397
4398 switch (target) {
4399 case GL_VERTEX_BINDING_DIVISOR:
4400 case GL_VERTEX_BINDING_OFFSET:
4401 case GL_VERTEX_BINDING_STRIDE:
4402 case GL_VERTEX_BINDING_BUFFER:
4403 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4404 break;
4405 default:
4406 break;
4407 }
4408
4409 switch (target) {
4410 case GL_VERTEX_BINDING_DIVISOR:
4411 *params = currBindings[index].divisor;
4412 return;
4413 case GL_VERTEX_BINDING_OFFSET:
4414 *params = currBindings[index].offset;
4415 return;
4416 case GL_VERTEX_BINDING_STRIDE:
4417 *params = currBindings[index].effectiveStride;
4418 return;
4419 case GL_VERTEX_BINDING_BUFFER:
4420 *params = currBindings[index].buffer;
4421 return;
4422 default:
4423 break;
4424 }
4425
Lingfeng Yang80a36332017-07-09 10:58:07 -07004426 ctx->safe_glGetIntegeri_v(target, index, params);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004427}
4428
4429void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
4430 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004431 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004432
4433 GLint limit;
4434
4435 switch (target) {
4436 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4437 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4438 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4439 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4440 default:
4441 break;
4442 }
4443
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004444 const GLClientState::VertexAttribBindingVector& currBindings =
4445 state->currentVertexBufferBindings();
4446
4447 switch (target) {
4448 case GL_VERTEX_BINDING_DIVISOR:
4449 case GL_VERTEX_BINDING_OFFSET:
4450 case GL_VERTEX_BINDING_STRIDE:
4451 case GL_VERTEX_BINDING_BUFFER:
4452 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4453 break;
4454 default:
4455 break;
4456 }
4457
4458 switch (target) {
4459 case GL_VERTEX_BINDING_DIVISOR:
4460 *params = currBindings[index].divisor;
4461 return;
4462 case GL_VERTEX_BINDING_OFFSET:
4463 *params = currBindings[index].offset;
4464 return;
4465 case GL_VERTEX_BINDING_STRIDE:
4466 *params = currBindings[index].effectiveStride;
4467 return;
4468 case GL_VERTEX_BINDING_BUFFER:
4469 *params = currBindings[index].buffer;
4470 return;
4471 default:
4472 break;
4473 }
4474
Lingfeng Yang80a36332017-07-09 10:58:07 -07004475 ctx->safe_glGetInteger64i_v(target, index, params);
4476}
4477
4478void GL2Encoder::s_glGetInteger64v(void* self, GLenum param, GLint64* val) {
4479 GL2Encoder *ctx = (GL2Encoder *)self;
4480 ctx->safe_glGetInteger64v(param, val);
4481}
4482
4483void GL2Encoder::s_glGetBooleani_v(void* self, GLenum param, GLuint index, GLboolean* val) {
4484 GL2Encoder *ctx = (GL2Encoder *)self;
4485 ctx->safe_glGetBooleani_v(param, index, val);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004486}
4487
4488void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4489 GL2Encoder *ctx = (GL2Encoder *)self;
4490 ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4491 if (pname == GL_SHADER_SOURCE_LENGTH) {
4492 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4493 if (shaderData) {
4494 int totalLen = 0;
4495 for (int i = 0; i < shaderData->sources.size(); i++) {
4496 totalLen += shaderData->sources[i].size();
4497 }
4498 if (totalLen != 0) {
4499 *params = totalLen + 1; // account for null terminator
4500 }
4501 }
4502 }
4503}
4504
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004505void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) {
4506 GL2Encoder *ctx = (GL2Encoder*)self;
4507 GLClientState* state = ctx->m_state;
4508 GLSharedGroupPtr shared = ctx->m_shared;
4509
4510 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4511 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4512 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4513
4514 ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program);
4515 if (!state->currentProgram()) {
4516 state->setCurrentShaderProgram(program);
4517 }
4518}
4519
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004520GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4521
4522 GLint* length = NULL;
4523 GL2Encoder* ctx = (GL2Encoder*)self;
4524
4525 int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
4526 char *str = new char[len + 1];
4527 glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
4528
4529 // Do GLSharedGroup and location WorkARound-specific initialization
4530 // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4531 uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4532 ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004533
Lingfeng Yang44209df2018-09-21 10:04:17 -07004534 if (!replaceSamplerExternalWith2D(str, &spData->shaderData)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004535 delete [] str;
4536 ctx->setError(GL_OUT_OF_MEMORY);
4537 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4538 return -1;
4539 }
4540
4541 GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
4542 delete [] str;
4543
4544 // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4545 GLint linkStatus = 0;
4546 ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4547 if (!linkStatus) {
4548 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4549 return -1;
4550 }
4551
4552 ctx->m_shared->associateGLShaderProgram(res, spDataId);
4553
4554 GLint numUniforms = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07004555 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORMS, &numUniforms);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004556 ctx->m_shared->initShaderProgramData(res, numUniforms);
4557
4558 GLint maxLength=0;
4559 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4560
4561 GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4562
4563 for (GLint i = 0; i < numUniforms; ++i) {
4564 ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4565 GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4566 ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4567 }
4568
4569 ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4570
4571 delete [] name;
4572
4573 return res;
4574}
4575
4576void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4577{
4578 GL2Encoder *ctx = (GL2Encoder*)self;
4579 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4580 ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4581}
4582
4583void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4584{
4585 GL2Encoder *ctx = (GL2Encoder*)self;
4586 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4587 ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4588}
4589
4590void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4591{
4592 GL2Encoder *ctx = (GL2Encoder*)self;
4593 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004594 ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004595
4596 GLClientState* state = ctx->m_state;
4597 GLSharedGroupPtr shared = ctx->m_shared;
4598 GLenum target;
4599
4600 if (shared->setSamplerUniform(program, location, v0, &target)) {
4601 GLenum origActiveTexture = state->getActiveTextureUnit();
4602 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4603 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4604 }
4605 state->setActiveTextureUnit(origActiveTexture);
4606 }
4607}
4608
4609void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4610{
4611 GL2Encoder *ctx = (GL2Encoder*)self;
4612 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4613 ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4614}
4615
4616void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4617{
4618 GL2Encoder *ctx = (GL2Encoder*)self;
4619 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4620 ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4621
4622 GLClientState* state = ctx->m_state;
4623 GLSharedGroupPtr shared = ctx->m_shared;
4624 GLenum target;
4625
4626 if (shared->setSamplerUniform(program, location, v0, &target)) {
4627 GLenum origActiveTexture = state->getActiveTextureUnit();
4628 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4629 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4630 }
4631 state->setActiveTextureUnit(origActiveTexture);
4632 }
4633}
4634
4635void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4636{
4637 GL2Encoder *ctx = (GL2Encoder*)self;
4638 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4639 ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
4640}
4641
4642void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
4643{
4644 GL2Encoder *ctx = (GL2Encoder*)self;
4645 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4646 ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
4647}
4648
4649void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4650{
4651 GL2Encoder *ctx = (GL2Encoder*)self;
4652 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4653 ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
4654}
4655
4656void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
4657{
4658 GL2Encoder *ctx = (GL2Encoder*)self;
4659 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4660 ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
4661}
4662
4663void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4664{
4665 GL2Encoder *ctx = (GL2Encoder*)self;
4666 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4667 ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
4668}
4669
4670void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
4671{
4672 GL2Encoder *ctx = (GL2Encoder*)self;
4673 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4674 ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
4675}
4676
4677void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4678{
4679 GL2Encoder *ctx = (GL2Encoder*)self;
4680 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4681 ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
4682}
4683
4684void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
4685{
4686 GL2Encoder *ctx = (GL2Encoder*)self;
4687 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4688 ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
4689}
4690
4691void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4692{
4693 GL2Encoder *ctx = (GL2Encoder*)self;
4694 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4695 ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
4696}
4697
4698void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
4699{
4700 GL2Encoder *ctx = (GL2Encoder*)self;
4701 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4702 ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
4703}
4704
4705void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4706{
4707 GL2Encoder *ctx = (GL2Encoder*)self;
4708 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4709 ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
4710}
4711
4712void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
4713{
4714 GL2Encoder *ctx = (GL2Encoder*)self;
4715 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4716 ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
4717}
4718
4719void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4720{
4721 GL2Encoder *ctx = (GL2Encoder*)self;
4722 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4723 ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
4724}
4725
4726void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
4727{
4728 GL2Encoder *ctx = (GL2Encoder*)self;
4729 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4730 ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
4731}
4732
4733void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4734{
4735 GL2Encoder *ctx = (GL2Encoder*)self;
4736 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4737 ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
4738}
4739
4740void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
4741{
4742 GL2Encoder *ctx = (GL2Encoder*)self;
4743 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4744 ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
4745}
4746
4747void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4748{
4749 GL2Encoder *ctx = (GL2Encoder*)self;
4750 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4751 ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
4752}
4753
4754void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
4755{
4756 GL2Encoder *ctx = (GL2Encoder*)self;
4757 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4758 ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
4759}
4760
4761void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4762{
4763 GL2Encoder *ctx = (GL2Encoder*)self;
4764 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4765 ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
4766}
4767
4768void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4769{
4770 GL2Encoder *ctx = (GL2Encoder*)self;
4771 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4772 ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
4773}
4774
4775void GL2Encoder::s_glProgramUniformMatrix2x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4776{
4777 GL2Encoder *ctx = (GL2Encoder*)self;
4778 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4779 ctx->m_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
4780}
4781
4782void GL2Encoder::s_glProgramUniformMatrix2x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4783{
4784 GL2Encoder *ctx = (GL2Encoder*)self;
4785 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4786 ctx->m_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
4787}
4788
4789void GL2Encoder::s_glProgramUniformMatrix3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4790{
4791 GL2Encoder *ctx = (GL2Encoder*)self;
4792 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4793 ctx->m_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
4794}
4795
4796void GL2Encoder::s_glProgramUniformMatrix3x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4797{
4798 GL2Encoder *ctx = (GL2Encoder*)self;
4799 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4800 ctx->m_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
4801}
4802
4803void GL2Encoder::s_glProgramUniformMatrix3x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4804{
4805 GL2Encoder *ctx = (GL2Encoder*)self;
4806 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4807 ctx->m_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
4808}
4809
4810void GL2Encoder::s_glProgramUniformMatrix4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4811{
4812 GL2Encoder *ctx = (GL2Encoder*)self;
4813 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4814 ctx->m_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
4815}
4816
4817void GL2Encoder::s_glProgramUniformMatrix4x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4818{
4819 GL2Encoder *ctx = (GL2Encoder*)self;
4820 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4821 ctx->m_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
4822}
4823
4824void GL2Encoder::s_glProgramUniformMatrix4x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4825{
4826 GL2Encoder *ctx = (GL2Encoder*)self;
4827 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4828 ctx->m_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
4829}
4830
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004831void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) {
4832 GL2Encoder* ctx = (GL2Encoder*)self;
4833 ctx->m_glProgramParameteri_enc(self, program, pname, value);
4834}
4835
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004836void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
4837{
4838 GL2Encoder *ctx = (GL2Encoder*)self;
4839 GLClientState* state = ctx->m_state;
4840 GLSharedGroupPtr shared = ctx->m_shared;
4841
4842 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4843 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4844 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4845
4846 ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
4847 state->associateProgramWithPipeline(program, pipeline);
4848
4849 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4850 if (state->currentProgram()) {
4851 return;
4852 }
4853
4854 // Otherwise, update host texture 2D bindings.
4855 ctx->updateHostTexture2DBindingsFromProgramData(program);
4856}
4857
4858void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
4859{
4860 GL2Encoder *ctx = (GL2Encoder*)self;
4861 GLClientState* state = ctx->m_state;
4862
4863 ctx->m_glBindProgramPipeline_enc(self, pipeline);
4864
4865 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4866 if (!pipeline || state->currentProgram()) {
4867 return;
4868 }
4869
4870 GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
4871 for (; it != state->programPipelineEnd(); ++it) {
4872 if (it->second == pipeline) {
4873 ctx->updateHostTexture2DBindingsFromProgramData(it->first);
4874 }
4875 }
4876}
4877
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004878void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
4879 GL2Encoder *ctx = (GL2Encoder*)self;
4880 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4881 if (bufSize == 0) {
4882 if (length) *length = 0;
4883 return;
4884 }
4885
4886 // Avoid modifying |name| if |*length| < bufSize.
4887 GLint* intermediate = new GLint[bufSize];
4888 GLsizei* myLength = length ? length : new GLsizei;
4889 bool needFreeLength = length == NULL;
4890
4891 ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
4892 GLsizei writtenInts = *myLength;
4893 memcpy(params, intermediate, writtenInts * sizeof(GLint));
4894
4895 delete [] intermediate;
4896 if (needFreeLength)
4897 delete myLength;
4898}
4899
4900GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
4901 GL2Encoder *ctx = (GL2Encoder*)self;
4902 return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
4903}
4904
4905GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
4906 GL2Encoder *ctx = (GL2Encoder*)self;
4907 return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
4908}
4909
4910void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
4911 GL2Encoder *ctx = (GL2Encoder*)self;
4912 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4913 if (bufSize == 0) {
4914 if (length) *length = 0;
4915 return;
4916 }
4917
4918 // Avoid modifying |name| if |*length| < bufSize.
4919 char* intermediate = new char[bufSize];
4920 GLsizei* myLength = length ? length : new GLsizei;
4921 bool needFreeLength = length == NULL;
4922
4923 ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
4924 GLsizei writtenStrLen = *myLength;
4925 memcpy(name, intermediate, writtenStrLen + 1);
4926
4927 delete [] intermediate;
4928 if (needFreeLength)
4929 delete myLength;
4930}
4931
4932void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
4933 GL2Encoder *ctx = (GL2Encoder*)self;
4934 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4935 if (bufSize == 0) {
4936 if (length) *length = 0;
4937 return;
4938 }
4939
4940 // Avoid modifying |infoLog| if |*length| < bufSize.
4941 GLchar* intermediate = new GLchar[bufSize];
4942 GLsizei* myLength = length ? length : new GLsizei;
4943 bool needFreeLength = length == NULL;
4944
4945 ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
4946 GLsizei writtenStrLen = *myLength;
4947 memcpy(infoLog, intermediate, writtenStrLen + 1);
4948
4949 delete [] intermediate;
4950 if (needFreeLength)
4951 delete myLength;
4952}
4953
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004954void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
4955 GL2Encoder *ctx = (GL2Encoder*)self;
4956 GLClientState* state = ctx->m_state;
4957
Lingfeng Yang07289902017-01-27 12:26:19 -08004958 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004959 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4960
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004961 state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false);
4962 ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset);
4963}
4964
4965void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
4966 GL2Encoder *ctx = (GL2Encoder*)self;
4967 GLClientState* state = ctx->m_state;
4968
Lingfeng Yang07289902017-01-27 12:26:19 -08004969 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004970 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4971
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004972 state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true);
4973 ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset);
4974}
4975
4976void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004977 GL2Encoder *ctx = (GL2Encoder*)self;
4978 GLClientState* state = ctx->m_state;
4979
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004980 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4981
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004982 state->setVertexBindingDivisor(bindingindex, divisor);
4983 ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor);
4984}
4985
4986void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) {
4987 GL2Encoder *ctx = (GL2Encoder*)self;
4988 GLClientState* state = ctx->m_state;
Lingfeng Yang07289902017-01-27 12:26:19 -08004989 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004990 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004991
4992 state->setVertexAttribBinding(attribindex, bindingindex);
4993 ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex);
4994}
4995
4996void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
4997 GL2Encoder *ctx = (GL2Encoder*)self;
4998 GLClientState* state = ctx->m_state;
4999
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005000 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
5001
5002 GLint maxStride;
5003 ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
5004 SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE);
5005
5006 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5007
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005008 state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride);
5009 ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride);
5010}
5011
5012void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) {
5013 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005014 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005015
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005016 bool hasClientArrays = false;
5017 ctx->getVBOUsage(&hasClientArrays, NULL);
5018
5019 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
5020 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5021 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
5022
5023 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005024 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005025 // BufferData* buf = ctx->getBufferData(target);
5026 // if (buf) {
5027 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
5028 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005029 ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect);
5030 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005031 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
5032 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005033 ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize);
5034 }
5035}
5036
5037void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) {
5038 GL2Encoder *ctx = (GL2Encoder*)self;
5039
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005040 GLClientState* state = ctx->m_state;
5041
5042 bool hasClientArrays = false;
5043 ctx->getVBOUsage(&hasClientArrays, NULL);
5044
5045 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
5046 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5047 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
5048
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005049 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005050
5051 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005052 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005053 // BufferData* buf = ctx->getBufferData(target);
5054 // if (buf) {
5055 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
5056 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005057 ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect);
5058 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005059 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
5060 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005061 ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize);
5062 }
5063
5064}
5065
5066void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
5067 GL2Encoder *ctx = (GL2Encoder*)self;
5068 GLClientState* state = ctx->m_state;
5069
5070 SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
5071 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
5072 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
5073 SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
5074 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005075 GLint max_samples;
5076 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
5077 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005078
5079 state->setBoundTextureInternalFormat(target, internalformat);
5080 state->setBoundTextureDims(target, 0, width, height, 1);
5081 state->setBoundTextureImmutableFormat(target);
5082 state->setBoundTextureSamples(target, samples);
5083
5084 ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
5085}
5086