blob: 8b07e66a05869d4d22e3a92659dcf8af41d17a00 [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();
Lingfeng Yang72ecf472018-06-11 14:20:14 -0700429 if (hostError == GL_NO_ERROR && mTarget) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700430 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
539 ctx->m_shared->updateBufferData(bufferId, size, (void*)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
552 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
553 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",
1136 hasClientArrays, i, bufferObject, buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen);
1137 }
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
keunyoungb85b2752013-03-08 12:28:03 -08001258 bool adjustIndices = true;
1259 if (ctx->m_state->currentIndexVbo() != 0) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001260 if (!has_client_vertex_arrays) {
1261 ctx->sendVertexAttributes(0, maxIndex + 1, false);
keunyoungb85b2752013-03-08 12:28:03 -08001262 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -07001263 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001264 ctx->flushDrawCall();
keunyoungb85b2752013-03-08 12:28:03 -08001265 adjustIndices = false;
1266 } else {
1267 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1268 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001269 }
1270 }
1271 if (adjustIndices) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001272 void *adjustedIndices =
1273 ctx->recenterIndices(indices,
1274 type,
1275 count,
1276 minIndex);
keunyoungb85b2752013-03-08 12:28:03 -08001277
keunyoungb85b2752013-03-08 12:28:03 -08001278 if (has_indirect_arrays || 1) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001279 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
keunyoungb85b2752013-03-08 12:28:03 -08001280 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
1281 count * glSizeof(type));
1282 // XXX - OPTIMIZATION (see the other else branch) should be implemented
1283 if(!has_indirect_arrays) {
1284 //ALOGD("unoptimized drawelements !!!\n");
1285 }
1286 } else {
1287 // we are all direct arrays and immidate mode index array -
1288 // rebuild the arrays and the index array;
1289 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
1290 }
1291 }
1292}
1293
1294
1295GLint * GL2Encoder::getCompressedTextureFormats()
1296{
1297 if (m_compressedTextureFormats == NULL) {
1298 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
1299 &m_num_compressedTextureFormats);
1300 if (m_num_compressedTextureFormats > 0) {
1301 // get number of texture formats;
1302 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
1303 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
1304 }
1305 }
1306 return m_compressedTextureFormats;
1307}
1308
1309// Replace uses of samplerExternalOES with sampler2D, recording the names of
1310// modified shaders in data. Also remove
1311// #extension GL_OES_EGL_image_external : require
1312// statements.
1313//
1314// This implementation assumes the input has already been pre-processed. If not,
1315// a few cases will be mishandled:
1316//
1317// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
1318// the following code:
1319// #if 1
1320// uniform sampler2D mySampler;
1321// #else
1322// uniform samplerExternalOES mySampler;
1323// #endif
1324//
1325// 2. Comments that look like sampler declarations will be incorrectly modified
1326// and recorded:
1327// // samplerExternalOES hahaFooledYou
1328//
1329// 3. However, GLSL ES does not have a concatentation operator, so things like
1330// this (valid in C) are invalid and not a problem:
1331// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
1332// SAMPLER(ExternalOES, mySampler);
1333//
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001334
1335static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
1336static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
1337static const char STR_DEFINE[] = "#define";
1338
1339static std::vector<std::string> getSamplerExternalAliases(char* str) {
1340 std::vector<std::string> res;
1341
1342 res.push_back(STR_SAMPLER_EXTERNAL_OES);
1343
1344 // -- capture #define x samplerExternalOES
1345 char* c = str;
1346 while ((c = strstr(c, STR_DEFINE))) {
1347 // Don't push it if samplerExternalOES is not even there.
1348 char* samplerExternalOES_next = strstr(c, STR_SAMPLER_EXTERNAL_OES);
1349 if (!samplerExternalOES_next) break;
1350
1351 bool prevIdent = false;
1352
1353 std::vector<std::string> idents;
1354 std::string curr;
1355
1356 while (*c != '\0') {
1357
1358 if (isspace(*c)) {
1359 if (prevIdent) {
1360 idents.push_back(curr);
1361 curr = "";
1362 }
1363 }
1364
1365 if (*c == '\n' || idents.size() == 3) break;
1366
1367 if (isalpha(*c) || *c == '_') {
1368 curr.push_back(*c);
1369 prevIdent = true;
1370 }
1371
1372 ++c;
1373 }
1374
1375 if (idents.size() != 3) continue;
1376
1377 const std::string& defineLhs = idents[1];
1378 const std::string& defineRhs = idents[2];
1379
1380 if (defineRhs == STR_SAMPLER_EXTERNAL_OES) {
1381 res.push_back(defineLhs);
1382 }
1383
1384 if (*c == '\0') break;
1385 }
1386
1387 return res;
1388}
1389
1390static bool replaceExternalSamplerUniformDefinition(char* str, const std::string& samplerExternalType, ShaderData* data) {
1391 // -- replace "samplerExternalOES" with "sampler2D" and record name
1392 char* c = str;
1393 while ((c = strstr(c, samplerExternalType.c_str()))) {
1394 // Make sure "samplerExternalOES" isn't a substring of a larger token
1395 if (c == str || !isspace(*(c-1))) {
1396 c++;
1397 continue;
1398 }
1399 char* sampler_start = c;
1400 c += samplerExternalType.size();
1401 if (!isspace(*c) && *c != '\0') {
1402 continue;
1403 }
1404
1405 // capture sampler name
1406 while (isspace(*c) && *c != '\0') {
1407 c++;
1408 }
1409 if (!isalpha(*c) && *c != '_') {
1410 // not an identifier
1411 return false;
1412 }
1413 char* name_start = c;
1414 do {
1415 c++;
1416 } while (isalnum(*c) || *c == '_');
1417 data->samplerExternalNames.push_back(
1418 android::String8(name_start, c - name_start));
1419
1420 // We only need to perform a string replacement for the original
1421 // occurrence of samplerExternalOES if a #define was used.
1422 //
1423 // The important part was to record the name in
1424 // |data->samplerExternalNames|.
1425 if (samplerExternalType == STR_SAMPLER_EXTERNAL_OES) {
1426 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
1427 }
1428 }
1429
1430 return true;
1431}
1432
keunyoungb85b2752013-03-08 12:28:03 -08001433static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
1434{
1435 static const char STR_HASH_EXTENSION[] = "#extension";
1436 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
Lingfeng Yang3546c4d2018-04-10 12:34:30 -07001437 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3[] = "GL_OES_EGL_image_external_essl3";
keunyoungb85b2752013-03-08 12:28:03 -08001438
1439 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
1440 char* c = str;
1441 while ((c = strstr(c, STR_HASH_EXTENSION))) {
1442 char* start = c;
1443 c += sizeof(STR_HASH_EXTENSION)-1;
1444 while (isspace(*c) && *c != '\0') {
1445 c++;
1446 }
Lingfeng Yang3546c4d2018-04-10 12:34:30 -07001447
1448 bool hasBaseImageExternal =
1449 !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
1450 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL) - 1);
1451 bool hasEssl3ImageExternal =
1452 !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3,
1453 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3) - 1);
1454
1455 if (hasBaseImageExternal || hasEssl3ImageExternal)
keunyoungb85b2752013-03-08 12:28:03 -08001456 {
1457 // #extension statements are terminated by end of line
1458 c = start;
1459 while (*c != '\0' && *c != '\r' && *c != '\n') {
1460 *c++ = ' ';
1461 }
1462 }
1463 }
1464
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001465 std::vector<std::string> samplerExternalAliases =
1466 getSamplerExternalAliases(str);
keunyoungb85b2752013-03-08 12:28:03 -08001467
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001468 for (size_t i = 0; i < samplerExternalAliases.size(); i++) {
1469 if (!replaceExternalSamplerUniformDefinition(
1470 str, samplerExternalAliases[i], data))
keunyoungb85b2752013-03-08 12:28:03 -08001471 return false;
keunyoungb85b2752013-03-08 12:28:03 -08001472 }
1473
1474 return true;
1475}
1476
Bo Hu73568cd2015-01-20 16:29:50 -08001477void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
1478{
1479 GL2Encoder* ctx = (GL2Encoder*)self;
1480 // Although it is not supported, need to set proper error code.
1481 SET_ERROR_IF(1, GL_INVALID_ENUM);
1482}
1483
David 'Digit' Turner02fdb692014-10-30 18:07:56 +01001484void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -08001485{
1486 GL2Encoder* ctx = (GL2Encoder*)self;
1487 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001488 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(shader), GL_INVALID_VALUE);
Tina Zhang7a84f652014-12-04 12:37:30 +08001489 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
1490 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001491
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001492 // Track original sources---they may be translated in the backend
1493 std::vector<std::string> orig_sources;
1494 for (int i = 0; i < count; i++) {
1495 orig_sources.push_back(std::string((const char*)(string[i])));
1496 }
1497 shaderData->sources = orig_sources;
1498
keunyoungb85b2752013-03-08 12:28:03 -08001499 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
1500 char *str = new char[len + 1];
1501 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
1502
1503 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
1504 // Perhaps we can borrow Mesa's pre-processor?
1505
1506 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001507 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001508 ctx->setError(GL_OUT_OF_MEMORY);
1509 return;
1510 }
keunyoungb85b2752013-03-08 12:28:03 -08001511 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001512 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001513}
1514
1515void GL2Encoder::s_glFinish(void *self)
1516{
1517 GL2Encoder *ctx = (GL2Encoder *)self;
1518 ctx->glFinishRoundTrip(self);
1519}
1520
1521void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1522{
1523 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -08001524 bool isProgram = ctx->m_shared->isProgram(program);
1525 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
1526 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
1527
keunyoungb85b2752013-03-08 12:28:03 -08001528 ctx->m_glLinkProgram_enc(self, program);
1529
1530 GLint linkStatus = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07001531 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001532 if (!linkStatus) {
keunyoungb85b2752013-03-08 12:28:03 -08001533 return;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001534 }
keunyoungb85b2752013-03-08 12:28:03 -08001535
1536 //get number of active uniforms in the program
1537 GLint numUniforms=0;
1538 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
1539 ctx->m_shared->initProgramData(program,numUniforms);
1540
1541 //get the length of the longest uniform name
1542 GLint maxLength=0;
1543 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
1544
1545 GLint size;
1546 GLenum type;
1547 GLchar *name = new GLchar[maxLength+1];
1548 GLint location;
1549 //for each active uniform, get its size and starting location.
1550 for (GLint i=0 ; i<numUniforms ; ++i)
1551 {
1552 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1553 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1554 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1555 }
1556 ctx->m_shared->setupLocationShiftWAR(program);
1557
1558 delete[] name;
1559}
1560
1561void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1562{
1563 GL2Encoder *ctx = (GL2Encoder*)self;
1564 ctx->m_glDeleteProgram_enc(self, program);
1565
1566 ctx->m_shared->deleteProgramData(program);
1567}
1568
1569void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1570{
1571 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001572 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001573 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001574 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1575 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1576 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1577 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1578}
1579void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1580{
1581 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001582 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001583 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001584 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1585 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1586 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1587 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1588}
1589
1590GLuint GL2Encoder::s_glCreateProgram(void * self)
1591{
1592 GL2Encoder *ctx = (GL2Encoder*)self;
1593 GLuint program = ctx->m_glCreateProgram_enc(self);
1594 if (program!=0)
1595 ctx->m_shared->addProgramData(program);
1596 return program;
1597}
1598
1599GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1600{
1601 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001602 RET_AND_SET_ERROR_IF(!GLESv2Validation::shaderType(ctx, shaderType), GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001603 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1604 if (shader != 0) {
1605 if (!ctx->m_shared->addShaderData(shader)) {
1606 ctx->m_glDeleteShader_enc(self, shader);
1607 return 0;
1608 }
1609 }
1610 return shader;
1611}
1612
bohu56bf82f2014-10-17 15:35:48 -07001613void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1614 GLsizei* count, GLuint* shaders)
1615{
1616 GL2Encoder *ctx = (GL2Encoder*)self;
1617 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1618 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1619}
1620
1621void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1622 GLsizei* length, GLchar* source)
1623{
1624 GL2Encoder *ctx = (GL2Encoder*)self;
1625 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1626 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001627 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
1628 if (shaderData) {
1629 std::string returned;
1630 int curr_len = 0;
1631 for (int i = 0; i < shaderData->sources.size(); i++) {
1632 if (curr_len + shaderData->sources[i].size() < bufsize - 1) {
1633 returned += shaderData->sources[i];
1634 } else {
1635 returned += shaderData->sources[i].substr(0, bufsize - 1 - curr_len);
1636 break;
1637 }
1638 }
1639 memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize);
1640 }
bohu56bf82f2014-10-17 15:35:48 -07001641}
1642
1643void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1644 GLsizei* length, GLchar* infolog)
1645{
1646 GL2Encoder *ctx = (GL2Encoder*)self;
1647 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1648 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1649}
1650
1651void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1652 GLsizei* length, GLchar* infolog)
1653{
1654 GL2Encoder *ctx = (GL2Encoder*)self;
1655 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1656 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1657}
1658
keunyoungb85b2752013-03-08 12:28:03 -08001659void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1660{
1661 GL2Encoder *ctx = (GL2Encoder*)self;
1662 ctx->m_glDeleteShader_enc(self,shader);
1663 ctx->m_shared->unrefShaderData(shader);
1664}
1665
1666void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1667{
1668 GL2Encoder *ctx = (GL2Encoder*)self;
1669 ctx->m_glAttachShader_enc(self, program, shader);
1670 ctx->m_shared->attachShader(program, shader);
1671}
1672
1673void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1674{
1675 GL2Encoder *ctx = (GL2Encoder*)self;
1676 ctx->m_glDetachShader_enc(self, program, shader);
1677 ctx->m_shared->detachShader(program, shader);
1678}
1679
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001680int sArrIndexOfUniformExpr(const char* name, int* err) {
1681 *err = 0;
1682 int arrIndex = 0;
1683 int namelen = strlen(name);
1684 if (name[namelen-1] == ']') {
1685 const char *brace = strrchr(name,'[');
1686 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1687 *err = 1; return 0;
1688 }
1689 }
1690 return arrIndex;
1691}
1692
keunyoungb85b2752013-03-08 12:28:03 -08001693int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1694{
1695 if (!name) return -1;
1696
1697 GL2Encoder *ctx = (GL2Encoder*)self;
1698
1699 // if we need the uniform location WAR
1700 // parse array index from the end of the name string
1701 int arrIndex = 0;
1702 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1703 if (needLocationWAR) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001704 int err;
1705 arrIndex = sArrIndexOfUniformExpr(name, &err);
1706 if (err) return -1;
keunyoungb85b2752013-03-08 12:28:03 -08001707 }
1708
1709 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1710 if (hostLoc >= 0 && needLocationWAR) {
1711 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1712 }
1713 return hostLoc;
1714}
1715
1716bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1717{
1718 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1719 return false;
1720
1721 m_state->setActiveTextureUnit(texUnit);
1722
1723 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1724 if (newTarget != oldTarget) {
1725 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1726 m_state->disableTextureTarget(GL_TEXTURE_2D);
1727 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1728 } else {
1729 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1730 m_state->enableTextureTarget(GL_TEXTURE_2D);
1731 }
1732 m_glActiveTexture_enc(this, texUnit);
1733 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1734 m_state->getBoundTexture(newTarget));
1735 return true;
1736 }
1737
1738 return false;
1739}
1740
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001741void GL2Encoder::updateHostTexture2DBindingsFromProgramData(GLuint program) {
1742 GL2Encoder *ctx = this;
keunyoungb85b2752013-03-08 12:28:03 -08001743 GLClientState* state = ctx->m_state;
1744 GLSharedGroupPtr shared = ctx->m_shared;
1745
keunyoungb85b2752013-03-08 12:28:03 -08001746 GLenum origActiveTexture = state->getActiveTextureUnit();
1747 GLenum hostActiveTexture = origActiveTexture;
1748 GLint samplerIdx = -1;
1749 GLint samplerVal;
1750 GLenum samplerTarget;
1751 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1752 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1753 continue;
1754 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001755 samplerTarget))
keunyoungb85b2752013-03-08 12:28:03 -08001756 {
1757 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1758 }
1759 }
1760 state->setActiveTextureUnit(origActiveTexture);
1761 if (hostActiveTexture != origActiveTexture) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001762 ctx->m_glActiveTexture_enc(ctx, origActiveTexture);
keunyoungb85b2752013-03-08 12:28:03 -08001763 }
1764}
1765
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001766void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1767{
1768 GL2Encoder *ctx = (GL2Encoder*)self;
1769 GLSharedGroupPtr shared = ctx->m_shared;
1770
1771 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
1772 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1773
1774 ctx->m_glUseProgram_enc(self, program);
1775 ctx->m_state->setCurrentProgram(program);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001776 ctx->m_state->setCurrentShaderProgram(program);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001777
1778 ctx->updateHostTexture2DBindingsFromProgramData(program);
1779}
1780
keunyoungb85b2752013-03-08 12:28:03 -08001781void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1782{
1783 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001784 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001785 ctx->m_glUniform1f_enc(self, hostLoc, x);
1786}
1787
1788void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1789{
1790 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001791 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001792 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1793}
1794
1795void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1796{
1797 GL2Encoder *ctx = (GL2Encoder*)self;
1798 GLClientState* state = ctx->m_state;
1799 GLSharedGroupPtr shared = ctx->m_shared;
1800
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001801 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001802 ctx->m_glUniform1i_enc(self, hostLoc, x);
1803
1804 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001805 if (shared->setSamplerUniform(state->currentShaderProgram(), location, x, &target)) {
keunyoungb85b2752013-03-08 12:28:03 -08001806 GLenum origActiveTexture = state->getActiveTextureUnit();
1807 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1808 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1809 }
1810 state->setActiveTextureUnit(origActiveTexture);
1811 }
1812}
1813
1814void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1815{
1816 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001817 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001818 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1819}
1820
1821void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1822{
1823 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001824 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001825 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1826}
1827
1828void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1829{
1830 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001831 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001832 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1833}
1834
1835void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1836{
1837 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001838 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001839 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1840}
1841
1842void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1843{
1844 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001845 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001846 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1847}
1848
1849void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1850{
1851 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001852 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001853 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1854}
1855
1856void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1857{
1858 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001859 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001860 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1861}
1862
1863void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1864{
1865 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001866 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001867 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1868}
1869
1870void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1871{
1872 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001873 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001874 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1875}
1876
1877void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1878{
1879 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001880 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001881 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1882}
1883
1884void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1885{
1886 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001887 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001888 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1889}
1890
1891void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1892{
1893 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001894 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001895 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1896}
1897
1898void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1899{
1900 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001901 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001902 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1903}
1904
1905void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1906{
1907 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001908 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001909 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1910}
1911
1912void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1913{
1914 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001915 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001916 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1917}
1918
1919void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1920{
1921 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001922 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001923 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1924}
1925
1926void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1927{
1928 GL2Encoder* ctx = (GL2Encoder*)self;
1929 GLClientState* state = ctx->m_state;
1930 GLenum err;
1931
1932 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1933
1934 ctx->m_glActiveTexture_enc(ctx, texture);
1935}
1936
1937void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1938{
1939 GL2Encoder* ctx = (GL2Encoder*)self;
1940 GLClientState* state = ctx->m_state;
1941 GLenum err;
1942 GLboolean firstUse;
1943
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001944 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -08001945 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1946
1947 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1948 ctx->m_glBindTexture_enc(ctx, target, texture);
1949 return;
1950 }
1951
1952 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1953
1954 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1955 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1956 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1957 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1958 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1959 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1960 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1961 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1962
1963 if (target != priorityTarget) {
1964 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1965 state->getBoundTexture(GL_TEXTURE_2D));
1966 }
1967 }
1968
1969 if (target == priorityTarget) {
1970 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1971 }
1972}
1973
1974void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1975{
1976 GL2Encoder* ctx = (GL2Encoder*)self;
1977 GLClientState* state = ctx->m_state;
1978
1979 state->deleteTextures(n, textures);
1980 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1981}
1982
1983void GL2Encoder::s_glGetTexParameterfv(void* self,
1984 GLenum target, GLenum pname, GLfloat* params)
1985{
1986 GL2Encoder* ctx = (GL2Encoder*)self;
1987 const GLClientState* state = ctx->m_state;
1988
1989 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1990 ctx->override2DTextureTarget(target);
1991 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001992 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001993 } else {
1994 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1995 }
1996}
1997
1998void GL2Encoder::s_glGetTexParameteriv(void* self,
1999 GLenum target, GLenum pname, GLint* params)
2000{
2001 GL2Encoder* ctx = (GL2Encoder*)self;
2002 const GLClientState* state = ctx->m_state;
2003
2004 switch (pname) {
2005 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
2006 *params = 1;
2007 break;
2008
2009 default:
2010 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2011 ctx->override2DTextureTarget(target);
2012 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002013 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002014 } else {
2015 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
2016 }
2017 break;
2018 }
2019}
2020
2021static bool isValidTextureExternalParam(GLenum pname, GLenum param)
2022{
2023 switch (pname) {
2024 case GL_TEXTURE_MIN_FILTER:
2025 case GL_TEXTURE_MAG_FILTER:
2026 return param == GL_NEAREST || param == GL_LINEAR;
2027
2028 case GL_TEXTURE_WRAP_S:
2029 case GL_TEXTURE_WRAP_T:
2030 return param == GL_CLAMP_TO_EDGE;
2031
2032 default:
2033 return true;
2034 }
2035}
2036
2037void GL2Encoder::s_glTexParameterf(void* self,
2038 GLenum target, GLenum pname, GLfloat param)
2039{
2040 GL2Encoder* ctx = (GL2Encoder*)self;
2041 const GLClientState* state = ctx->m_state;
2042
2043 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2044 !isValidTextureExternalParam(pname, (GLenum)param)),
2045 GL_INVALID_ENUM);
2046
2047 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2048 ctx->override2DTextureTarget(target);
2049 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002050 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002051 } else {
2052 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
2053 }
2054}
2055
2056void GL2Encoder::s_glTexParameterfv(void* self,
2057 GLenum target, GLenum pname, const GLfloat* params)
2058{
2059 GL2Encoder* ctx = (GL2Encoder*)self;
2060 const GLClientState* state = ctx->m_state;
2061
2062 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2063 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2064 GL_INVALID_ENUM);
2065
2066 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2067 ctx->override2DTextureTarget(target);
2068 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002069 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002070 } else {
2071 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
2072 }
2073}
2074
2075void GL2Encoder::s_glTexParameteri(void* self,
2076 GLenum target, GLenum pname, GLint param)
2077{
2078 GL2Encoder* ctx = (GL2Encoder*)self;
2079 const GLClientState* state = ctx->m_state;
2080
2081 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2082 !isValidTextureExternalParam(pname, (GLenum)param)),
2083 GL_INVALID_ENUM);
2084
2085 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2086 ctx->override2DTextureTarget(target);
2087 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002088 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002089 } else {
2090 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
2091 }
2092}
2093
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002094static int ilog2(uint32_t x) {
2095 int p = 0;
2096 while ((1 << p) < x)
2097 p++;
2098 return p;
2099}
2100
bohu26a92982014-11-25 16:50:37 -08002101void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
2102 GLint internalformat, GLsizei width, GLsizei height, GLint border,
2103 GLenum format, GLenum type, const GLvoid* pixels)
2104{
2105 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07002106 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002107
2108 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2109 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2110 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2111 // If unpack buffer is nonzero, verify unmapped state.
2112 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2113
2114 GLint max_texture_size;
2115 GLint max_cube_map_texture_size;
2116 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2117 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2118 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2119 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2120 SET_ERROR_IF((target == GL_TEXTURE_CUBE_MAP) &&
2121 (level > ilog2(max_cube_map_texture_size)), GL_INVALID_VALUE);
2122 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2123 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2124 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2125 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && width > max_cube_map_texture_size, GL_INVALID_VALUE);
2126 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && height > max_cube_map_texture_size, GL_INVALID_VALUE);
2127 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
2128 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2129 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2130 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2131 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 0) >
2132 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2133 GL_INVALID_OPERATION);
2134 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2135 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2136 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2137 glSizeof(type)),
2138 GL_INVALID_OPERATION);
2139 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2140 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2141 ((uintptr_t)pixels % glSizeof(type)),
2142 GL_INVALID_OPERATION);
2143 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
2144
2145 GLenum stateTarget = target;
2146 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2147 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2148 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2149 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2150 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2151 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2152 stateTarget = GL_TEXTURE_CUBE_MAP;
2153
2154 state->setBoundTextureInternalFormat(stateTarget, internalformat);
2155 state->setBoundTextureFormat(stateTarget, format);
2156 state->setBoundTextureType(stateTarget, type);
2157 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2158
bohu26a92982014-11-25 16:50:37 -08002159 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2160 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002161 }
Lingfeng Yang69066602016-04-12 09:29:11 -07002162
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002163 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2164 ctx->glTexImage2DOffsetAEMU(
2165 ctx, target, level, internalformat,
2166 width, height, border,
2167 format, type, (uintptr_t)pixels);
bohu26a92982014-11-25 16:50:37 -08002168 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002169 ctx->m_glTexImage2D_enc(
2170 ctx, target, level, internalformat,
2171 width, height, border,
2172 format, type, pixels);
2173 }
2174
2175 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2176 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08002177 }
2178}
2179
Yahan Zhou2a208292016-06-22 15:36:04 -07002180void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
2181 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
2182 GLenum type, const GLvoid* pixels)
2183{
2184 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002185 GLClientState* state = ctx->m_state;
2186
2187 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2188 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2189 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2190 // If unpack buffer is nonzero, verify unmapped state.
2191 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2192
2193 GLint max_texture_size;
2194 GLint max_cube_map_texture_size;
2195 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2196 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2197 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2198 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2199 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) &&
2200 level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2201 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2202 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2203
2204 GLuint tex = state->getBoundTexture(target);
2205 GLsizei neededWidth = xoffset + width;
2206 GLsizei neededHeight = yoffset + height;
2207 GLsizei neededDepth = 1;
2208
2209 if (tex && !state->queryTexEGLImageBacked(tex)) {
2210 SET_ERROR_IF(
2211 (neededWidth > state->queryTexWidth(level, tex) ||
2212 neededHeight > state->queryTexHeight(level, tex) ||
2213 neededDepth > state->queryTexDepth(level, tex)),
2214 GL_INVALID_VALUE);
2215 }
2216
2217 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2218 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2219 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2220 (state->pboNeededDataSize(width, height, 1, format, type, 0) >
2221 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2222 GL_INVALID_OPERATION);
2223 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2224 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2225 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2226 glSizeof(type)),
2227 GL_INVALID_OPERATION);
2228 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !pixels, GL_INVALID_OPERATION);
Yahan Zhou2a208292016-06-22 15:36:04 -07002229
2230 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2231 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002232 }
2233
2234 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2235 ctx->glTexSubImage2DOffsetAEMU(
2236 ctx, target, level,
2237 xoffset, yoffset, width, height,
2238 format, type, (uintptr_t)pixels);
Yahan Zhou2a208292016-06-22 15:36:04 -07002239 } else {
2240 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
2241 height, format, type, pixels);
2242 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002243
2244 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2245 ctx->restore2DTextureTarget(target);
2246 }
Yahan Zhou2a208292016-06-22 15:36:04 -07002247}
bohu26a92982014-11-25 16:50:37 -08002248
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002249void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
2250 GLenum internalformat, GLint x, GLint y,
2251 GLsizei width, GLsizei height, GLint border)
2252{
2253 GL2Encoder* ctx = (GL2Encoder*)self;
2254 GLClientState* state = ctx->m_state;
2255
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002256 SET_ERROR_IF(ctx->glCheckFramebufferStatus(ctx, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
2257 GL_INVALID_FRAMEBUFFER_OPERATION);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002258 // This is needed to work around underlying OpenGL drivers
2259 // (such as those feeding some some AMD GPUs) that expect
2260 // positive components of cube maps to be defined _before_
2261 // the negative components (otherwise a segfault occurs).
2262 GLenum extraTarget =
2263 state->copyTexImageLuminanceCubeMapAMDWorkaround
2264 (target, level, internalformat);
2265
2266 if (extraTarget) {
2267 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
2268 x, y, width, height, border);
2269 }
2270
2271 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
2272 x, y, width, height, border);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002273
2274 state->setBoundTextureInternalFormat(target, internalformat);
2275 state->setBoundTextureDims(target, level, width, height, 1);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002276}
2277
keunyoungb85b2752013-03-08 12:28:03 -08002278void GL2Encoder::s_glTexParameteriv(void* self,
2279 GLenum target, GLenum pname, const GLint* params)
2280{
2281 GL2Encoder* ctx = (GL2Encoder*)self;
2282 const GLClientState* state = ctx->m_state;
2283
2284 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2285 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2286 GL_INVALID_ENUM);
2287
2288 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2289 ctx->override2DTextureTarget(target);
2290 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002291 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002292 } else {
2293 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
2294 }
2295}
2296
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002297bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
2298 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
2299 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2300}
2301
keunyoungb85b2752013-03-08 12:28:03 -08002302void GL2Encoder::override2DTextureTarget(GLenum target)
2303{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002304 if (texture2DNeedsOverride(target)) {
2305 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2306 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08002307 }
2308}
2309
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002310void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08002311{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002312 if (texture2DNeedsOverride(target)) {
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002313 GLuint priorityEnabledBoundTexture =
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002314 m_state->getBoundTexture(
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002315 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D));
2316 GLuint texture2DBoundTexture =
2317 m_state->getBoundTexture(GL_TEXTURE_2D);
2318 if (!priorityEnabledBoundTexture) {
2319 m_glBindTexture_enc(this, GL_TEXTURE_2D, texture2DBoundTexture);
2320 } else {
2321 m_glBindTexture_enc(this, GL_TEXTURE_2D, priorityEnabledBoundTexture);
2322 }
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002323 }
keunyoungb85b2752013-03-08 12:28:03 -08002324}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002325
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002326void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2327 m_state->setBoundEGLImage(target, eglImage);
2328}
2329
2330
2331GLuint GL2Encoder::boundBuffer(GLenum target) const {
2332 return m_state->getBuffer(target);
2333}
2334
2335BufferData* GL2Encoder::getBufferData(GLenum target) const {
2336 GLuint bufferId = m_state->getBuffer(target);
2337 if (!bufferId) return NULL;
2338 return m_shared->getBufferData(bufferId);
2339}
2340
2341BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2342 if (!bufferId) return NULL;
2343 return m_shared->getBufferData(bufferId);
2344}
2345
2346bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2347 return m_shared->getBufferData(buffer)->m_mapped;
2348}
2349
2350bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2351 BufferData* buf = getBufferData(target);
2352 if (!buf) return false;
2353 return buf->m_mapped;
2354}
2355
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002356void GL2Encoder::s_glGenRenderbuffers(void* self,
2357 GLsizei n, GLuint* renderbuffers) {
2358 GL2Encoder* ctx = (GL2Encoder*)self;
2359 GLClientState* state = ctx->m_state;
2360
2361 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2362
2363 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2364 state->addRenderbuffers(n, renderbuffers);
2365}
2366
2367void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2368 GLsizei n, const GLuint* renderbuffers) {
2369 GL2Encoder* ctx = (GL2Encoder*)self;
2370 GLClientState* state = ctx->m_state;
2371
2372 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2373
2374 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002375
2376 // Nope, lets just leak those for now.
2377 // The spec has an *amazingly* convoluted set of conditions for when
2378 // render buffers are actually deleted:
2379 // 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.
2380 //
2381 // 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***
2382 //
2383 // So, just detach this one from the bound FBO, and ignore the rest.
2384 for (int i = 0; i < n; i++) {
2385 state->detachRbo(renderbuffers[i]);
2386 }
2387 // state->removeRenderbuffers(n, renderbuffers);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002388}
2389
2390void GL2Encoder::s_glBindRenderbuffer(void* self,
2391 GLenum target, GLuint renderbuffer) {
2392 GL2Encoder* ctx = (GL2Encoder*)self;
2393 GLClientState* state = ctx->m_state;
2394
2395 SET_ERROR_IF((target != GL_RENDERBUFFER),
2396 GL_INVALID_ENUM);
2397
2398 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2399 state->bindRenderbuffer(target, renderbuffer);
2400}
2401
Lingfeng Yang69066602016-04-12 09:29:11 -07002402void GL2Encoder::s_glRenderbufferStorage(void* self,
2403 GLenum target, GLenum internalformat,
2404 GLsizei width, GLsizei height) {
2405 GL2Encoder* ctx = (GL2Encoder*) self;
2406 GLClientState* state = ctx->m_state;
2407
2408 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002409 SET_ERROR_IF(
2410 !GLESv2Validation::rboFormat(ctx, internalformat),
2411 GL_INVALID_ENUM);
Lingfeng Yang69066602016-04-12 09:29:11 -07002412
2413 state->setBoundRenderbufferFormat(internalformat);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002414 state->setBoundRenderbufferSamples(0);
2415
Lingfeng Yang69066602016-04-12 09:29:11 -07002416 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
2417 width, height);
2418}
2419
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002420void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
2421 GLenum target, GLenum attachment,
2422 GLenum renderbuffertarget, GLuint renderbuffer) {
2423 GL2Encoder* ctx = (GL2Encoder*)self;
2424 GLClientState* state = ctx->m_state;
2425
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002426 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2427 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2428 state->attachRbo(target, attachment, renderbuffer);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002429
2430 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
2431}
2432
2433void GL2Encoder::s_glGenFramebuffers(void* self,
2434 GLsizei n, GLuint* framebuffers) {
2435 GL2Encoder* ctx = (GL2Encoder*)self;
2436 GLClientState* state = ctx->m_state;
2437
2438 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2439
2440 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2441 state->addFramebuffers(n, framebuffers);
2442}
2443
2444void GL2Encoder::s_glDeleteFramebuffers(void* self,
2445 GLsizei n, const GLuint* framebuffers) {
2446 GL2Encoder* ctx = (GL2Encoder*)self;
2447 GLClientState* state = ctx->m_state;
2448
2449 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2450
2451 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2452 state->removeFramebuffers(n, framebuffers);
2453}
2454
2455void GL2Encoder::s_glBindFramebuffer(void* self,
2456 GLenum target, GLuint framebuffer) {
2457 GL2Encoder* ctx = (GL2Encoder*)self;
2458 GLClientState* state = ctx->m_state;
2459
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002460 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002461
2462 state->bindFramebuffer(target, framebuffer);
2463
2464 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
2465}
2466
2467void GL2Encoder::s_glFramebufferTexture2D(void* self,
2468 GLenum target, GLenum attachment,
2469 GLenum textarget, GLuint texture, GLint level) {
2470 GL2Encoder* ctx = (GL2Encoder*)self;
2471 GLClientState* state = ctx->m_state;
2472
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002473 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2474 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2475 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002476
2477 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
2478}
2479
2480void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2481 GLenum target, GLenum attachment,
2482 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2483 GL2Encoder* ctx = (GL2Encoder*)self;
2484 GLClientState* state = ctx->m_state;
2485
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002486 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002487
2488 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2489}
2490
2491void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2492 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2493 GL2Encoder* ctx = (GL2Encoder*)self;
2494 const GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002495 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2496 SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2497 pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE &&
2498 !state->attachmentHasObject(target, attachment),
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002499 GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002500 SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL ||
2501 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE ||
2502 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) &&
2503 (!state->attachmentHasObject(target, attachment) ||
2504 state->getBoundFramebufferAttachmentType(target, attachment) !=
2505 FBO_ATTACHMENT_TEXTURE),
2506 !state->attachmentHasObject(target, attachment) ?
2507 GL_INVALID_OPERATION : GL_INVALID_ENUM);
2508 SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2509 pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2510 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
2511 state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
2512 GL_INVALID_OPERATION);
2513 SET_ERROR_IF(state->boundFramebuffer(target) &&
2514 (attachment == GL_BACK ||
2515 attachment == GL_FRONT),
2516 GL_INVALID_OPERATION);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002517 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
2518}
Lingfeng Yang69066602016-04-12 09:29:11 -07002519
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002520bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state,
Lingfeng Yang69066602016-04-12 09:29:11 -07002521 GLenum attachment) const {
2522 FboFormatInfo fbo_format_info;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002523 state->getBoundFramebufferFormat(target, attachment, &fbo_format_info);
Lingfeng Yang69066602016-04-12 09:29:11 -07002524
2525 bool res;
2526 switch (fbo_format_info.type) {
2527 case FBO_ATTACHMENT_RENDERBUFFER:
2528 switch (fbo_format_info.rb_format) {
2529 case GL_R16F:
2530 case GL_RG16F:
Lingfeng Yang69066602016-04-12 09:29:11 -07002531 case GL_RGBA16F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002532 case GL_R32F:
2533 case GL_RG32F:
2534 case GL_RGBA32F:
2535 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002536 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002537 break;
2538 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002539 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang69066602016-04-12 09:29:11 -07002540 break;
2541 case GL_STENCIL_INDEX8:
2542 if (attachment == GL_STENCIL_ATTACHMENT) {
2543 res = true;
2544 } else {
2545 res = false;
2546 }
2547 break;
2548 default:
2549 res = true;
2550 }
2551 break;
2552 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002553 switch (fbo_format_info.tex_internalformat) {
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002554 case GL_R16F:
2555 case GL_RG16F:
2556 case GL_RGBA16F:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002557 case GL_R32F:
2558 case GL_RG32F:
2559 case GL_RGBA32F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002560 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002561 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002562 break;
2563 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002564 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002565 break;
2566 case GL_RED:
2567 case GL_RG:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002568 case GL_SRGB8:
2569 case GL_RGB32UI:
2570 case GL_RGB16UI:
2571 case GL_RGB8UI:
2572 case GL_RGB32I:
2573 case GL_RGB16I:
2574 case GL_RGB8I:
2575 case GL_R8_SNORM:
2576 case GL_RG8_SNORM:
2577 case GL_RGB8_SNORM:
2578 case GL_RGBA8_SNORM:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002579 res = false;
2580 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07002581 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002582 case GL_RGB:
2583 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07002584 switch (fbo_format_info.tex_type) {
2585 case GL_FLOAT:
2586 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002587 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002588 case GL_UNSIGNED_INT_2_10_10_10_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07002589 res = false;
2590 break;
2591 default:
2592 res = true;
2593 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002594 break;
2595 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07002596 res = true;
2597 }
2598 break;
2599 case FBO_ATTACHMENT_NONE:
2600 res = true;
2601 break;
2602 default:
2603 res = true;
2604 }
2605 return res;
2606}
2607
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002608bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const {
2609 bool res = true;
2610
2611 for (int i = 0; i < state->getMaxColorAttachments(); i++) {
2612 res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i));
2613 }
2614
2615 res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT);
2616 res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT);
2617
2618 return res;
2619}
2620
Lingfeng Yang69066602016-04-12 09:29:11 -07002621GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
2622 GL2Encoder* ctx = (GL2Encoder*)self;
2623 GLClientState* state = ctx->m_state;
2624
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002625 bool fboCompleteByCodec =
2626 ctx->checkFramebufferCompleteness(target, state);
2627
2628 if (!fboCompleteByCodec) {
2629 state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
Lingfeng Yang69066602016-04-12 09:29:11 -07002630 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2631 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002632 // double check with underlying opengl to avoid craziness.
Lingfeng Yang69066602016-04-12 09:29:11 -07002633 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002634 state->setCheckFramebufferStatus(target, host_checkstatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002635 if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE;
Lingfeng Yang69066602016-04-12 09:29:11 -07002636 return host_checkstatus;
2637 }
2638}
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002639
2640void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2641 GL2Encoder* ctx = (GL2Encoder*)self;
2642 GLClientState* state = ctx->m_state;
2643 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2644
2645 ctx->m_glGenVertexArrays_enc(self, n, arrays);
2646 for (int i = 0; i < n; i++) {
2647 ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2648 }
2649 state->addVertexArrayObjects(n, arrays);
2650}
2651
2652void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2653 GL2Encoder* ctx = (GL2Encoder*)self;
2654 GLClientState* state = ctx->m_state;
2655 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2656
2657 ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2658 for (int i = 0; i < n; i++) {
2659 ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2660 }
2661 state->removeVertexArrayObjects(n, arrays);
2662}
2663
2664void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2665 ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2666 GL2Encoder* ctx = (GL2Encoder*)self;
2667 GLClientState* state = ctx->m_state;
2668 SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2669 ctx->m_glBindVertexArray_enc(self, array);
2670 state->setVertexArrayObject(array);
2671}
2672
Lingfeng Yangfb3d2bb2017-09-07 15:02:04 -07002673void* GL2Encoder::s_glMapBufferOES(void* self, GLenum target, GLenum access) {
2674 GL2Encoder* ctx = (GL2Encoder*)self;
2675
2676 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2677
2678 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2679
2680 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2681
2682 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2683 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2684
2685 return ctx->glMapBufferRange(ctx, target, 0, buf->m_size, access);
2686}
2687
2688GLboolean GL2Encoder::s_glUnmapBufferOES(void* self, GLenum target) {
2689 GL2Encoder* ctx = (GL2Encoder*)self;
2690
2691 return ctx->glUnmapBuffer(ctx, target);
2692}
2693
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002694void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2695 GL2Encoder* ctx = (GL2Encoder*)self;
2696 GLClientState* state = ctx->m_state;
2697
2698 // begin validation (lots)
2699
2700 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2701
2702 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2703
2704 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2705
2706 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2707 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2708
2709 GLsizeiptr bufferDataSize = buf->m_size;
2710
2711 RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2712 RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2713 RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2714 RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2715
2716 RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2717 RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2718 RET_AND_SET_ERROR_IF(
2719 (access & GL_MAP_READ_BIT) &&
2720 ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2721 (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2722 (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2723 (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2724
2725 // end validation; actually do stuff now
2726
2727 buf->m_mapped = true;
2728 buf->m_mappedAccess = access;
2729 buf->m_mappedOffset = offset;
2730 buf->m_mappedLength = length;
2731
2732 char* todo = (char*)buf->m_fixedBuffer.ptr() + offset;
2733 ctx->glMapBufferRangeAEMU(
2734 ctx, target,
2735 offset, length,
2736 access,
2737 todo);
2738
2739 return todo;
2740}
2741
2742GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
2743 GL2Encoder* ctx = (GL2Encoder*)self;
2744 GLClientState* state = ctx->m_state;
2745
2746 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
2747
2748 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2749
2750 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
2751
2752 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2753 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
2754 RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
2755
Lingfeng Yang423129e2017-01-18 09:23:12 -08002756 if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
2757 // invalide index range cache here
2758 if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) {
2759 buf->m_indexRangeCache.invalidateRange(0, buf->m_size);
2760 } else {
2761 buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength);
2762 }
2763 }
2764
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002765 GLboolean host_res = GL_TRUE;
2766
2767 ctx->glUnmapBufferAEMU(
2768 ctx, target,
2769 buf->m_mappedOffset,
2770 buf->m_mappedLength,
2771 buf->m_mappedAccess,
2772 (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
2773 &host_res);
2774
2775 buf->m_mapped = false;
2776 buf->m_mappedAccess = 0;
2777 buf->m_mappedOffset = 0;
2778 buf->m_mappedLength = 0;
2779
2780 return host_res;
2781}
2782
2783void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
2784 GL2Encoder* ctx = (GL2Encoder*)self;
2785 GLClientState* state = ctx->m_state;
2786
2787 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2788
2789 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2790 SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
2791
2792 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2793 SET_ERROR_IF(!buf, GL_INVALID_VALUE);
2794 SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
2795 SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
2796
2797 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
2798 SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
2799 SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
2800
2801 GLintptr totalOffset = buf->m_mappedOffset + offset;
Lingfeng Yang423129e2017-01-18 09:23:12 -08002802
2803 buf->m_indexRangeCache.invalidateRange(totalOffset, length);
2804
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002805 ctx->glFlushMappedBufferRangeAEMU(
2806 ctx, target,
2807 totalOffset,
2808 length,
2809 buf->m_mappedAccess,
2810 (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
2811}
2812
2813void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
2814 GL2Encoder* ctx = (GL2Encoder*)self;
2815 GLClientState* state = ctx->m_state;
2816
2817 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2818 // Filter compressed formats support.
2819 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
2820 // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
2821 GLint max_texture_size;
2822 GLint max_cube_map_texture_size;
2823 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2824 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2825 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2826 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2827 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2828 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2829 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2830 SET_ERROR_IF(border, GL_INVALID_VALUE);
2831 // If unpack buffer is nonzero, verify unmapped state.
2832 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2833 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2834 // If unpack buffer is nonzero, verify buffer data fits.
2835 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2836 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2837 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2838 GL_INVALID_OPERATION);
2839 // TODO: Fix:
2840 // If |imageSize| is inconsistent with compressed dimensions.
2841 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
2842
2843 GLenum stateTarget = target;
2844 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2845 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2846 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2847 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2848 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2849 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2850 stateTarget = GL_TEXTURE_CUBE_MAP;
2851 state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
2852 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2853
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002854 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2855 ctx->override2DTextureTarget(target);
2856 }
2857
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002858 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2859 ctx->glCompressedTexImage2DOffsetAEMU(
2860 ctx, target, level, internalformat,
2861 width, height, border,
2862 imageSize, (uintptr_t)data);
2863 } else {
2864 ctx->m_glCompressedTexImage2D_enc(
2865 ctx, target, level, internalformat,
2866 width, height, border,
2867 imageSize, data);
2868 }
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002869
2870 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2871 ctx->restore2DTextureTarget(target);
2872 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002873}
2874
2875void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
2876 GL2Encoder* ctx = (GL2Encoder*)self;
2877 GLClientState* state = ctx->m_state;
2878
2879 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2880 // If unpack buffer is nonzero, verify unmapped state.
2881 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2882 GLint max_texture_size;
2883 GLint max_cube_map_texture_size;
2884 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2885 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2886 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2887 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2888 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2889 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2890 // If unpack buffer is nonzero, verify buffer data fits.
2891 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2892 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2893 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2894 GL_INVALID_OPERATION);
2895 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2896
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002897 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2898 ctx->override2DTextureTarget(target);
2899 }
2900
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002901 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2902 ctx->glCompressedTexSubImage2DOffsetAEMU(
2903 ctx, target, level,
2904 xoffset, yoffset,
2905 width, height, format,
2906 imageSize, (uintptr_t)data);
2907 } else {
2908 ctx->m_glCompressedTexSubImage2D_enc(
2909 ctx, target, level,
2910 xoffset, yoffset,
2911 width, height, format,
2912 imageSize, data);
2913 }
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08002914
2915 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2916 ctx->restore2DTextureTarget(target);
2917 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002918}
2919
2920void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
2921 GL2Encoder* ctx = (GL2Encoder*)self;
2922 GLClientState* state = ctx->m_state;
2923
2924 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2925
2926 // Only works with certain targets
2927 SET_ERROR_IF(
2928 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2929 target == GL_SHADER_STORAGE_BUFFER ||
2930 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2931 target == GL_UNIFORM_BUFFER),
2932 GL_INVALID_ENUM);
2933
2934 // Can't exceed range
2935 SET_ERROR_IF(index < 0 ||
2936 index >= state->getMaxIndexedBufferBindings(target),
2937 GL_INVALID_VALUE);
2938 SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
2939 SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
2940 target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
2941 (size % 4 || offset % 4),
2942 GL_INVALID_VALUE);
2943
2944 GLint ssbo_offset_align, ubo_offset_align;
2945 ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
2946 ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
2947 SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
2948 offset % ssbo_offset_align,
2949 GL_INVALID_VALUE);
2950 SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
2951 offset % ubo_offset_align,
2952 GL_INVALID_VALUE);
2953
2954 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002955 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002956 state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0);
2957 ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size);
2958}
2959
2960void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
2961 GL2Encoder* ctx = (GL2Encoder*)self;
2962 GLClientState* state = ctx->m_state;
2963
2964 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2965
2966 // Only works with certain targets
2967 SET_ERROR_IF(
2968 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2969 target == GL_SHADER_STORAGE_BUFFER ||
2970 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2971 target == GL_UNIFORM_BUFFER),
2972 GL_INVALID_ENUM);
2973 // Can't exceed range
2974 SET_ERROR_IF(index < 0 ||
2975 index >= state->getMaxIndexedBufferBindings(target),
2976 GL_INVALID_VALUE);
2977
2978 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002979 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002980 BufferData* buf = ctx->getBufferDataById(buffer);
2981 state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0);
2982 ctx->m_glBindBufferBase_enc(self, target, index, buffer);
2983}
2984
2985void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
2986 GL2Encoder* ctx = (GL2Encoder*)self;
2987 GLClientState* state = ctx->m_state;
2988
2989 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
2990 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
2991 SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
2992 readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
2993 readtarget == GL_DRAW_INDIRECT_BUFFER ||
2994 readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2995 SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
2996 writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
2997 writetarget == GL_DRAW_INDIRECT_BUFFER ||
2998 writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2999 SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
3000 SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
3001 SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
3002 SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
3003 SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
3004 SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
3005 SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
3006 SET_ERROR_IF(
3007 ctx->getBufferData(readtarget) &&
3008 (readoffset + size > ctx->getBufferData(readtarget)->m_size),
3009 GL_INVALID_VALUE);
3010 SET_ERROR_IF(
3011 ctx->getBufferData(writetarget) &&
3012 (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
3013 GL_INVALID_VALUE);
3014 SET_ERROR_IF(readtarget == writetarget &&
3015 !((writeoffset >= readoffset + size) ||
3016 (readoffset >= writeoffset + size)),
3017 GL_INVALID_VALUE);
3018
3019 ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
3020}
3021
3022void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
3023 GL2Encoder* ctx = (GL2Encoder*)self;
3024
3025 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3026 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003027 target != GL_ARRAY_BUFFER &&
3028 target != GL_ELEMENT_ARRAY_BUFFER &&
3029 target != GL_COPY_READ_BUFFER &&
3030 target != GL_COPY_WRITE_BUFFER &&
3031 target != GL_PIXEL_PACK_BUFFER &&
3032 target != GL_PIXEL_UNPACK_BUFFER &&
3033 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
3034 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003035 GL_INVALID_ENUM);
3036 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
3037 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003038 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
3039 pname != GL_BUFFER_MAPPED &&
3040 pname != GL_BUFFER_SIZE &&
3041 pname != GL_BUFFER_USAGE &&
3042 pname != GL_BUFFER_MAP_LENGTH &&
3043 pname != GL_BUFFER_MAP_OFFSET,
3044 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003045
3046 if (!params) return;
3047
3048 BufferData* buf = ctx->getBufferData(target);
3049
3050 switch (pname) {
3051 case GL_BUFFER_ACCESS_FLAGS:
3052 *params = buf ? buf->m_mappedAccess : 0;
3053 break;
3054 case GL_BUFFER_MAPPED:
3055 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3056 break;
3057 case GL_BUFFER_SIZE:
3058 *params = buf ? buf->m_size : 0;
3059 break;
3060 case GL_BUFFER_USAGE:
3061 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3062 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003063 case GL_BUFFER_MAP_LENGTH:
3064 *params = buf ? buf->m_mappedLength : 0;
3065 break;
3066 case GL_BUFFER_MAP_OFFSET:
3067 *params = buf ? buf->m_mappedOffset : 0;
3068 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003069 default:
3070 break;
3071 }
3072}
3073
3074void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
3075 GL2Encoder* ctx = (GL2Encoder*)self;
3076
3077 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3078 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003079 target != GL_ARRAY_BUFFER &&
3080 target != GL_ELEMENT_ARRAY_BUFFER &&
3081 target != GL_COPY_READ_BUFFER &&
3082 target != GL_COPY_WRITE_BUFFER &&
3083 target != GL_PIXEL_PACK_BUFFER &&
3084 target != GL_PIXEL_UNPACK_BUFFER &&
3085 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
3086 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003087 GL_INVALID_ENUM);
3088 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
3089 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003090 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
3091 pname != GL_BUFFER_MAPPED &&
3092 pname != GL_BUFFER_SIZE &&
3093 pname != GL_BUFFER_USAGE &&
3094 pname != GL_BUFFER_MAP_LENGTH &&
3095 pname != GL_BUFFER_MAP_OFFSET,
3096 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003097
3098 if (!params) return;
3099
3100 BufferData* buf = ctx->getBufferData(target);
3101
3102 switch (pname) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003103 case GL_BUFFER_ACCESS_FLAGS:
3104 *params = buf ? buf->m_mappedAccess : 0;
3105 break;
3106 case GL_BUFFER_MAPPED:
3107 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3108 break;
3109 case GL_BUFFER_SIZE:
3110 *params = buf ? buf->m_size : 0;
3111 break;
3112 case GL_BUFFER_USAGE:
3113 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3114 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003115 case GL_BUFFER_MAP_LENGTH:
3116 *params = buf ? buf->m_mappedLength : 0;
3117 break;
3118 case GL_BUFFER_MAP_OFFSET:
3119 *params = buf ? buf->m_mappedOffset : 0;
3120 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003121 default:
3122 break;
3123 }
3124}
3125
3126void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
3127 GL2Encoder* ctx = (GL2Encoder*)self;
3128 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3129 SET_ERROR_IF(
3130 target == GL_ATOMIC_COUNTER_BUFFER ||
3131 target == GL_DISPATCH_INDIRECT_BUFFER ||
3132 target == GL_DRAW_INDIRECT_BUFFER ||
3133 target == GL_SHADER_STORAGE_BUFFER,
3134 GL_INVALID_ENUM);
3135 SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
3136 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
3137 if (!params) return;
3138
3139 BufferData* buf = ctx->getBufferData(target);
3140
3141 if (!buf || !buf->m_mapped) { *params = NULL; return; }
3142
3143 *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
3144}
3145
3146static const char* const kNameDelimiter = ";";
3147
3148static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
3149
3150#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
3151
3152 std::string packed;
3153 // validate the array of char[]'s
3154 const char* currName;
3155 for (GLsizei i = 0; i < count; i++) {
3156 currName = names[i];
3157 VALIDATE(!currName, GL_INVALID_OPERATION);
3158 // check if has reasonable size
3159 size_t len = strlen(currName);
3160 VALIDATE(!len, GL_INVALID_OPERATION);
3161 // check for our delimiter, which if present
3162 // in the name, means an invalid name anyway.
3163 VALIDATE(strstr(currName, kNameDelimiter),
3164 GL_INVALID_OPERATION);
3165 packed += currName;
3166 packed += ";";
3167 }
3168
3169 *err_out = GL_NO_ERROR;
3170 return packed;
3171}
3172
3173void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
3174 GL2Encoder* ctx = (GL2Encoder*)self;
3175
3176 if (!uniformCount) return;
3177
3178 GLint err = GL_NO_ERROR;
3179 std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
3180 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3181
3182 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
3183 std::vector<int> arrIndices;
3184 for (size_t i = 0; i < uniformCount; i++) {
3185 int err;
3186 arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
3187 if (err) {
3188 ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
3189 return;
3190 }
3191 }
3192
3193 ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
3194
3195 for (int i = 0; i < uniformCount; i++) {
3196 if (uniformIndices[i] >= 0 && needLocationWAR) {
3197 uniformIndices[i] =
3198 ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
3199 }
3200 }
3201}
3202
3203void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
3204 GL2Encoder *ctx = (GL2Encoder*)self;
3205 GLClientState* state = ctx->m_state;
3206 GLSharedGroupPtr shared = ctx->m_shared;
3207
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003208 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003209 ctx->m_glUniform1ui_enc(self, hostLoc, v0);
3210
3211 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003212 if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003213 GLenum origActiveTexture = state->getActiveTextureUnit();
3214 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
3215 ctx->m_glActiveTexture_enc(self, origActiveTexture);
3216 }
3217 state->setActiveTextureUnit(origActiveTexture);
3218 }
3219}
3220
3221void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) {
3222 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003223 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003224 ctx->m_glUniform2ui_enc(self, hostLoc, v0, v1);
3225}
3226
3227void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) {
3228 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003229 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003230 ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2);
3231}
3232
3233void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) {
3234 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003235 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003236 ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3);
3237}
3238
3239void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3240 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003241 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003242 ctx->m_glUniform1uiv_enc(self, hostLoc, count, value);
3243}
3244
3245void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3246 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003247 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003248 ctx->m_glUniform2uiv_enc(self, hostLoc, count, value);
3249}
3250
3251void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3252 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003253 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003254 ctx->m_glUniform3uiv_enc(self, hostLoc, count, value);
3255}
3256
3257void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3258 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003259 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003260 ctx->m_glUniform4uiv_enc(self, hostLoc, count, value);
3261}
3262
3263void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3264 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003265 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003266 ctx->m_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value);
3267}
3268
3269void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3270 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003271 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003272 ctx->m_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value);
3273}
3274
3275void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3276 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003277 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003278 ctx->m_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value);
3279}
3280
3281void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3282 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003283 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003284 ctx->m_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value);
3285}
3286
3287void GL2Encoder::s_glUniformMatrix3x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3288 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003289 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003290 ctx->m_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value);
3291}
3292
3293void GL2Encoder::s_glUniformMatrix4x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3294 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003295 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003296 ctx->m_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value);
3297}
3298
3299void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3300 GL2Encoder *ctx = (GL2Encoder*)self;
3301 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3302 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3303 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3304 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3305 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3306 ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3307}
3308
3309void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3310 GL2Encoder* ctx = (GL2Encoder*)self;
3311 GLClientState* state = ctx->m_state;
3312
3313 // refresh client state's # active uniforms in this block
3314 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3315 // TODO if worth it: cache uniform count and other params,
3316 // invalidate on program relinking.
3317 GLint numActiveUniforms;
3318 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3319 program, uniformBlockIndex,
3320 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3321 &numActiveUniforms);
3322 ctx->m_state->setNumActiveUniformsInUniformBlock(
3323 program, uniformBlockIndex, numActiveUniforms);
3324 }
3325
3326 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3327 program, uniformBlockIndex,
3328 pname, params);
3329}
3330
3331void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3332 GL2Encoder *ctx = (GL2Encoder *)self;
3333 assert(ctx->m_state);
3334 GLint maxIndex;
3335 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3336 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3337
3338 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3339 ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3340 }
3341}
3342
3343void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3344 GL2Encoder *ctx = (GL2Encoder *)self;
3345 assert(ctx->m_state);
3346 GLint maxIndex;
3347 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3348 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3349
3350 if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3351 ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3352 }
3353}
3354
3355void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3356 GL2Encoder *ctx = (GL2Encoder *)self;
3357 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003358 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003359 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
3360 SET_ERROR_IF(
3361 !(type == GL_BYTE ||
3362 type == GL_UNSIGNED_BYTE ||
3363 type == GL_SHORT ||
3364 type == GL_UNSIGNED_SHORT ||
3365 type == GL_INT ||
3366 type == GL_UNSIGNED_INT),
3367 GL_INVALID_ENUM);
3368 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
3369
3370 ctx->m_state->setVertexAttribBinding(index, index);
3371 ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true);
3372 GLsizei effectiveStride = stride;
3373 if (stride == 0) {
3374 effectiveStride = glSizeof(type) * size;
3375 }
3376 ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride);
3377
3378 if (ctx->m_state->currentArrayVbo() != 0) {
3379 ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer);
3380 } else {
3381 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION);
3382 // wait for client-array handler
3383 }
3384}
3385
3386void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) {
3387 GL2Encoder *ctx = (GL2Encoder *)self;
3388 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003389 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003390 ctx->m_state->setVertexAttribBinding(index, index);
3391 ctx->m_state->setVertexBindingDivisor(index, divisor);
3392 ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor);
3393}
3394
3395void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3396 GLenum target, GLsizei samples, GLenum internalformat,
3397 GLsizei width, GLsizei height) {
3398 GL2Encoder *ctx = (GL2Encoder *)self;
3399 GLClientState* state = ctx->m_state;
3400
3401 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3402 SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3403
3404 GLint max_samples;
3405 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3406 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3407
3408 state->setBoundRenderbufferFormat(internalformat);
3409 state->setBoundRenderbufferSamples(samples);
3410 ctx->m_glRenderbufferStorageMultisample_enc(
3411 self, target, samples, internalformat, width, height);
3412}
3413
3414void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3415 GL2Encoder* ctx = (GL2Encoder*)self;
3416 SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3417 SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3418 for (int i = 0; i < n; i++) {
3419 SET_ERROR_IF(
3420 bufs[i] != GL_NONE &&
3421 bufs[i] != GL_BACK &&
3422 glUtilsColorAttachmentIndex(bufs[i]) == -1,
3423 GL_INVALID_ENUM);
3424 SET_ERROR_IF(
3425 !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3426 glUtilsColorAttachmentIndex(bufs[i]) != -1,
3427 GL_INVALID_OPERATION);
3428 SET_ERROR_IF(
3429 ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3430 ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3431 glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3432 (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3433 bufs[i] != GL_NONE)),
3434 GL_INVALID_OPERATION);
3435 }
3436
3437 ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3438}
3439
3440void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3441 GL2Encoder* ctx = (GL2Encoder*)self;
3442
3443 SET_ERROR_IF(
3444 glUtilsColorAttachmentIndex(src) != -1 &&
3445 (glUtilsColorAttachmentIndex(src) >=
3446 ctx->m_state->getMaxColorAttachments()),
3447 GL_INVALID_OPERATION);
3448 SET_ERROR_IF(
3449 src != GL_NONE &&
3450 src != GL_BACK &&
3451 src > GL_COLOR_ATTACHMENT0 &&
3452 src < GL_DEPTH_ATTACHMENT &&
3453 (src - GL_COLOR_ATTACHMENT0) >
3454 ctx->m_state->getMaxColorAttachments(),
3455 GL_INVALID_OPERATION);
3456 SET_ERROR_IF(
3457 src != GL_NONE &&
3458 src != GL_BACK &&
3459 glUtilsColorAttachmentIndex(src) == -1,
3460 GL_INVALID_ENUM);
3461 SET_ERROR_IF(
3462 !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3463 src != GL_NONE &&
3464 src != GL_BACK,
3465 GL_INVALID_OPERATION);
3466 SET_ERROR_IF(
3467 ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3468 src != GL_NONE &&
3469 glUtilsColorAttachmentIndex(src) == -1,
3470 GL_INVALID_OPERATION);
3471
3472 ctx->m_glReadBuffer_enc(ctx, src);
3473}
3474
3475void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3476 GL2Encoder* ctx = (GL2Encoder*)self;
3477 GLClientState* state = ctx->m_state;
3478
3479 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3480 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3481 GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3482 SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3483 lastBoundTarget != GL_TEXTURE_3D,
3484 GL_INVALID_OPERATION);
3485 state->attachTextureObject(target, attachment, texture);
3486
3487 GLint max3DTextureSize;
3488 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3489 SET_ERROR_IF(
3490 layer >= max3DTextureSize,
3491 GL_INVALID_VALUE);
3492
3493 ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3494}
3495
3496void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3497 GL2Encoder* ctx = (GL2Encoder*)self;
3498 GLClientState* state = ctx->m_state;
3499
3500 SET_ERROR_IF(
3501 target != GL_TEXTURE_2D &&
3502 target != GL_TEXTURE_CUBE_MAP,
3503 GL_INVALID_ENUM);
3504 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3505 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3506 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3507 SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3508 GL_INVALID_OPERATION);
3509 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3510
3511 state->setBoundTextureInternalFormat(target, internalformat);
3512 state->setBoundTextureDims(target, -1, width, height, 1);
3513 state->setBoundTextureImmutableFormat(target);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003514
3515 if (target == GL_TEXTURE_2D) {
3516 ctx->override2DTextureTarget(target);
3517 }
3518
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003519 ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003520
3521 if (target == GL_TEXTURE_2D) {
3522 ctx->restore2DTextureTarget(target);
3523 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003524}
3525
3526void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3527 GL2Encoder* ctx = (GL2Encoder*)self;
3528
3529 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3530
3531 GLint maxCount = 0;
3532 ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3533
3534 SET_ERROR_IF(
3535 bufferMode == GL_SEPARATE_ATTRIBS &&
3536 maxCount < count,
3537 GL_INVALID_VALUE);
3538 SET_ERROR_IF(
3539 bufferMode != GL_INTERLEAVED_ATTRIBS &&
3540 bufferMode != GL_SEPARATE_ATTRIBS,
3541 GL_INVALID_ENUM);
3542
3543 if (!count) return;
3544
3545 GLint err = GL_NO_ERROR;
3546 std::string packed = packVarNames(count, varyings, &err);
3547 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3548
3549 ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3550}
3551
3552void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3553 GL2Encoder* ctx = (GL2Encoder*)self;
3554 GLClientState* state = ctx->m_state;
3555 ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3556 state->setTransformFeedbackActiveUnpaused(true);
3557}
3558
3559void GL2Encoder::s_glEndTransformFeedback(void* self) {
3560 GL2Encoder* ctx = (GL2Encoder*)self;
3561 GLClientState* state = ctx->m_state;
3562 ctx->m_glEndTransformFeedback_enc(ctx);
3563 state->setTransformFeedbackActiveUnpaused(false);
3564}
3565
3566void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3567 GL2Encoder* ctx = (GL2Encoder*)self;
3568 GLClientState* state = ctx->m_state;
3569 ctx->m_glPauseTransformFeedback_enc(ctx);
3570 state->setTransformFeedbackActiveUnpaused(false);
3571}
3572
3573void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3574 GL2Encoder* ctx = (GL2Encoder*)self;
3575 GLClientState* state = ctx->m_state;
3576 ctx->m_glResumeTransformFeedback_enc(ctx);
3577 state->setTransformFeedbackActiveUnpaused(true);
3578}
3579
3580void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3581 GLsizei width, GLsizei height, GLsizei depth,
3582 GLint border, GLenum format, GLenum type, const GLvoid* data) {
3583 GL2Encoder* ctx = (GL2Encoder*)self;
3584 GLClientState* state = ctx->m_state;
3585
3586 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3587 target != GL_TEXTURE_2D_ARRAY,
3588 GL_INVALID_ENUM);
3589 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3590 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3591
3592 // If unpack buffer is nonzero, verify unmapped state.
3593 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3594
3595 GLint max_texture_size;
3596 GLint max_3d_texture_size;
3597 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3598 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3599 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3600 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3601 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3602
3603 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3604 SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3605 SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3606 SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3607 SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3608 SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3609 SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3610 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3611 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3612 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3613 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3614 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3615 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3616 GL_INVALID_OPERATION);
3617 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3618 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3619 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3620 glSizeof(type)),
3621 GL_INVALID_OPERATION);
3622 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3623
3624 state->setBoundTextureInternalFormat(target, internalFormat);
3625 state->setBoundTextureFormat(target, format);
3626 state->setBoundTextureType(target, type);
3627 state->setBoundTextureDims(target, level, width, height, depth);
3628
3629 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3630 ctx->glTexImage3DOffsetAEMU(
3631 ctx, target, level, internalFormat,
3632 width, height, depth,
3633 border, format, type, (uintptr_t)data);
3634 } else {
3635 ctx->m_glTexImage3D_enc(ctx,
3636 target, level, internalFormat,
3637 width, height, depth,
3638 border, format, type, data);
3639 }
3640}
3641
3642void 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) {
3643 GL2Encoder* ctx = (GL2Encoder*)self;
3644 GLClientState* state = ctx->m_state;
3645
3646 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3647 target != GL_TEXTURE_2D_ARRAY,
3648 GL_INVALID_ENUM);
3649 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3650 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3651 // If unpack buffer is nonzero, verify unmapped state.
3652 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3653 GLint max_texture_size;
3654 GLint max_3d_texture_size;
3655 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3656 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3657 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3658 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3659 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3660 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3661 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3662 GLuint tex = state->getBoundTexture(target);
3663 GLsizei neededWidth = xoffset + width;
3664 GLsizei neededHeight = yoffset + height;
3665 GLsizei neededDepth = zoffset + depth;
3666
3667 SET_ERROR_IF(tex &&
3668 (neededWidth > state->queryTexWidth(level, tex) ||
3669 neededHeight > state->queryTexHeight(level, tex) ||
3670 neededDepth > state->queryTexDepth(level, tex)),
3671 GL_INVALID_VALUE);
3672 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3673 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3674 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3675 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3676 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3677 GL_INVALID_OPERATION);
3678 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3679 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3680 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3681 glSizeof(type)),
3682 GL_INVALID_OPERATION);
3683 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
3684 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3685
3686 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3687 ctx->glTexSubImage3DOffsetAEMU(ctx,
3688 target, level,
3689 xoffset, yoffset, zoffset,
3690 width, height, depth,
3691 format, type, (uintptr_t)data);
3692 } else {
3693 ctx->m_glTexSubImage3D_enc(ctx,
3694 target, level,
3695 xoffset, yoffset, zoffset,
3696 width, height, depth,
3697 format, type, data);
3698 }
3699}
3700
3701void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
3702 GL2Encoder* ctx = (GL2Encoder*)self;
3703 GLClientState* state = ctx->m_state;
3704
3705 // Filter compressed formats support.
3706 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3707 // If unpack buffer is nonzero, verify unmapped state.
3708 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3709 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3710 SET_ERROR_IF(border, GL_INVALID_VALUE);
3711 // If unpack buffer is nonzero, verify buffer data fits.
3712 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3713 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3714 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3715 GL_INVALID_OPERATION);
3716 // TODO: Fix:
3717 // If |imageSize| is too small for compressed dimensions.
3718 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
3719 state->setBoundTextureInternalFormat(target, (GLint)internalformat);
3720 state->setBoundTextureDims(target, level, width, height, depth);
3721
3722 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3723 ctx->glCompressedTexImage3DOffsetAEMU(
3724 ctx, target, level, internalformat,
3725 width, height, depth, border,
3726 imageSize, (uintptr_t)data);
3727 } else {
3728 ctx->m_glCompressedTexImage3D_enc(
3729 ctx, target, level, internalformat,
3730 width, height, depth, border,
3731 imageSize, data);
3732 }
3733}
3734
3735void 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) {
3736 GL2Encoder* ctx = (GL2Encoder*)self;
3737 GLClientState* state = ctx->m_state;
3738
3739 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3740 // If unpack buffer is nonzero, verify unmapped state.
3741 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3742 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3743 // If unpack buffer is nonzero, verify buffer data fits.
3744 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3745 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3746 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3747 GL_INVALID_OPERATION);
3748 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3749
3750 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3751 ctx->glCompressedTexSubImage3DOffsetAEMU(
3752 ctx, target, level,
3753 xoffset, yoffset, zoffset,
3754 width, height, depth,
3755 format, imageSize, (uintptr_t)data);
3756 } else {
3757 ctx->m_glCompressedTexSubImage3D_enc(
3758 ctx, target, level,
3759 xoffset, yoffset, zoffset,
3760 width, height, depth,
3761 format, imageSize, data);
3762
3763 }
3764}
3765
3766void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
3767 GL2Encoder* ctx = (GL2Encoder*)self;
3768 GLClientState* state = ctx->m_state;
3769 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3770 target != GL_TEXTURE_2D_ARRAY,
3771 GL_INVALID_ENUM);
3772 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3773 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3774 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3775 SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
3776 GL_INVALID_OPERATION);
3777 SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
3778 GL_INVALID_OPERATION);
3779 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3780
3781 state->setBoundTextureInternalFormat(target, internalformat);
3782 state->setBoundTextureDims(target, -1, width, height, depth);
3783 state->setBoundTextureImmutableFormat(target);
3784 ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
3785 state->setBoundTextureImmutableFormat(target);
3786}
3787
3788void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
3789 GL2Encoder *ctx = (GL2Encoder *)self;
3790 assert(ctx->m_state != NULL);
3791 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3792 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3793
3794 bool has_client_vertex_arrays = false;
3795 bool has_indirect_arrays = false;
3796 ctx->getVBOUsage(&has_client_vertex_arrays,
3797 &has_indirect_arrays);
3798
3799 if (has_client_vertex_arrays ||
3800 (!has_client_vertex_arrays &&
3801 !has_indirect_arrays)) {
3802 ctx->sendVertexAttributes(first, count, true, primcount);
3803 ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
3804 } else {
3805 ctx->sendVertexAttributes(0, count, false, primcount);
3806 ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
3807 }
3808 ctx->m_stream->flush();
3809}
3810
3811void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
3812{
3813
3814 GL2Encoder *ctx = (GL2Encoder *)self;
3815 assert(ctx->m_state != NULL);
3816 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3817 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3818 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3819 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3820
3821 bool has_client_vertex_arrays = false;
3822 bool has_indirect_arrays = false;
3823 int nLocations = ctx->m_state->nLocations();
3824 GLintptr offset = 0;
3825
3826 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3827
3828 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3829 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3830 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3831 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3832 }
3833
3834 BufferData* buf = NULL;
3835 int minIndex = 0, maxIndex = 0;
3836
3837 // For validation/immediate index array purposes,
3838 // we need the min/max vertex index of the index array.
3839 // If the VBO != 0, this may not be the first time we have
3840 // used this particular index buffer. getBufferIndexRange
3841 // can more quickly get min/max vertex index by
3842 // caching previous results.
3843 if (ctx->m_state->currentIndexVbo() != 0) {
3844 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3845 offset = (GLintptr)indices;
3846 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3847 ctx->getBufferIndexRange(buf,
3848 indices,
3849 type,
3850 (size_t)count,
3851 (size_t)offset,
3852 &minIndex, &maxIndex);
3853 } else {
3854 // In this case, the |indices| field holds a real
3855 // array, so calculate the indices now. They will
3856 // also be needed to know how much data to
3857 // transfer to host.
3858 ctx->calcIndexRange(indices,
3859 type,
3860 count,
3861 &minIndex,
3862 &maxIndex);
3863 }
3864
3865 bool adjustIndices = true;
3866 if (ctx->m_state->currentIndexVbo() != 0) {
3867 if (!has_client_vertex_arrays) {
3868 ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
3869 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3870 ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
3871 ctx->flushDrawCall();
3872 adjustIndices = false;
3873 } else {
3874 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3875 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3876 }
3877 }
3878 if (adjustIndices) {
3879 void *adjustedIndices =
3880 ctx->recenterIndices(indices,
3881 type,
3882 count,
3883 minIndex);
3884
3885 if (has_indirect_arrays || 1) {
3886 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
3887 ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
3888 ctx->m_stream->flush();
3889 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3890 if(!has_indirect_arrays) {
3891 //ALOGD("unoptimized drawelements !!!\n");
3892 }
3893 } else {
3894 // we are all direct arrays and immidate mode index array -
3895 // rebuild the arrays and the index array;
3896 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3897 }
3898 }
3899}
3900
3901void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
3902{
3903
3904 GL2Encoder *ctx = (GL2Encoder *)self;
3905 assert(ctx->m_state != NULL);
3906 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3907 SET_ERROR_IF(end < start, GL_INVALID_VALUE);
3908 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3909 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3910 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3911
3912 bool has_client_vertex_arrays = false;
3913 bool has_indirect_arrays = false;
3914 int nLocations = ctx->m_state->nLocations();
3915 GLintptr offset = 0;
3916
3917 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3918
3919 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3920 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3921 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3922 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3923 }
3924
3925 BufferData* buf = NULL;
3926 int minIndex = 0, maxIndex = 0;
3927
3928 // For validation/immediate index array purposes,
3929 // we need the min/max vertex index of the index array.
3930 // If the VBO != 0, this may not be the first time we have
3931 // used this particular index buffer. getBufferIndexRange
3932 // can more quickly get min/max vertex index by
3933 // caching previous results.
3934 if (ctx->m_state->currentIndexVbo() != 0) {
3935 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3936 offset = (GLintptr)indices;
3937 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3938 ctx->getBufferIndexRange(buf,
3939 indices,
3940 type,
3941 (size_t)count,
3942 (size_t)offset,
3943 &minIndex, &maxIndex);
3944 } else {
3945 // In this case, the |indices| field holds a real
3946 // array, so calculate the indices now. They will
3947 // also be needed to know how much data to
3948 // transfer to host.
3949 ctx->calcIndexRange(indices,
3950 type,
3951 count,
3952 &minIndex,
3953 &maxIndex);
3954 }
3955
3956 bool adjustIndices = true;
3957 if (ctx->m_state->currentIndexVbo() != 0) {
3958 if (!has_client_vertex_arrays) {
3959 ctx->sendVertexAttributes(0, maxIndex + 1, false);
3960 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3961 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
3962 ctx->flushDrawCall();
3963 adjustIndices = false;
3964 } else {
3965 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3966 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3967 }
3968 }
3969 if (adjustIndices) {
3970 void *adjustedIndices =
3971 ctx->recenterIndices(indices,
3972 type,
3973 count,
3974 minIndex);
3975
3976 if (has_indirect_arrays || 1) {
3977 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
3978 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
3979 ctx->m_stream->flush();
3980 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3981 if(!has_indirect_arrays) {
3982 //ALOGD("unoptimized drawelements !!!\n");
3983 }
3984 } else {
3985 // we are all direct arrays and immidate mode index array -
3986 // rebuild the arrays and the index array;
3987 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3988 }
3989 }
3990}
3991
3992// struct GLStringKey {
3993// GLenum name;
3994// GLuint index;
3995// };
3996//
3997// struct GLStringKeyCompare {
3998// bool operator() (const GLStringKey& a,
3999// const GLStringKey& b) const {
4000// if (a.name != b.name) return a.name < b.name;
4001// if (a.index != b.index) return a.index < b.index;
4002// return false;
4003// }
4004// };
4005//
4006// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
4007//
4008// static GLStringStore sGLStringStore;
4009// bool sGLStringStoreInitialized = false;
4010
4011const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
4012 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004013 const GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004014
4015 RET_AND_SET_ERROR_IF(
4016 name != GL_VENDOR &&
4017 name != GL_RENDERER &&
4018 name != GL_VERSION &&
4019 name != GL_EXTENSIONS,
4020 GL_INVALID_ENUM,
4021 retval);
4022
4023 RET_AND_SET_ERROR_IF(
4024 name == GL_VENDOR ||
4025 name == GL_RENDERER ||
4026 name == GL_VERSION ||
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004027 index != 0,
4028 GL_INVALID_VALUE,
4029 retval);
4030
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004031 RET_AND_SET_ERROR_IF(
4032 name == GL_EXTENSIONS &&
4033 index >= ctx->m_currExtensionsArray.size(),
4034 GL_INVALID_VALUE,
4035 retval);
4036
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004037 switch (name) {
4038 case GL_VENDOR:
4039 retval = gVendorString;
4040 break;
4041 case GL_RENDERER:
4042 retval = gRendererString;
4043 break;
4044 case GL_VERSION:
4045 retval = gVersionString;
4046 break;
4047 case GL_EXTENSIONS:
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004048 retval = (const GLubyte*)(ctx->m_currExtensionsArray[index].c_str());
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004049 break;
4050 }
4051
4052 return retval;
4053}
4054
4055void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
4056 GL2Encoder *ctx = (GL2Encoder *)self;
4057
4058 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
4059
4060 GLint linkStatus = 0;
4061 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
4062 GLint properLength = 0;
4063 ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
4064
4065 SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
4066 SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
4067
4068 ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
4069}
4070
4071void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
4072 GL2Encoder *ctx = (GL2Encoder *)self;
4073
4074 SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
4075 SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
4076 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
4077 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
4078 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
4079 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
4080 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
4081 ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
4082 GL_INVALID_OPERATION);
4083 /*
4084GL_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.
4085
4086GL_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.
4087
4088GL_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.
4089
4090GL_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.
4091*/
4092
4093 FboFormatInfo fbo_format_info;
4094 ctx->m_state->getBoundFramebufferFormat(
4095 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
4096 SET_ERROR_IF(
4097 fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4098 !GLESv2Validation::readPixelsFboFormatMatch(
4099 format, type, fbo_format_info.tex_type),
4100 GL_INVALID_OPERATION);
4101
4102 if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
4103 ctx->glReadPixelsOffsetAEMU(
4104 ctx, x, y, width, height,
4105 format, type, (uintptr_t)pixels);
4106 } else {
4107 ctx->m_glReadPixels_enc(
4108 ctx, x, y, width, height,
4109 format, type, pixels);
4110 }
4111}
4112
4113// Track enabled state for some things like:
4114// - Primitive restart
4115void GL2Encoder::s_glEnable(void* self, GLenum what) {
4116 GL2Encoder *ctx = (GL2Encoder *)self;
4117
4118 switch (what) {
4119 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4120 ctx->m_primitiveRestartEnabled = true;
4121 break;
4122 }
4123
4124 ctx->m_glEnable_enc(ctx, what);
4125}
4126
4127void GL2Encoder::s_glDisable(void* self, GLenum what) {
4128 GL2Encoder *ctx = (GL2Encoder *)self;
4129
4130 switch (what) {
4131 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4132 ctx->m_primitiveRestartEnabled = false;
4133 break;
4134 }
4135
4136 ctx->m_glDisable_enc(ctx, what);
4137}
4138
4139void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
4140 GL2Encoder *ctx = (GL2Encoder *)self;
4141
4142 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4143
4144 ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
4145}
4146
4147void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
4148 GL2Encoder *ctx = (GL2Encoder *)self;
4149
4150 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4151
4152 ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
4153}
4154
4155void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
4156 GL2Encoder *ctx = (GL2Encoder *)self;
4157
4158 SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4159
4160 ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
4161}
4162
4163void 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) {
4164 GL2Encoder *ctx = (GL2Encoder *)self;
4165 GLClientState* state = ctx->m_state;
4166
4167 bool validateColor = mask | GL_COLOR_BUFFER_BIT;
4168 bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
4169 bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
4170
4171 FboFormatInfo read_fbo_format_info;
4172 FboFormatInfo draw_fbo_format_info;
4173 if (validateColor) {
4174 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4175 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4176
4177 if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4178 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
4179 SET_ERROR_IF(
4180 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4181 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4182 !GLESv2Validation::blitFramebufferFormat(
4183 read_fbo_format_info.tex_type,
4184 draw_fbo_format_info.tex_type),
4185 GL_INVALID_OPERATION);
4186 }
4187 }
4188
4189 if (validateDepth) {
4190 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
4191 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
4192
4193 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4194 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4195 SET_ERROR_IF(
4196 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4197 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4198 !GLESv2Validation::blitFramebufferFormat(
4199 read_fbo_format_info.rb_format,
4200 draw_fbo_format_info.rb_format),
4201 GL_INVALID_OPERATION);
4202 }
4203 }
4204
4205 if (validateStencil) {
4206 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
4207 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
4208
4209 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4210 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4211 SET_ERROR_IF(
4212 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4213 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4214 !GLESv2Validation::blitFramebufferFormat(
4215 read_fbo_format_info.rb_format,
4216 draw_fbo_format_info.rb_format),
4217 GL_INVALID_OPERATION);
4218 }
4219 }
4220
4221 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4222 SET_ERROR_IF(
4223 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4224 draw_fbo_format_info.rb_multisamples > 0,
4225 GL_INVALID_OPERATION);
4226 SET_ERROR_IF(
4227 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4228 draw_fbo_format_info.tex_multisamples > 0,
4229 GL_INVALID_OPERATION);
4230
4231 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4232 SET_ERROR_IF(
4233 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4234 read_fbo_format_info.rb_multisamples > 0 &&
4235 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4236 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4237 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4238 (read_fbo_format_info.rb_format !=
4239 draw_fbo_format_info.rb_format),
4240 GL_INVALID_OPERATION);
4241 SET_ERROR_IF(
4242 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4243 read_fbo_format_info.rb_multisamples > 0 &&
4244 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4245 (srcX0 != dstX0 || srcY0 != dstY0 ||
4246 srcX1 != dstX1 || srcY1 != dstY1),
4247 GL_INVALID_OPERATION);
4248
4249 ctx->m_glBlitFramebuffer_enc(ctx,
4250 srcX0, srcY0, srcX1, srcY1,
4251 dstX0, dstY0, dstX1, dstY1,
4252 mask, filter);
4253}
4254
4255void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
4256 GL2Encoder *ctx = (GL2Encoder *)self;
4257
4258 SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
4259 pname != GL_SAMPLES,
4260 GL_INVALID_ENUM);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004261 SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004262 SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004263 !GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4264 !GLESv2Validation::depthRenderableFormat(ctx, internalformat) &&
4265 !GLESv2Validation::stencilRenderableFormat(ctx, internalformat),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004266 GL_INVALID_ENUM);
4267 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4268
4269 if (bufSize < 1) return;
4270
4271 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
4272 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
4273 switch (pname) {
4274 case GL_NUM_SAMPLE_COUNTS:
4275 *params = 3;
4276 break;
4277 case GL_SAMPLES:
4278 params[0] = 4;
4279 if (bufSize > 1) params[1] = 2;
4280 if (bufSize > 2) params[2] = 1;
4281 break;
4282 default:
4283 break;
4284 }
4285}
4286
4287void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
4288 GL2Encoder *ctx = (GL2Encoder *)self;
4289 GLClientState* state = ctx->m_state;
4290
4291 SET_ERROR_IF(target != GL_TEXTURE_2D &&
4292 target != GL_TEXTURE_3D &&
Yahan Zhou53c64582018-04-16 15:46:17 -07004293 target != GL_TEXTURE_CUBE_MAP &&
4294 target != GL_TEXTURE_2D_ARRAY,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004295 GL_INVALID_ENUM);
4296
4297 GLuint tex = state->getBoundTexture(target);
4298 GLenum internalformat = state->queryTexInternalFormat(tex);
4299 GLenum format = state->queryTexFormat(tex);
4300
4301 SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
4302 GL_INVALID_OPERATION);
4303 SET_ERROR_IF(tex &&
4304 !GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004305 !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4306 GLESv2Validation::filterableTexFormat(ctx, internalformat)),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004307 GL_INVALID_OPERATION);
4308
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08004309 if (target == GL_TEXTURE_2D) {
4310 ctx->override2DTextureTarget(target);
4311 }
4312
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004313 ctx->m_glGenerateMipmap_enc(ctx, target);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08004314
4315 if (target == GL_TEXTURE_2D) {
4316 ctx->restore2DTextureTarget(target);
4317 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004318}
4319
4320void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4321 GL2Encoder *ctx = (GL2Encoder *)self;
4322 GLint maxCombinedUnits;
4323 ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4324 SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4325
4326 ctx->m_glBindSampler_enc(ctx, unit, sampler);
4327}
4328
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004329GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4330 GL2Encoder *ctx = (GL2Encoder *)self;
4331 uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4332 return (GLsync)(uintptr_t)syncHandle;
4333}
4334
4335GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4336 GL2Encoder *ctx = (GL2Encoder *)self;
4337 return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4338}
4339
4340void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4341 GL2Encoder *ctx = (GL2Encoder *)self;
4342 ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4343}
4344
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004345void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) {
4346 GL2Encoder *ctx = (GL2Encoder *)self;
4347
4348 if (!sync) return;
4349
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004350 ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4351}
4352
4353GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4354 GL2Encoder *ctx = (GL2Encoder *)self;
4355 return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4356}
4357
4358void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4359 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004360
4361 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4362
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004363 return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004364}
4365
4366#define LIMIT_CASE(target, lim) \
4367 case target: \
4368 ctx->glGetIntegerv(ctx, lim, &limit); \
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004369 SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004370 break; \
4371
4372void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) {
4373 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004374 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004375
4376 GLint limit;
4377
4378 switch (target) {
4379 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4380 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4381 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4382 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4383 default:
4384 break;
4385 }
4386
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004387 const GLClientState::VertexAttribBindingVector& currBindings =
4388 state->currentVertexBufferBindings();
4389
4390 switch (target) {
4391 case GL_VERTEX_BINDING_DIVISOR:
4392 case GL_VERTEX_BINDING_OFFSET:
4393 case GL_VERTEX_BINDING_STRIDE:
4394 case GL_VERTEX_BINDING_BUFFER:
4395 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4396 break;
4397 default:
4398 break;
4399 }
4400
4401 switch (target) {
4402 case GL_VERTEX_BINDING_DIVISOR:
4403 *params = currBindings[index].divisor;
4404 return;
4405 case GL_VERTEX_BINDING_OFFSET:
4406 *params = currBindings[index].offset;
4407 return;
4408 case GL_VERTEX_BINDING_STRIDE:
4409 *params = currBindings[index].effectiveStride;
4410 return;
4411 case GL_VERTEX_BINDING_BUFFER:
4412 *params = currBindings[index].buffer;
4413 return;
4414 default:
4415 break;
4416 }
4417
Lingfeng Yang80a36332017-07-09 10:58:07 -07004418 ctx->safe_glGetIntegeri_v(target, index, params);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004419}
4420
4421void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
4422 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004423 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004424
4425 GLint limit;
4426
4427 switch (target) {
4428 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4429 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4430 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4431 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4432 default:
4433 break;
4434 }
4435
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004436 const GLClientState::VertexAttribBindingVector& currBindings =
4437 state->currentVertexBufferBindings();
4438
4439 switch (target) {
4440 case GL_VERTEX_BINDING_DIVISOR:
4441 case GL_VERTEX_BINDING_OFFSET:
4442 case GL_VERTEX_BINDING_STRIDE:
4443 case GL_VERTEX_BINDING_BUFFER:
4444 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4445 break;
4446 default:
4447 break;
4448 }
4449
4450 switch (target) {
4451 case GL_VERTEX_BINDING_DIVISOR:
4452 *params = currBindings[index].divisor;
4453 return;
4454 case GL_VERTEX_BINDING_OFFSET:
4455 *params = currBindings[index].offset;
4456 return;
4457 case GL_VERTEX_BINDING_STRIDE:
4458 *params = currBindings[index].effectiveStride;
4459 return;
4460 case GL_VERTEX_BINDING_BUFFER:
4461 *params = currBindings[index].buffer;
4462 return;
4463 default:
4464 break;
4465 }
4466
Lingfeng Yang80a36332017-07-09 10:58:07 -07004467 ctx->safe_glGetInteger64i_v(target, index, params);
4468}
4469
4470void GL2Encoder::s_glGetInteger64v(void* self, GLenum param, GLint64* val) {
4471 GL2Encoder *ctx = (GL2Encoder *)self;
4472 ctx->safe_glGetInteger64v(param, val);
4473}
4474
4475void GL2Encoder::s_glGetBooleani_v(void* self, GLenum param, GLuint index, GLboolean* val) {
4476 GL2Encoder *ctx = (GL2Encoder *)self;
4477 ctx->safe_glGetBooleani_v(param, index, val);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004478}
4479
4480void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4481 GL2Encoder *ctx = (GL2Encoder *)self;
4482 ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4483 if (pname == GL_SHADER_SOURCE_LENGTH) {
4484 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4485 if (shaderData) {
4486 int totalLen = 0;
4487 for (int i = 0; i < shaderData->sources.size(); i++) {
4488 totalLen += shaderData->sources[i].size();
4489 }
4490 if (totalLen != 0) {
4491 *params = totalLen + 1; // account for null terminator
4492 }
4493 }
4494 }
4495}
4496
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004497void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) {
4498 GL2Encoder *ctx = (GL2Encoder*)self;
4499 GLClientState* state = ctx->m_state;
4500 GLSharedGroupPtr shared = ctx->m_shared;
4501
4502 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4503 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4504 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4505
4506 ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program);
4507 if (!state->currentProgram()) {
4508 state->setCurrentShaderProgram(program);
4509 }
4510}
4511
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004512GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4513
4514 GLint* length = NULL;
4515 GL2Encoder* ctx = (GL2Encoder*)self;
4516
4517 int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
4518 char *str = new char[len + 1];
4519 glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
4520
4521 // Do GLSharedGroup and location WorkARound-specific initialization
4522 // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4523 uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4524 ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
4525 ShaderData* sData = spData->shaderData;
4526
4527 if (!replaceSamplerExternalWith2D(str, sData)) {
4528 delete [] str;
4529 ctx->setError(GL_OUT_OF_MEMORY);
4530 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4531 return -1;
4532 }
4533
4534 GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
4535 delete [] str;
4536
4537 // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4538 GLint linkStatus = 0;
4539 ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4540 if (!linkStatus) {
4541 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4542 return -1;
4543 }
4544
4545 ctx->m_shared->associateGLShaderProgram(res, spDataId);
4546
4547 GLint numUniforms = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07004548 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORMS, &numUniforms);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004549 ctx->m_shared->initShaderProgramData(res, numUniforms);
4550
4551 GLint maxLength=0;
4552 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4553
4554 GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4555
4556 for (GLint i = 0; i < numUniforms; ++i) {
4557 ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4558 GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4559 ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4560 }
4561
4562 ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4563
4564 delete [] name;
4565
4566 return res;
4567}
4568
4569void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4570{
4571 GL2Encoder *ctx = (GL2Encoder*)self;
4572 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4573 ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4574}
4575
4576void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4577{
4578 GL2Encoder *ctx = (GL2Encoder*)self;
4579 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4580 ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4581}
4582
4583void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4584{
4585 GL2Encoder *ctx = (GL2Encoder*)self;
4586 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004587 ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004588
4589 GLClientState* state = ctx->m_state;
4590 GLSharedGroupPtr shared = ctx->m_shared;
4591 GLenum target;
4592
4593 if (shared->setSamplerUniform(program, location, v0, &target)) {
4594 GLenum origActiveTexture = state->getActiveTextureUnit();
4595 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4596 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4597 }
4598 state->setActiveTextureUnit(origActiveTexture);
4599 }
4600}
4601
4602void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4603{
4604 GL2Encoder *ctx = (GL2Encoder*)self;
4605 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4606 ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4607}
4608
4609void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4610{
4611 GL2Encoder *ctx = (GL2Encoder*)self;
4612 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4613 ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4614
4615 GLClientState* state = ctx->m_state;
4616 GLSharedGroupPtr shared = ctx->m_shared;
4617 GLenum target;
4618
4619 if (shared->setSamplerUniform(program, location, v0, &target)) {
4620 GLenum origActiveTexture = state->getActiveTextureUnit();
4621 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4622 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4623 }
4624 state->setActiveTextureUnit(origActiveTexture);
4625 }
4626}
4627
4628void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4629{
4630 GL2Encoder *ctx = (GL2Encoder*)self;
4631 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4632 ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
4633}
4634
4635void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
4636{
4637 GL2Encoder *ctx = (GL2Encoder*)self;
4638 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4639 ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
4640}
4641
4642void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4643{
4644 GL2Encoder *ctx = (GL2Encoder*)self;
4645 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4646 ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
4647}
4648
4649void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
4650{
4651 GL2Encoder *ctx = (GL2Encoder*)self;
4652 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4653 ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
4654}
4655
4656void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4657{
4658 GL2Encoder *ctx = (GL2Encoder*)self;
4659 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4660 ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
4661}
4662
4663void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
4664{
4665 GL2Encoder *ctx = (GL2Encoder*)self;
4666 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4667 ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
4668}
4669
4670void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4671{
4672 GL2Encoder *ctx = (GL2Encoder*)self;
4673 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4674 ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
4675}
4676
4677void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
4678{
4679 GL2Encoder *ctx = (GL2Encoder*)self;
4680 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4681 ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
4682}
4683
4684void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4685{
4686 GL2Encoder *ctx = (GL2Encoder*)self;
4687 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4688 ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
4689}
4690
4691void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
4692{
4693 GL2Encoder *ctx = (GL2Encoder*)self;
4694 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4695 ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
4696}
4697
4698void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4699{
4700 GL2Encoder *ctx = (GL2Encoder*)self;
4701 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4702 ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
4703}
4704
4705void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
4706{
4707 GL2Encoder *ctx = (GL2Encoder*)self;
4708 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4709 ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
4710}
4711
4712void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4713{
4714 GL2Encoder *ctx = (GL2Encoder*)self;
4715 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4716 ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
4717}
4718
4719void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
4720{
4721 GL2Encoder *ctx = (GL2Encoder*)self;
4722 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4723 ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
4724}
4725
4726void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4727{
4728 GL2Encoder *ctx = (GL2Encoder*)self;
4729 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4730 ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
4731}
4732
4733void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
4734{
4735 GL2Encoder *ctx = (GL2Encoder*)self;
4736 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4737 ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
4738}
4739
4740void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4741{
4742 GL2Encoder *ctx = (GL2Encoder*)self;
4743 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4744 ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
4745}
4746
4747void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
4748{
4749 GL2Encoder *ctx = (GL2Encoder*)self;
4750 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4751 ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
4752}
4753
4754void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4755{
4756 GL2Encoder *ctx = (GL2Encoder*)self;
4757 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4758 ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
4759}
4760
4761void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4762{
4763 GL2Encoder *ctx = (GL2Encoder*)self;
4764 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4765 ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
4766}
4767
4768void GL2Encoder::s_glProgramUniformMatrix2x3fv(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_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
4773}
4774
4775void GL2Encoder::s_glProgramUniformMatrix2x4fv(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_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
4780}
4781
4782void GL2Encoder::s_glProgramUniformMatrix3fv(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_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
4787}
4788
4789void GL2Encoder::s_glProgramUniformMatrix3x2fv(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_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
4794}
4795
4796void GL2Encoder::s_glProgramUniformMatrix3x4fv(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_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
4801}
4802
4803void GL2Encoder::s_glProgramUniformMatrix4fv(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_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
4808}
4809
4810void GL2Encoder::s_glProgramUniformMatrix4x2fv(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_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
4815}
4816
4817void GL2Encoder::s_glProgramUniformMatrix4x3fv(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_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
4822}
4823
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004824void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) {
4825 GL2Encoder* ctx = (GL2Encoder*)self;
4826 ctx->m_glProgramParameteri_enc(self, program, pname, value);
4827}
4828
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004829void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
4830{
4831 GL2Encoder *ctx = (GL2Encoder*)self;
4832 GLClientState* state = ctx->m_state;
4833 GLSharedGroupPtr shared = ctx->m_shared;
4834
4835 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4836 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4837 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4838
4839 ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
4840 state->associateProgramWithPipeline(program, pipeline);
4841
4842 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4843 if (state->currentProgram()) {
4844 return;
4845 }
4846
4847 // Otherwise, update host texture 2D bindings.
4848 ctx->updateHostTexture2DBindingsFromProgramData(program);
4849}
4850
4851void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
4852{
4853 GL2Encoder *ctx = (GL2Encoder*)self;
4854 GLClientState* state = ctx->m_state;
4855
4856 ctx->m_glBindProgramPipeline_enc(self, pipeline);
4857
4858 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4859 if (!pipeline || state->currentProgram()) {
4860 return;
4861 }
4862
4863 GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
4864 for (; it != state->programPipelineEnd(); ++it) {
4865 if (it->second == pipeline) {
4866 ctx->updateHostTexture2DBindingsFromProgramData(it->first);
4867 }
4868 }
4869}
4870
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004871void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
4872 GL2Encoder *ctx = (GL2Encoder*)self;
4873 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4874 if (bufSize == 0) {
4875 if (length) *length = 0;
4876 return;
4877 }
4878
4879 // Avoid modifying |name| if |*length| < bufSize.
4880 GLint* intermediate = new GLint[bufSize];
4881 GLsizei* myLength = length ? length : new GLsizei;
4882 bool needFreeLength = length == NULL;
4883
4884 ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
4885 GLsizei writtenInts = *myLength;
4886 memcpy(params, intermediate, writtenInts * sizeof(GLint));
4887
4888 delete [] intermediate;
4889 if (needFreeLength)
4890 delete myLength;
4891}
4892
4893GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
4894 GL2Encoder *ctx = (GL2Encoder*)self;
4895 return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
4896}
4897
4898GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
4899 GL2Encoder *ctx = (GL2Encoder*)self;
4900 return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
4901}
4902
4903void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
4904 GL2Encoder *ctx = (GL2Encoder*)self;
4905 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4906 if (bufSize == 0) {
4907 if (length) *length = 0;
4908 return;
4909 }
4910
4911 // Avoid modifying |name| if |*length| < bufSize.
4912 char* intermediate = new char[bufSize];
4913 GLsizei* myLength = length ? length : new GLsizei;
4914 bool needFreeLength = length == NULL;
4915
4916 ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
4917 GLsizei writtenStrLen = *myLength;
4918 memcpy(name, intermediate, writtenStrLen + 1);
4919
4920 delete [] intermediate;
4921 if (needFreeLength)
4922 delete myLength;
4923}
4924
4925void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
4926 GL2Encoder *ctx = (GL2Encoder*)self;
4927 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4928 if (bufSize == 0) {
4929 if (length) *length = 0;
4930 return;
4931 }
4932
4933 // Avoid modifying |infoLog| if |*length| < bufSize.
4934 GLchar* intermediate = new GLchar[bufSize];
4935 GLsizei* myLength = length ? length : new GLsizei;
4936 bool needFreeLength = length == NULL;
4937
4938 ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
4939 GLsizei writtenStrLen = *myLength;
4940 memcpy(infoLog, intermediate, writtenStrLen + 1);
4941
4942 delete [] intermediate;
4943 if (needFreeLength)
4944 delete myLength;
4945}
4946
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004947void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
4948 GL2Encoder *ctx = (GL2Encoder*)self;
4949 GLClientState* state = ctx->m_state;
4950
Lingfeng Yang07289902017-01-27 12:26:19 -08004951 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004952 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4953
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004954 state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false);
4955 ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset);
4956}
4957
4958void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
4959 GL2Encoder *ctx = (GL2Encoder*)self;
4960 GLClientState* state = ctx->m_state;
4961
Lingfeng Yang07289902017-01-27 12:26:19 -08004962 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004963 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4964
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004965 state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true);
4966 ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset);
4967}
4968
4969void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004970 GL2Encoder *ctx = (GL2Encoder*)self;
4971 GLClientState* state = ctx->m_state;
4972
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004973 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4974
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004975 state->setVertexBindingDivisor(bindingindex, divisor);
4976 ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor);
4977}
4978
4979void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) {
4980 GL2Encoder *ctx = (GL2Encoder*)self;
4981 GLClientState* state = ctx->m_state;
Lingfeng Yang07289902017-01-27 12:26:19 -08004982 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004983 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004984
4985 state->setVertexAttribBinding(attribindex, bindingindex);
4986 ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex);
4987}
4988
4989void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
4990 GL2Encoder *ctx = (GL2Encoder*)self;
4991 GLClientState* state = ctx->m_state;
4992
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004993 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
4994
4995 GLint maxStride;
4996 ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
4997 SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE);
4998
4999 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5000
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005001 state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride);
5002 ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride);
5003}
5004
5005void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) {
5006 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005007 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005008
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005009 bool hasClientArrays = false;
5010 ctx->getVBOUsage(&hasClientArrays, NULL);
5011
5012 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
5013 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5014 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
5015
5016 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005017 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005018 // BufferData* buf = ctx->getBufferData(target);
5019 // if (buf) {
5020 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
5021 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005022 ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect);
5023 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005024 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
5025 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005026 ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize);
5027 }
5028}
5029
5030void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) {
5031 GL2Encoder *ctx = (GL2Encoder*)self;
5032
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005033 GLClientState* state = ctx->m_state;
5034
5035 bool hasClientArrays = false;
5036 ctx->getVBOUsage(&hasClientArrays, NULL);
5037
5038 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
5039 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5040 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
5041
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005042 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005043
5044 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005045 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005046 // BufferData* buf = ctx->getBufferData(target);
5047 // if (buf) {
5048 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
5049 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005050 ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect);
5051 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005052 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
5053 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005054 ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize);
5055 }
5056
5057}
5058
5059void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
5060 GL2Encoder *ctx = (GL2Encoder*)self;
5061 GLClientState* state = ctx->m_state;
5062
5063 SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
5064 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
5065 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
5066 SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
5067 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005068 GLint max_samples;
5069 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
5070 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005071
5072 state->setBoundTextureInternalFormat(target, internalformat);
5073 state->setBoundTextureDims(target, 0, width, height, 1);
5074 state->setBoundTextureImmutableFormat(target);
5075 state->setBoundTextureSamples(target, samples);
5076
5077 ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
5078}
5079