blob: ff88b3141bb513fa2a654c54b8bdf02102ab43aa [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;
Roman Kiryanovdaecd142018-11-14 14:56:27 -080079
keunyoungb85b2752013-03-08 12:28:03 -080080 m_num_compressedTextureFormats = 0;
Lingfeng Yang48685bb2018-10-19 06:44:20 -070081 m_max_combinedTextureImageUnits = 0;
Lingfeng Yanga1edab62018-10-19 07:53:49 -070082 m_max_vertexTextureImageUnits = 0;
83 m_max_textureImageUnits = 0;
Lizhe Liue41f4ef2015-05-27 11:13:23 +080084 m_max_cubeMapTextureSize = 0;
85 m_max_renderBufferSize = 0;
86 m_max_textureSize = 0;
Lingfeng Yang46153ab2017-01-09 13:37:22 -080087 m_max_3d_textureSize = 0;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -080088 m_max_vertexAttribStride = 0;
Lingfeng Yanga1edab62018-10-19 07:53:49 -070089
90 m_max_transformFeedbackSeparateAttribs = 0;
91 m_max_uniformBufferBindings = 0;
92 m_max_colorAttachments = 0;
93 m_max_drawBuffers = 0;
94
95 m_max_atomicCounterBufferBindings = 0;
96 m_max_shaderStorageBufferBindings = 0;
97 m_max_vertexAttribBindings = 0;
98
keunyoungb85b2752013-03-08 12:28:03 -080099 m_compressedTextureFormats = NULL;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100100
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800101 m_ssbo_offset_align = 0;
102 m_ubo_offset_align = 0;
103
Lingfeng Yangde51dfb2016-10-17 22:48:59 -0700104 m_drawCallFlushCount = 0;
105 m_primitiveRestartEnabled = false;
106 m_primitiveRestartIndex = 0;
107
Lingfeng Yang07289902017-01-27 12:26:19 -0800108 // overrides
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100109#define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name
Lingfeng Yange6556dc2017-01-09 12:04:12 -0800110#define OVERRIDE_CUSTOM(name) this-> name = &s_##name
111#define OVERRIDEWITH(name, target) do { \
112 m_##target##_enc = this-> target; \
113 this-> target = &s_##name; \
114} while(0)
115#define OVERRIDEOES(name) OVERRIDEWITH(name, name##OES)
bohu56bf82f2014-10-17 15:35:48 -0700116
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100117 OVERRIDE(glFlush);
118 OVERRIDE(glPixelStorei);
119 OVERRIDE(glGetString);
120 OVERRIDE(glBindBuffer);
121 OVERRIDE(glBufferData);
122 OVERRIDE(glBufferSubData);
123 OVERRIDE(glDeleteBuffers);
124 OVERRIDE(glDrawArrays);
125 OVERRIDE(glDrawElements);
Lingfeng Yang09545912019-01-30 09:22:38 -0800126 OVERRIDE(glDrawArraysNullAEMU);
127 OVERRIDE(glDrawElementsNullAEMU);
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100128 OVERRIDE(glGetIntegerv);
129 OVERRIDE(glGetFloatv);
130 OVERRIDE(glGetBooleanv);
131 OVERRIDE(glVertexAttribPointer);
132 OVERRIDE(glEnableVertexAttribArray);
133 OVERRIDE(glDisableVertexAttribArray);
134 OVERRIDE(glGetVertexAttribiv);
135 OVERRIDE(glGetVertexAttribfv);
136 OVERRIDE(glGetVertexAttribPointerv);
keunyoungb85b2752013-03-08 12:28:03 -0800137
Bo Hu73568cd2015-01-20 16:29:50 -0800138 this->glShaderBinary = &s_glShaderBinary;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100139 this->glShaderSource = &s_glShaderSource;
140 this->glFinish = &s_glFinish;
keunyoungb85b2752013-03-08 12:28:03 -0800141
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100142 OVERRIDE(glGetError);
143 OVERRIDE(glLinkProgram);
144 OVERRIDE(glDeleteProgram);
145 OVERRIDE(glGetUniformiv);
146 OVERRIDE(glGetUniformfv);
147 OVERRIDE(glCreateProgram);
148 OVERRIDE(glCreateShader);
149 OVERRIDE(glDeleteShader);
150 OVERRIDE(glAttachShader);
151 OVERRIDE(glDetachShader);
152 OVERRIDE(glGetAttachedShaders);
153 OVERRIDE(glGetShaderSource);
154 OVERRIDE(glGetShaderInfoLog);
155 OVERRIDE(glGetProgramInfoLog);
156
157 OVERRIDE(glGetUniformLocation);
158 OVERRIDE(glUseProgram);
159
160 OVERRIDE(glUniform1f);
161 OVERRIDE(glUniform1fv);
162 OVERRIDE(glUniform1i);
163 OVERRIDE(glUniform1iv);
164 OVERRIDE(glUniform2f);
165 OVERRIDE(glUniform2fv);
166 OVERRIDE(glUniform2i);
167 OVERRIDE(glUniform2iv);
168 OVERRIDE(glUniform3f);
169 OVERRIDE(glUniform3fv);
170 OVERRIDE(glUniform3i);
171 OVERRIDE(glUniform3iv);
172 OVERRIDE(glUniform4f);
173 OVERRIDE(glUniform4fv);
174 OVERRIDE(glUniform4i);
175 OVERRIDE(glUniform4iv);
176 OVERRIDE(glUniformMatrix2fv);
177 OVERRIDE(glUniformMatrix3fv);
178 OVERRIDE(glUniformMatrix4fv);
179
180 OVERRIDE(glActiveTexture);
181 OVERRIDE(glBindTexture);
182 OVERRIDE(glDeleteTextures);
183 OVERRIDE(glGetTexParameterfv);
184 OVERRIDE(glGetTexParameteriv);
185 OVERRIDE(glTexParameterf);
186 OVERRIDE(glTexParameterfv);
187 OVERRIDE(glTexParameteri);
188 OVERRIDE(glTexParameteriv);
bohu26a92982014-11-25 16:50:37 -0800189 OVERRIDE(glTexImage2D);
Yahan Zhou2a208292016-06-22 15:36:04 -0700190 OVERRIDE(glTexSubImage2D);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -0700191 OVERRIDE(glCopyTexImage2D);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700192
193 OVERRIDE(glGenRenderbuffers);
194 OVERRIDE(glDeleteRenderbuffers);
195 OVERRIDE(glBindRenderbuffer);
Lingfeng Yang69066602016-04-12 09:29:11 -0700196 OVERRIDE(glRenderbufferStorage);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700197 OVERRIDE(glFramebufferRenderbuffer);
198
199 OVERRIDE(glGenFramebuffers);
200 OVERRIDE(glDeleteFramebuffers);
201 OVERRIDE(glBindFramebuffer);
202 OVERRIDE(glFramebufferTexture2D);
203 OVERRIDE(glFramebufferTexture3DOES);
204 OVERRIDE(glGetFramebufferAttachmentParameteriv);
Lingfeng Yang69066602016-04-12 09:29:11 -0700205
206 OVERRIDE(glCheckFramebufferStatus);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800207
208 OVERRIDE(glGenVertexArrays);
209 OVERRIDE(glDeleteVertexArrays);
210 OVERRIDE(glBindVertexArray);
211 OVERRIDEOES(glGenVertexArrays);
212 OVERRIDEOES(glDeleteVertexArrays);
213 OVERRIDEOES(glBindVertexArray);
214
Lingfeng Yangfb3d2bb2017-09-07 15:02:04 -0700215 OVERRIDE_CUSTOM(glMapBufferOES);
216 OVERRIDE_CUSTOM(glUnmapBufferOES);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800217 OVERRIDE_CUSTOM(glMapBufferRange);
218 OVERRIDE_CUSTOM(glUnmapBuffer);
219 OVERRIDE_CUSTOM(glFlushMappedBufferRange);
220
221 OVERRIDE(glCompressedTexImage2D);
222 OVERRIDE(glCompressedTexSubImage2D);
223
224 OVERRIDE(glBindBufferRange);
225 OVERRIDE(glBindBufferBase);
226
227 OVERRIDE(glCopyBufferSubData);
228
229 OVERRIDE(glGetBufferParameteriv);
230 OVERRIDE(glGetBufferParameteri64v);
231 OVERRIDE(glGetBufferPointerv);
232
233 OVERRIDE_CUSTOM(glGetUniformIndices);
234
235 OVERRIDE(glUniform1ui);
236 OVERRIDE(glUniform2ui);
237 OVERRIDE(glUniform3ui);
238 OVERRIDE(glUniform4ui);
239 OVERRIDE(glUniform1uiv);
240 OVERRIDE(glUniform2uiv);
241 OVERRIDE(glUniform3uiv);
242 OVERRIDE(glUniform4uiv);
243 OVERRIDE(glUniformMatrix2x3fv);
244 OVERRIDE(glUniformMatrix3x2fv);
245 OVERRIDE(glUniformMatrix2x4fv);
246 OVERRIDE(glUniformMatrix4x2fv);
247 OVERRIDE(glUniformMatrix3x4fv);
248 OVERRIDE(glUniformMatrix4x3fv);
249
250 OVERRIDE(glGetUniformuiv);
251 OVERRIDE(glGetActiveUniformBlockiv);
252
253 OVERRIDE(glGetVertexAttribIiv);
254 OVERRIDE(glGetVertexAttribIuiv);
255
256 OVERRIDE_CUSTOM(glVertexAttribIPointer);
257
258 OVERRIDE(glVertexAttribDivisor);
259
260 OVERRIDE(glRenderbufferStorageMultisample);
261 OVERRIDE(glDrawBuffers);
262 OVERRIDE(glReadBuffer);
263 OVERRIDE(glFramebufferTextureLayer);
264 OVERRIDE(glTexStorage2D);
265
266 OVERRIDE_CUSTOM(glTransformFeedbackVaryings);
267 OVERRIDE(glBeginTransformFeedback);
268 OVERRIDE(glEndTransformFeedback);
269 OVERRIDE(glPauseTransformFeedback);
270 OVERRIDE(glResumeTransformFeedback);
271
272 OVERRIDE(glTexImage3D);
273 OVERRIDE(glTexSubImage3D);
274 OVERRIDE(glTexStorage3D);
275 OVERRIDE(glCompressedTexImage3D);
276 OVERRIDE(glCompressedTexSubImage3D);
277
278 OVERRIDE(glDrawArraysInstanced);
279 OVERRIDE_CUSTOM(glDrawElementsInstanced);
280 OVERRIDE_CUSTOM(glDrawRangeElements);
281
282 OVERRIDE_CUSTOM(glGetStringi);
283 OVERRIDE(glGetProgramBinary);
284 OVERRIDE(glReadPixels);
285
286 OVERRIDE(glEnable);
287 OVERRIDE(glDisable);
288 OVERRIDE(glClearBufferiv);
289 OVERRIDE(glClearBufferuiv);
290 OVERRIDE(glClearBufferfv);
291 OVERRIDE(glBlitFramebuffer);
292 OVERRIDE_CUSTOM(glGetInternalformativ);
293
294 OVERRIDE(glGenerateMipmap);
295
296 OVERRIDE(glBindSampler);
297
Lingfeng Yangf000ab42017-01-11 18:31:38 -0800298 OVERRIDE_CUSTOM(glFenceSync);
299 OVERRIDE_CUSTOM(glClientWaitSync);
300 OVERRIDE_CUSTOM(glWaitSync);
301 OVERRIDE_CUSTOM(glDeleteSync);
302 OVERRIDE_CUSTOM(glIsSync);
303 OVERRIDE_CUSTOM(glGetSynciv);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800304
305 OVERRIDE(glGetIntegeri_v);
306 OVERRIDE(glGetInteger64i_v);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700307 OVERRIDE(glGetInteger64v);
308 OVERRIDE(glGetBooleani_v);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800309
310 OVERRIDE(glGetShaderiv);
311
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800312 OVERRIDE(glActiveShaderProgram);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800313 OVERRIDE_CUSTOM(glCreateShaderProgramv);
314 OVERRIDE(glProgramUniform1f);
315 OVERRIDE(glProgramUniform1fv);
316 OVERRIDE(glProgramUniform1i);
317 OVERRIDE(glProgramUniform1iv);
318 OVERRIDE(glProgramUniform1ui);
319 OVERRIDE(glProgramUniform1uiv);
320 OVERRIDE(glProgramUniform2f);
321 OVERRIDE(glProgramUniform2fv);
322 OVERRIDE(glProgramUniform2i);
323 OVERRIDE(glProgramUniform2iv);
324 OVERRIDE(glProgramUniform2ui);
325 OVERRIDE(glProgramUniform2uiv);
326 OVERRIDE(glProgramUniform3f);
327 OVERRIDE(glProgramUniform3fv);
328 OVERRIDE(glProgramUniform3i);
329 OVERRIDE(glProgramUniform3iv);
330 OVERRIDE(glProgramUniform3ui);
331 OVERRIDE(glProgramUniform3uiv);
332 OVERRIDE(glProgramUniform4f);
333 OVERRIDE(glProgramUniform4fv);
334 OVERRIDE(glProgramUniform4i);
335 OVERRIDE(glProgramUniform4iv);
336 OVERRIDE(glProgramUniform4ui);
337 OVERRIDE(glProgramUniform4uiv);
338 OVERRIDE(glProgramUniformMatrix2fv);
339 OVERRIDE(glProgramUniformMatrix2x3fv);
340 OVERRIDE(glProgramUniformMatrix2x4fv);
341 OVERRIDE(glProgramUniformMatrix3fv);
342 OVERRIDE(glProgramUniformMatrix3x2fv);
343 OVERRIDE(glProgramUniformMatrix3x4fv);
344 OVERRIDE(glProgramUniformMatrix4fv);
345 OVERRIDE(glProgramUniformMatrix4x2fv);
346 OVERRIDE(glProgramUniformMatrix4x3fv);
347
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800348 OVERRIDE(glProgramParameteri);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800349 OVERRIDE(glUseProgramStages);
350 OVERRIDE(glBindProgramPipeline);
351
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800352 OVERRIDE(glGetProgramResourceiv);
353 OVERRIDE(glGetProgramResourceIndex);
354 OVERRIDE(glGetProgramResourceLocation);
355 OVERRIDE(glGetProgramResourceName);
356 OVERRIDE(glGetProgramPipelineInfoLog);
357
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800358 OVERRIDE(glVertexAttribFormat);
359 OVERRIDE(glVertexAttribIFormat);
360 OVERRIDE(glVertexBindingDivisor);
361 OVERRIDE(glVertexAttribBinding);
362 OVERRIDE(glBindVertexBuffer);
363
364 OVERRIDE_CUSTOM(glDrawArraysIndirect);
365 OVERRIDE_CUSTOM(glDrawElementsIndirect);
366
367 OVERRIDE(glTexStorage2DMultisample);
Yahan Zhou72944ba2019-01-02 15:43:46 -0800368
369 OVERRIDE_CUSTOM(glGetGraphicsResetStatusEXT);
370 OVERRIDE_CUSTOM(glReadnPixelsEXT);
371 OVERRIDE_CUSTOM(glGetnUniformfvEXT);
372 OVERRIDE_CUSTOM(glGetnUniformivEXT);
keunyoungb85b2752013-03-08 12:28:03 -0800373}
374
375GL2Encoder::~GL2Encoder()
376{
377 delete m_compressedTextureFormats;
378}
379
380GLenum GL2Encoder::s_glGetError(void * self)
381{
382 GL2Encoder *ctx = (GL2Encoder *)self;
383 GLenum err = ctx->getError();
384 if(err != GL_NO_ERROR) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700385 ctx->m_glGetError_enc(ctx); // also clear host error
keunyoungb85b2752013-03-08 12:28:03 -0800386 ctx->setError(GL_NO_ERROR);
387 return err;
388 }
389
Lingfeng Yange980c7a2018-01-12 14:50:18 -0800390 if (ctx->m_noHostError) {
391 return GL_NO_ERROR;
392 } else {
393 return ctx->m_glGetError_enc(self);
394 }
Lingfeng Yang80a36332017-07-09 10:58:07 -0700395}
Yahan Zhouae30fe82016-08-10 21:15:45 +0000396
Lingfeng Yang80a36332017-07-09 10:58:07 -0700397class GL2Encoder::ErrorUpdater {
398public:
399 ErrorUpdater(GL2Encoder* ctx) :
400 mCtx(ctx),
401 guest_error(ctx->getError()),
402 host_error(ctx->m_glGetError_enc(ctx)) {
403 // Preserve any existing GL error in the guest:
404 // OpenGL ES 3.0.5 spec:
405 // The command enum GetError( void ); is used to obtain error information.
406 // Each detectable error is assigned a numeric code. When an error is
407 // detected, a flag is set and the code is recorded. Further errors, if
408 // they occur, do not affect this recorded code. When GetError is called,
409 // the code is returned and the flag is cleared, so that a further error
410 // will again record its code. If a call to GetError returns NO_ERROR, then
411 // there has been no detectable error since the last call to GetError (or
412 // since the GL was initialized).
413 if (guest_error == GL_NO_ERROR) {
414 guest_error = host_error;
415 }
416 }
417
418 GLenum getHostErrorAndUpdate() {
419 host_error = mCtx->m_glGetError_enc(mCtx);
420 if (guest_error == GL_NO_ERROR) {
421 guest_error = host_error;
422 }
423 return host_error;
424 }
425
426 void updateGuestErrorState() {
427 mCtx->setError(guest_error);
428 }
429
430private:
431 GL2Encoder* mCtx;
432 GLenum guest_error;
433 GLenum host_error;
434};
435
436template<class T>
437class GL2Encoder::ScopedQueryUpdate {
438public:
439 ScopedQueryUpdate(GL2Encoder* ctx, uint32_t bytes, T* target) :
440 mCtx(ctx),
441 mBuf(bytes, 0),
442 mTarget(target),
443 mErrorUpdater(ctx) {
444 }
445 T* hostStagingBuffer() {
446 return (T*)&mBuf[0];
447 }
448 ~ScopedQueryUpdate() {
449 GLint hostError = mErrorUpdater.getHostErrorAndUpdate();
Lingfeng Yang72ecf472018-06-11 14:20:14 -0700450 if (hostError == GL_NO_ERROR && mTarget) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700451 memcpy(mTarget, &mBuf[0], mBuf.size());
452 }
453 mErrorUpdater.updateGuestErrorState();
454 }
455private:
456 GL2Encoder* mCtx;
457 std::vector<char> mBuf;
458 T* mTarget;
459 ErrorUpdater mErrorUpdater;
460};
461
462void GL2Encoder::safe_glGetBooleanv(GLenum param, GLboolean* val) {
463 ScopedQueryUpdate<GLboolean> query(this, glUtilsParamSize(param) * sizeof(GLboolean), val);
464 m_glGetBooleanv_enc(this, param, query.hostStagingBuffer());
465}
466
467void GL2Encoder::safe_glGetFloatv(GLenum param, GLfloat* val) {
468 ScopedQueryUpdate<GLfloat> query(this, glUtilsParamSize(param) * sizeof(GLfloat), val);
469 m_glGetFloatv_enc(this, param, query.hostStagingBuffer());
470}
471
472void GL2Encoder::safe_glGetIntegerv(GLenum param, GLint* val) {
473 ScopedQueryUpdate<GLint> query(this, glUtilsParamSize(param) * sizeof(GLint), val);
474 m_glGetIntegerv_enc(this, param, query.hostStagingBuffer());
475}
476
477void GL2Encoder::safe_glGetInteger64v(GLenum param, GLint64* val) {
478 ScopedQueryUpdate<GLint64> query(this, glUtilsParamSize(param) * sizeof(GLint64), val);
479 m_glGetInteger64v_enc(this, param, query.hostStagingBuffer());
480}
481
482void GL2Encoder::safe_glGetIntegeri_v(GLenum param, GLuint index, GLint* val) {
483 ScopedQueryUpdate<GLint> query(this, sizeof(GLint), val);
484 m_glGetIntegeri_v_enc(this, param, index, query.hostStagingBuffer());
485}
486
487void GL2Encoder::safe_glGetInteger64i_v(GLenum param, GLuint index, GLint64* val) {
488 ScopedQueryUpdate<GLint64> query(this, sizeof(GLint64), val);
489 m_glGetInteger64i_v_enc(this, param, index, query.hostStagingBuffer());
490}
491
492void GL2Encoder::safe_glGetBooleani_v(GLenum param, GLuint index, GLboolean* val) {
493 ScopedQueryUpdate<GLboolean> query(this, sizeof(GLboolean), val);
494 m_glGetBooleani_v_enc(this, param, index, query.hostStagingBuffer());
keunyoungb85b2752013-03-08 12:28:03 -0800495}
496
497void GL2Encoder::s_glFlush(void *self)
498{
499 GL2Encoder *ctx = (GL2Encoder *) self;
500 ctx->m_glFlush_enc(self);
501 ctx->m_stream->flush();
502}
503
504const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
505{
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800506 GL2Encoder *ctx = (GL2Encoder *)self;
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100507
keunyoungb85b2752013-03-08 12:28:03 -0800508 GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800509 RET_AND_SET_ERROR_IF(
510 name != GL_VENDOR &&
511 name != GL_RENDERER &&
512 name != GL_VERSION &&
513 name != GL_EXTENSIONS,
514 GL_INVALID_ENUM,
515 retval);
keunyoungb85b2752013-03-08 12:28:03 -0800516 switch(name) {
517 case GL_VENDOR:
518 retval = gVendorString;
519 break;
520 case GL_RENDERER:
521 retval = gRendererString;
522 break;
523 case GL_VERSION:
524 retval = gVersionString;
525 break;
526 case GL_EXTENSIONS:
527 retval = gExtensionsString;
528 break;
529 }
530 return retval;
531}
532
533void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
534{
535 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800536 SET_ERROR_IF(!GLESv2Validation::pixelStoreParam(ctx, param), GL_INVALID_ENUM);
537 SET_ERROR_IF(!GLESv2Validation::pixelStoreValue(param, value), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800538 ctx->m_glPixelStorei_enc(ctx, param, value);
539 assert(ctx->m_state != NULL);
540 ctx->m_state->setPixelStore(param, value);
541}
keunyoungb85b2752013-03-08 12:28:03 -0800542void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
543{
544 GL2Encoder *ctx = (GL2Encoder *) self;
545 assert(ctx->m_state != NULL);
546 ctx->m_state->bindBuffer(target, id);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800547 ctx->m_state->addBuffer(id);
keunyoungb85b2752013-03-08 12:28:03 -0800548 // TODO set error state if needed;
549 ctx->m_glBindBuffer_enc(self, target, id);
550}
551
552void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
553{
554 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800555 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800556 GLuint bufferId = ctx->m_state->getBuffer(target);
557 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
558 SET_ERROR_IF(size<0, GL_INVALID_VALUE);
559
Roman Kiryanovfb903d62018-09-19 13:38:53 -0700560 ctx->m_shared->updateBufferData(bufferId, size, data);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800561 ctx->m_shared->setBufferUsage(bufferId, usage);
keunyoungb85b2752013-03-08 12:28:03 -0800562 ctx->m_glBufferData_enc(self, target, size, data, usage);
563}
564
565void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
566{
567 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800568 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800569 GLuint bufferId = ctx->m_state->getBuffer(target);
570 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800571 SET_ERROR_IF(ctx->isBufferTargetMapped(target), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800572
Roman Kiryanovfb903d62018-09-19 13:38:53 -0700573 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, data);
keunyoungb85b2752013-03-08 12:28:03 -0800574 SET_ERROR_IF(res, res);
575
576 ctx->m_glBufferSubData_enc(self, target, offset, size, data);
577}
578
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800579void GL2Encoder::s_glGenBuffers(void* self, GLsizei n, GLuint* buffers) {
580 GL2Encoder *ctx = (GL2Encoder *) self;
581 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
582 ctx->m_glGenBuffers_enc(self, n, buffers);
583 for (int i = 0; i < n; i++) {
584 ctx->m_state->addBuffer(buffers[i]);
585 }
586}
587
keunyoungb85b2752013-03-08 12:28:03 -0800588void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
589{
590 GL2Encoder *ctx = (GL2Encoder *) self;
591 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
592 for (int i=0; i<n; i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800593 // Technically if the buffer is mapped, we should unmap it, but we won't
594 // use it anymore after this :)
keunyoungb85b2752013-03-08 12:28:03 -0800595 ctx->m_shared->deleteBufferData(buffers[i]);
bohub0f0cdf2014-11-06 18:08:07 -0800596 ctx->m_state->unBindBuffer(buffers[i]);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800597 ctx->m_state->removeBuffer(buffers[i]);
keunyoungb85b2752013-03-08 12:28:03 -0800598 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
599 }
600}
601
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700602static bool isValidVertexAttribIndex(void *self, GLuint indx)
603{
Lingfeng Yang07289902017-01-27 12:26:19 -0800604 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700605 GLint maxIndex;
606 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
607 return indx < maxIndex;
608}
609
Lingfeng Yang07289902017-01-27 12:26:19 -0800610#define VALIDATE_VERTEX_ATTRIB_INDEX(index) \
611 SET_ERROR_WITH_MESSAGE_IF( \
612 !isValidVertexAttribIndex(self, index), GL_INVALID_VALUE, \
613 GLESv2Validation::vertexAttribIndexRangeErrorMsg, (ctx, index)); \
614
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100615void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
keunyoungb85b2752013-03-08 12:28:03 -0800616{
617 GL2Encoder *ctx = (GL2Encoder *)self;
618 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -0800619 VALIDATE_VERTEX_ATTRIB_INDEX(indx);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700620 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800621 SET_ERROR_IF(!GLESv2Validation::vertexAttribType(ctx, type), GL_INVALID_ENUM);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700622 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800623 SET_ERROR_IF((type == GL_INT_2_10_10_10_REV ||
624 type == GL_UNSIGNED_INT_2_10_10_10_REV) &&
625 size != 4,
626 GL_INVALID_OPERATION);
627 ctx->m_state->setVertexAttribBinding(indx, indx);
628 ctx->m_state->setVertexAttribFormat(indx, size, type, normalized, 0, false);
629
630 GLsizei effectiveStride = stride;
631 if (stride == 0) {
632 effectiveStride = glSizeof(type) * size;
633 switch (type) {
634 case GL_INT_2_10_10_10_REV:
635 case GL_UNSIGNED_INT_2_10_10_10_REV:
636 effectiveStride /= 4;
637 break;
638 default:
639 break;
640 }
641 }
642
643 ctx->m_state->bindIndexedBuffer(0, indx, ctx->m_state->currentArrayVbo(), (uintptr_t)ptr, 0, stride, effectiveStride);
644
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800645 if (ctx->m_state->currentArrayVbo() != 0) {
646 ctx->glVertexAttribPointerOffset(ctx, indx, size, type, normalized, stride, (uintptr_t)ptr);
647 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800648 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && ptr, GL_INVALID_OPERATION);
649 // wait for client-array handler
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800650 }
keunyoungb85b2752013-03-08 12:28:03 -0800651}
652
653void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
654{
655 GL2Encoder *ctx = (GL2Encoder *) self;
keunyoungb85b2752013-03-08 12:28:03 -0800656 GLClientState* state = ctx->m_state;
657
658 switch (param) {
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -0800659 case GL_NUM_EXTENSIONS:
660 *ptr = (int)ctx->m_currExtensionsArray.size();
661 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800662 case GL_MAJOR_VERSION:
Lingfeng Yang324c8452017-02-17 09:56:26 -0800663 *ptr = ctx->m_deviceMajorVersion;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800664 break;
665 case GL_MINOR_VERSION:
Lingfeng Yang324c8452017-02-17 09:56:26 -0800666 *ptr = ctx->m_deviceMinorVersion;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800667 break;
keunyoungb85b2752013-03-08 12:28:03 -0800668 case GL_NUM_SHADER_BINARY_FORMATS:
669 *ptr = 0;
670 break;
671 case GL_SHADER_BINARY_FORMATS:
672 // do nothing
673 break;
674
675 case GL_COMPRESSED_TEXTURE_FORMATS: {
676 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
677 if (ctx->m_num_compressedTextureFormats > 0 &&
678 compressedTextureFormats != NULL) {
679 memcpy(ptr, compressedTextureFormats,
680 ctx->m_num_compressedTextureFormats * sizeof(GLint));
681 }
682 break;
683 }
684
685 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
Lingfeng Yang48685bb2018-10-19 06:44:20 -0700686 if (ctx->m_max_combinedTextureImageUnits != 0) {
687 *ptr = ctx->m_max_combinedTextureImageUnits;
688 } else {
689 ctx->safe_glGetIntegerv(param, ptr);
690 ctx->m_max_combinedTextureImageUnits = *ptr;
691 }
692 break;
keunyoungb85b2752013-03-08 12:28:03 -0800693 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700694 if (ctx->m_max_vertexTextureImageUnits != 0) {
695 *ptr = ctx->m_max_vertexTextureImageUnits;
696 } else {
697 ctx->safe_glGetIntegerv(param, ptr);
698 ctx->m_max_vertexTextureImageUnits = *ptr;
699 }
keunyoungb85b2752013-03-08 12:28:03 -0800700 break;
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700701 case GL_MAX_TEXTURE_IMAGE_UNITS:
702 if (ctx->m_max_textureImageUnits != 0) {
703 *ptr = ctx->m_max_textureImageUnits;
704 } else {
705 ctx->safe_glGetIntegerv(param, ptr);
706 ctx->m_max_textureImageUnits = *ptr;
707 }
708 break;
keunyoungb85b2752013-03-08 12:28:03 -0800709 case GL_TEXTURE_BINDING_2D:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700710 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800711 *ptr = state->getBoundTexture(GL_TEXTURE_2D);
712 break;
713 case GL_TEXTURE_BINDING_EXTERNAL_OES:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700714 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800715 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
716 break;
717
Lingfeng Yangb0176982016-03-01 21:27:49 -0800718 case GL_MAX_VERTEX_ATTRIBS:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700719 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
720 if (!state->getClientStateParameter<GLint>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700721 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700722 state->setMaxVertexAttribs(*ptr);
Yahan Zhoua5c36842016-06-01 12:49:39 -0700723 }
724 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800725 case GL_MAX_VERTEX_ATTRIB_STRIDE:
726 if (ctx->m_max_vertexAttribStride != 0) {
727 *ptr = ctx->m_max_vertexAttribStride;
728 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700729 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800730 ctx->m_max_vertexAttribStride = *ptr;
731 }
732 break;
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800733 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
734 if (ctx->m_max_cubeMapTextureSize != 0) {
735 *ptr = ctx->m_max_cubeMapTextureSize;
736 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700737 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800738 ctx->m_max_cubeMapTextureSize = *ptr;
739 }
740 break;
741 case GL_MAX_RENDERBUFFER_SIZE:
742 if (ctx->m_max_renderBufferSize != 0) {
743 *ptr = ctx->m_max_renderBufferSize;
744 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700745 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800746 ctx->m_max_renderBufferSize = *ptr;
747 }
748 break;
749 case GL_MAX_TEXTURE_SIZE:
750 if (ctx->m_max_textureSize != 0) {
751 *ptr = ctx->m_max_textureSize;
752 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700753 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800754 ctx->m_max_textureSize = *ptr;
Lingfeng Yangb0176982016-03-01 21:27:49 -0800755 }
756 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800757 case GL_MAX_3D_TEXTURE_SIZE:
758 if (ctx->m_max_3d_textureSize != 0) {
759 *ptr = ctx->m_max_3d_textureSize;
760 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700761 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800762 ctx->m_max_3d_textureSize = *ptr;
763 }
764 break;
765 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
766 if (ctx->m_ssbo_offset_align != 0) {
767 *ptr = ctx->m_ssbo_offset_align;
768 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700769 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800770 ctx->m_ssbo_offset_align = *ptr;
771 }
772 break;
773 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
774 if (ctx->m_ubo_offset_align != 0) {
775 *ptr = ctx->m_ubo_offset_align;
776 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700777 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800778 ctx->m_ubo_offset_align = *ptr;
779 }
780 break;
781 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
782 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
783 case GL_MAX_SAMPLES:
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800784 case GL_MAX_COLOR_TEXTURE_SAMPLES:
785 case GL_MAX_INTEGER_SAMPLES:
786 case GL_MAX_DEPTH_TEXTURE_SAMPLES:
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800787 *ptr = 4;
788 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700789 // Checks for version-incompatible enums.
790 // Not allowed in vanilla ES 2.0.
791 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700792 SET_ERROR_IF(ctx->majorVersion() < 3, GL_INVALID_ENUM);
793 if (ctx->m_max_transformFeedbackSeparateAttribs != 0) {
794 *ptr = ctx->m_max_transformFeedbackSeparateAttribs;
795 } else {
796 ctx->safe_glGetIntegerv(param, ptr);
797 ctx->m_max_transformFeedbackSeparateAttribs = *ptr;
798 }
799 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700800 case GL_MAX_UNIFORM_BUFFER_BINDINGS:
801 SET_ERROR_IF(ctx->majorVersion() < 3, GL_INVALID_ENUM);
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700802 if (ctx->m_max_uniformBufferBindings != 0) {
803 *ptr = ctx->m_max_uniformBufferBindings;
804 } else {
805 ctx->safe_glGetIntegerv(param, ptr);
806 ctx->m_max_uniformBufferBindings = *ptr;
807 }
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700808 break;
809 case GL_MAX_COLOR_ATTACHMENTS:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700810 SET_ERROR_IF(ctx->majorVersion() < 3 &&
811 !ctx->hasExtension("GL_EXT_draw_buffers"), GL_INVALID_ENUM);
812 if (ctx->m_max_colorAttachments != 0) {
813 *ptr = ctx->m_max_colorAttachments;
814 } else {
815 ctx->safe_glGetIntegerv(param, ptr);
816 ctx->m_max_colorAttachments = *ptr;
817 }
818 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700819 case GL_MAX_DRAW_BUFFERS:
820 SET_ERROR_IF(ctx->majorVersion() < 3 &&
821 !ctx->hasExtension("GL_EXT_draw_buffers"), GL_INVALID_ENUM);
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700822 if (ctx->m_max_drawBuffers != 0) {
823 *ptr = ctx->m_max_drawBuffers;
824 } else {
825 ctx->safe_glGetIntegerv(param, ptr);
826 ctx->m_max_drawBuffers = *ptr;
827 }
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700828 break;
829 // Not allowed in ES 3.0.
830 case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700831 SET_ERROR_IF(ctx->majorVersion() < 3 ||
832 (ctx->majorVersion() == 3 &&
833 ctx->minorVersion() == 0), GL_INVALID_ENUM);
834 if (ctx->m_max_atomicCounterBufferBindings != 0) {
835 *ptr = ctx->m_max_atomicCounterBufferBindings;
836 } else {
837 ctx->safe_glGetIntegerv(param, ptr);
838 ctx->m_max_atomicCounterBufferBindings = *ptr;
839 }
840 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700841 case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700842 SET_ERROR_IF(ctx->majorVersion() < 3 ||
843 (ctx->majorVersion() == 3 &&
844 ctx->minorVersion() == 0), GL_INVALID_ENUM);
845 if (ctx->m_max_shaderStorageBufferBindings != 0) {
846 *ptr = ctx->m_max_shaderStorageBufferBindings;
847 } else {
848 ctx->safe_glGetIntegerv(param, ptr);
849 ctx->m_max_shaderStorageBufferBindings = *ptr;
850 }
851 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700852 case GL_MAX_VERTEX_ATTRIB_BINDINGS:
853 SET_ERROR_IF(ctx->majorVersion() < 3 ||
854 (ctx->majorVersion() == 3 &&
855 ctx->minorVersion() == 0), GL_INVALID_ENUM);
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700856 if (ctx->m_max_vertexAttribBindings != 0) {
857 *ptr = ctx->m_max_vertexAttribBindings;
858 } else {
859 ctx->safe_glGetIntegerv(param, ptr);
860 ctx->m_max_vertexAttribBindings = *ptr;
861 }
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700862 break;
Yahan Zhou72944ba2019-01-02 15:43:46 -0800863 case GL_RESET_NOTIFICATION_STRATEGY_EXT:
864 // BUG: 121414786
865 *ptr = GL_LOSE_CONTEXT_ON_RESET_EXT;
866 break;
keunyoungb85b2752013-03-08 12:28:03 -0800867 default:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700868 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
869 if (!state->getClientStateParameter<GLint>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700870 ctx->safe_glGetIntegerv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800871 }
872 break;
873 }
874}
875
876
877void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
878{
879 GL2Encoder *ctx = (GL2Encoder *)self;
keunyoungb85b2752013-03-08 12:28:03 -0800880 GLClientState* state = ctx->m_state;
881
882 switch (param) {
883 case GL_NUM_SHADER_BINARY_FORMATS:
884 *ptr = 0;
885 break;
886 case GL_SHADER_BINARY_FORMATS:
887 // do nothing
888 break;
889
890 case GL_COMPRESSED_TEXTURE_FORMATS: {
891 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
892 if (ctx->m_num_compressedTextureFormats > 0 &&
893 compressedTextureFormats != NULL) {
894 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
895 ptr[i] = (GLfloat) compressedTextureFormats[i];
896 }
897 }
898 break;
899 }
900
901 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
902 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
903 case GL_MAX_TEXTURE_IMAGE_UNITS:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700904 case GL_MAX_VERTEX_ATTRIBS:
905 case GL_MAX_VERTEX_ATTRIB_STRIDE:
906 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
907 case GL_MAX_RENDERBUFFER_SIZE:
908 case GL_MAX_TEXTURE_SIZE:
909 case GL_MAX_3D_TEXTURE_SIZE:
910 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
911 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
912 case GL_MAX_SAMPLES:
913 case GL_MAX_COLOR_TEXTURE_SAMPLES:
914 case GL_MAX_INTEGER_SAMPLES:
915 case GL_MAX_DEPTH_TEXTURE_SAMPLES:
916 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
917 case GL_MAX_UNIFORM_BUFFER_BINDINGS:
918 case GL_MAX_COLOR_ATTACHMENTS:
919 case GL_MAX_DRAW_BUFFERS:
920 case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
921 case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
922 case GL_MAX_VERTEX_ATTRIB_BINDINGS:
keunyoungb85b2752013-03-08 12:28:03 -0800923 case GL_TEXTURE_BINDING_2D:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700924 case GL_TEXTURE_BINDING_EXTERNAL_OES: {
925 GLint res;
926 s_glGetIntegerv(ctx, param, &res);
927 *ptr = (GLfloat)res;
keunyoungb85b2752013-03-08 12:28:03 -0800928 break;
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700929 }
keunyoungb85b2752013-03-08 12:28:03 -0800930
931 default:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700932 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
933 if (!state->getClientStateParameter<GLfloat>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700934 ctx->safe_glGetFloatv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800935 }
936 break;
937 }
938}
939
940
941void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
942{
943 GL2Encoder *ctx = (GL2Encoder *)self;
keunyoungb85b2752013-03-08 12:28:03 -0800944 GLClientState* state = ctx->m_state;
945
946 switch (param) {
947 case GL_NUM_SHADER_BINARY_FORMATS:
948 *ptr = GL_FALSE;
949 break;
950 case GL_SHADER_BINARY_FORMATS:
951 // do nothing
952 break;
953
954 case GL_COMPRESSED_TEXTURE_FORMATS: {
955 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
956 if (ctx->m_num_compressedTextureFormats > 0 &&
957 compressedTextureFormats != NULL) {
958 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
959 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
960 }
961 }
962 break;
963 }
964
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700965 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
966 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
967 case GL_MAX_TEXTURE_IMAGE_UNITS:
968 case GL_MAX_VERTEX_ATTRIBS:
969 case GL_MAX_VERTEX_ATTRIB_STRIDE:
970 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
971 case GL_MAX_RENDERBUFFER_SIZE:
972 case GL_MAX_TEXTURE_SIZE:
973 case GL_MAX_3D_TEXTURE_SIZE:
974 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
975 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
976 case GL_MAX_SAMPLES:
977 case GL_MAX_COLOR_TEXTURE_SAMPLES:
978 case GL_MAX_INTEGER_SAMPLES:
979 case GL_MAX_DEPTH_TEXTURE_SAMPLES:
980 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
981 case GL_MAX_UNIFORM_BUFFER_BINDINGS:
982 case GL_MAX_COLOR_ATTACHMENTS:
983 case GL_MAX_DRAW_BUFFERS:
984 case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
985 case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
986 case GL_MAX_VERTEX_ATTRIB_BINDINGS:
keunyoungb85b2752013-03-08 12:28:03 -0800987 case GL_TEXTURE_BINDING_2D:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700988 case GL_TEXTURE_BINDING_EXTERNAL_OES: {
989 GLint res;
990 s_glGetIntegerv(ctx, param, &res);
991 *ptr = res == 0 ? GL_FALSE : GL_TRUE;
keunyoungb85b2752013-03-08 12:28:03 -0800992 break;
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700993 }
keunyoungb85b2752013-03-08 12:28:03 -0800994
995 default:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700996 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
997 if (!state->getClientStateParameter<GLboolean>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700998 ctx->safe_glGetBooleanv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800999 }
bohu05101d22014-11-17 16:28:42 -08001000 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
keunyoungb85b2752013-03-08 12:28:03 -08001001 break;
1002 }
1003}
1004
1005
1006void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
1007{
1008 GL2Encoder *ctx = (GL2Encoder *)self;
1009 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -08001010 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001011 ctx->m_glEnableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -08001012 ctx->m_state->enable(index, 1);
1013}
1014
1015void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
1016{
1017 GL2Encoder *ctx = (GL2Encoder *)self;
1018 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -08001019 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001020 ctx->m_glDisableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -08001021 ctx->m_state->enable(index, 0);
1022}
1023
1024
1025void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
1026{
1027 GL2Encoder *ctx = (GL2Encoder *)self;
1028 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -07001029 GLint maxIndex;
1030 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
1031 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001032
1033 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
1034 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
1035 }
1036}
1037
1038void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
1039{
1040 GL2Encoder *ctx = (GL2Encoder *)self;
1041 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -07001042 GLint maxIndex;
1043 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
1044 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001045
1046 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
1047 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
1048 }
1049}
1050
1051void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
1052{
1053 GL2Encoder *ctx = (GL2Encoder *)self;
1054 if (ctx->m_state == NULL) return;
Lingfeng Yang5e100432016-04-08 12:46:42 -07001055 GLint maxIndex;
1056 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
1057 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
1058 SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +01001059 (void)pname;
1060
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001061 *pointer = (GLvoid*)(ctx->m_state->getCurrAttributeBindingInfo(index).offset);
keunyoungb85b2752013-03-08 12:28:03 -08001062}
1063
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001064void GL2Encoder::calcIndexRange(const void* indices,
1065 GLenum type,
1066 GLsizei count,
1067 int* minIndex_out,
1068 int* maxIndex_out) {
1069 switch(type) {
1070 case GL_BYTE:
1071 case GL_UNSIGNED_BYTE:
1072 GLUtils::minmaxExcept(
1073 (unsigned char *)indices, count,
1074 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001075 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned char>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001076 break;
1077 case GL_SHORT:
1078 case GL_UNSIGNED_SHORT:
1079 GLUtils::minmaxExcept(
1080 (unsigned short *)indices, count,
1081 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001082 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned short>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001083 break;
1084 case GL_INT:
1085 case GL_UNSIGNED_INT:
1086 GLUtils::minmaxExcept(
1087 (unsigned int *)indices, count,
1088 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001089 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned int>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001090 break;
1091 default:
1092 ALOGE("unsupported index buffer type %d\n", type);
1093 }
1094}
1095
1096void* GL2Encoder::recenterIndices(const void* src,
1097 GLenum type,
1098 GLsizei count,
1099 int minIndex) {
1100
1101 void* adjustedIndices = (void*)src;
1102
1103 if (minIndex != 0) {
1104 adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count);
1105 switch(type) {
1106 case GL_BYTE:
1107 case GL_UNSIGNED_BYTE:
1108 GLUtils::shiftIndicesExcept(
1109 (unsigned char *)src,
1110 (unsigned char *)adjustedIndices,
1111 count, -minIndex,
1112 m_primitiveRestartEnabled,
1113 (unsigned char)m_primitiveRestartIndex);
1114 break;
1115 case GL_SHORT:
1116 case GL_UNSIGNED_SHORT:
1117 GLUtils::shiftIndicesExcept(
1118 (unsigned short *)src,
1119 (unsigned short *)adjustedIndices,
1120 count, -minIndex,
1121 m_primitiveRestartEnabled,
1122 (unsigned short)m_primitiveRestartIndex);
1123 break;
1124 case GL_INT:
1125 case GL_UNSIGNED_INT:
1126 GLUtils::shiftIndicesExcept(
1127 (unsigned int *)src,
1128 (unsigned int *)adjustedIndices,
1129 count, -minIndex,
1130 m_primitiveRestartEnabled,
1131 (unsigned int)m_primitiveRestartIndex);
1132 break;
1133 default:
1134 ALOGE("unsupported index buffer type %d\n", type);
1135 }
1136 }
1137
1138 return adjustedIndices;
1139}
1140
1141void GL2Encoder::getBufferIndexRange(BufferData* buf,
1142 const void* dataWithOffset,
1143 GLenum type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001144 size_t count,
1145 size_t offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001146 int* minIndex_out,
1147 int* maxIndex_out) {
1148
1149 if (buf->m_indexRangeCache.findRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001150 type, offset, count,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001151 m_primitiveRestartEnabled,
1152 minIndex_out,
1153 maxIndex_out)) {
1154 return;
1155 }
1156
1157 calcIndexRange(dataWithOffset, type, count, minIndex_out, maxIndex_out);
1158
1159 buf->m_indexRangeCache.addRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001160 type, offset, count, m_primitiveRestartEnabled,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001161 *minIndex_out, *maxIndex_out);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001162
1163 ALOGV("%s: got range [%u %u] pr? %d", __FUNCTION__, *minIndex_out, *maxIndex_out, m_primitiveRestartEnabled);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001164}
keunyoungb85b2752013-03-08 12:28:03 -08001165
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001166// For detecting legacy usage of glVertexAttribPointer
1167void GL2Encoder::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) const {
1168 if (hasClientArrays) *hasClientArrays = false;
1169 if (hasVBOs) *hasVBOs = false;
1170
1171 for (int i = 0; i < m_state->nLocations(); i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001172 const GLClientState::VertexAttribState& state = m_state->getState(i);
1173 if (state.enabled) {
1174 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
1175 GLuint bufferObject = curr_binding.buffer;
1176 if (bufferObject == 0 && curr_binding.offset && hasClientArrays) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001177 *hasClientArrays = true;
1178 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001179 if (bufferObject != 0 && hasVBOs) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001180 *hasVBOs = true;
1181 }
1182 }
1183 }
1184}
1185
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001186void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count, bool hasClientArrays, GLsizei primcount)
keunyoungb85b2752013-03-08 12:28:03 -08001187{
1188 assert(m_state);
1189
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001190 GLuint currentVao = m_state->currentVertexArrayObject();
Lingfeng Yang398162b2016-05-26 14:18:33 -07001191 GLuint lastBoundVbo = m_state->currentArrayVbo();
keunyoungb85b2752013-03-08 12:28:03 -08001192 for (int i = 0; i < m_state->nLocations(); i++) {
1193 bool enableDirty;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001194 const GLClientState::VertexAttribState& state = m_state->getStateAndEnableDirty(i, &enableDirty);
keunyoungb85b2752013-03-08 12:28:03 -08001195
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001196 if (!enableDirty && !state.enabled) {
keunyoungb85b2752013-03-08 12:28:03 -08001197 continue;
1198 }
1199
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001200 if (state.enabled) {
1201 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
1202 GLuint bufferObject = curr_binding.buffer;
1203 if (hasClientArrays && lastBoundVbo != bufferObject) {
1204 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, bufferObject);
1205 lastBoundVbo = bufferObject;
Lingfeng Yang398162b2016-05-26 14:18:33 -07001206 }
keunyoungb85b2752013-03-08 12:28:03 -08001207
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001208 int divisor = curr_binding.divisor;
1209 int stride = curr_binding.stride;
1210 int effectiveStride = curr_binding.effectiveStride;
1211 uintptr_t offset = curr_binding.offset;
Lingfeng Yang4e5446b2017-02-15 08:44:21 -08001212
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001213 int firstIndex = effectiveStride * first;
Lingfeng Yang4e5446b2017-02-15 08:44:21 -08001214 if (firstIndex && divisor && !primcount) {
1215 // If firstIndex != 0 according to effectiveStride * first,
1216 // it needs to be adjusted if a divisor has been specified,
1217 // even if we are not in glDraw***Instanced.
1218 firstIndex = 0;
1219 }
keunyoungb85b2752013-03-08 12:28:03 -08001220
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001221 if (bufferObject == 0) {
1222 unsigned int datalen = state.elementSize * count;
Yahan Zhoufe1820e2018-12-06 17:18:12 -08001223 if (divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001224 ALOGV("%s: divisor for att %d: %d, w/ stride %d (effective stride %d) size %d type 0x%x) datalen %u",
1225 __FUNCTION__, i, divisor, state.stride, effectiveStride, state.elementSize, state.type, datalen);
1226 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
1227 datalen = state.elementSize * actual_count;
1228 ALOGV("%s: actual datalen %u", __FUNCTION__, datalen);
1229 }
1230 if (state.elementSize == 0) {
Yahan Zhou3f2f1b42016-12-01 13:49:44 -08001231 // The vertex attribute array is uninitialized. Abandon it.
1232 ALOGE("a vertex attribute array is uninitialized. Skipping corresponding vertex attribute.");
1233 this->m_glDisableVertexAttribArray_enc(this, i);
1234 continue;
1235 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001236 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang000cf4c2017-01-25 08:09:02 -08001237
1238 if (datalen && (!offset || !((unsigned char*)offset + firstIndex))) {
1239 ALOGD("%s: bad offset / len!!!!!", __FUNCTION__);
1240 continue;
1241 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001242 if (state.isInt) {
1243 this->glVertexAttribIPointerDataAEMU(this, i, state.size, state.type, stride, (unsigned char *)offset + firstIndex, datalen);
1244 } else {
1245 this->glVertexAttribPointerData(this, i, state.size, state.type, state.normalized, stride, (unsigned char *)offset + firstIndex, datalen);
1246 }
keunyoungb85b2752013-03-08 12:28:03 -08001247 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001248 const BufferData* buf = m_shared->getBufferData(bufferObject);
Yahan Zhou5507c042016-06-01 17:24:28 -07001249 // The following expression actually means bufLen = stride*count;
1250 // But the last element doesn't have to fill up the whole stride.
1251 // So it becomes the current form.
Lingfeng Yang5fe99012017-01-18 09:17:09 -08001252 unsigned int bufLen = effectiveStride * (count ? (count - 1) : 0) + state.elementSize;
Yahan Zhoufe1820e2018-12-06 17:18:12 -08001253 if (divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001254 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
Lingfeng Yang5fe99012017-01-18 09:17:09 -08001255 bufLen = effectiveStride * (actual_count ? (actual_count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001256 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001257 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001258 if (hasClientArrays) {
1259 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001260 if (state.isInt) {
1261 this->glVertexAttribIPointerOffsetAEMU(this, i, state.size, state.type, stride, offset + firstIndex);
1262 } else {
1263 this->glVertexAttribPointerOffset(this, i, state.size, state.type, state.normalized, stride, offset + firstIndex);
1264 }
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001265 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001266 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001267 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=%p", buf);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -08001268 if (buf) {
1269 ALOGE("Out of bounds vertex attribute info: "
1270 "clientArray? %d attribute %d vbo %u allocedBufferSize %u bufferDataSpecified? %d wantedStart %u wantedEnd %u",
Lingfeng Yangddfb4452018-09-24 17:26:07 -07001271 hasClientArrays, i, bufferObject, (unsigned int)buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -08001272 }
1273 m_glDisableVertexAttribArray_enc(this, i);
Yahan Zhou5507c042016-06-01 17:24:28 -07001274 }
keunyoungb85b2752013-03-08 12:28:03 -08001275 }
1276 } else {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001277 if (hasClientArrays) {
1278 this->m_glDisableVertexAttribArray_enc(this, i);
1279 }
keunyoungb85b2752013-03-08 12:28:03 -08001280 }
1281 }
Lingfeng Yang398162b2016-05-26 14:18:33 -07001282
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001283 if (hasClientArrays && lastBoundVbo != m_state->currentArrayVbo()) {
Lingfeng Yang398162b2016-05-26 14:18:33 -07001284 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
1285 }
keunyoungb85b2752013-03-08 12:28:03 -08001286}
1287
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001288void GL2Encoder::flushDrawCall() {
Lingfeng Yang1ebb33c2017-01-19 08:04:48 -08001289 // This used to be every other draw call, but
1290 // now that we are using real GPU buffers on host,
1291 // set this to every 200 draw calls
1292 // (tuned on z840 linux NVIDIA Quadro K2200)
1293 if (m_drawCallFlushCount % 200 == 0) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001294 m_stream->flush();
1295 }
1296 m_drawCallFlushCount++;
1297}
1298
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001299static bool isValidDrawMode(GLenum mode)
1300{
1301 bool retval = false;
1302 switch (mode) {
1303 case GL_POINTS:
1304 case GL_LINE_STRIP:
1305 case GL_LINE_LOOP:
1306 case GL_LINES:
1307 case GL_TRIANGLE_STRIP:
1308 case GL_TRIANGLE_FAN:
1309 case GL_TRIANGLES:
1310 retval = true;
1311 }
1312 return retval;
1313}
1314
keunyoungb85b2752013-03-08 12:28:03 -08001315void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
1316{
1317 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001318 assert(ctx->m_state != NULL);
1319 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1320 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhoud6217a52016-02-10 16:10:46 -08001321
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001322 bool has_client_vertex_arrays = false;
1323 bool has_indirect_arrays = false;
1324 ctx->getVBOUsage(&has_client_vertex_arrays,
1325 &has_indirect_arrays);
1326
1327 if (has_client_vertex_arrays ||
1328 (!has_client_vertex_arrays &&
1329 !has_indirect_arrays)) {
1330 ctx->sendVertexAttributes(first, count, true);
1331 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
1332 } else {
1333 ctx->sendVertexAttributes(0, count, false);
1334 ctx->m_glDrawArrays_enc(ctx, mode, first, count);
1335 }
keunyoungb85b2752013-03-08 12:28:03 -08001336}
1337
1338
1339void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
1340{
1341
1342 GL2Encoder *ctx = (GL2Encoder *)self;
1343 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001344 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1345 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -07001346 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 -08001347 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001348
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001349 bool has_client_vertex_arrays = false;
keunyoungb85b2752013-03-08 12:28:03 -08001350 bool has_indirect_arrays = false;
1351 int nLocations = ctx->m_state->nLocations();
Yahan Zhou5507c042016-06-01 17:24:28 -07001352 GLintptr offset = 0;
keunyoungb85b2752013-03-08 12:28:03 -08001353
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001354 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
keunyoungb85b2752013-03-08 12:28:03 -08001355
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001356 if (!has_client_vertex_arrays && !has_indirect_arrays) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001357 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -07001358 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
1359 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001360 }
1361
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001362 BufferData* buf = NULL;
Yahan Zhou5507c042016-06-01 17:24:28 -07001363 int minIndex = 0, maxIndex = 0;
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001364
1365 // For validation/immediate index array purposes,
1366 // we need the min/max vertex index of the index array.
1367 // If the VBO != 0, this may not be the first time we have
1368 // used this particular index buffer. getBufferIndexRange
1369 // can more quickly get min/max vertex index by
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001370 // caching previous results.
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001371 if (ctx->m_state->currentIndexVbo() != 0) {
1372 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1373 offset = (GLintptr)indices;
1374 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
1375 ctx->getBufferIndexRange(buf,
1376 indices,
1377 type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001378 (size_t)count,
1379 (size_t)offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001380 &minIndex, &maxIndex);
1381 } else {
1382 // In this case, the |indices| field holds a real
1383 // array, so calculate the indices now. They will
1384 // also be needed to know how much data to
1385 // transfer to host.
1386 ctx->calcIndexRange(indices,
1387 type,
1388 count,
1389 &minIndex,
1390 &maxIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -07001391 }
1392
Lingfeng Yang26e629a2018-10-13 20:00:12 -07001393 if (count == 0) return;
1394
keunyoungb85b2752013-03-08 12:28:03 -08001395 bool adjustIndices = true;
1396 if (ctx->m_state->currentIndexVbo() != 0) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001397 if (!has_client_vertex_arrays) {
1398 ctx->sendVertexAttributes(0, maxIndex + 1, false);
keunyoungb85b2752013-03-08 12:28:03 -08001399 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -07001400 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001401 ctx->flushDrawCall();
keunyoungb85b2752013-03-08 12:28:03 -08001402 adjustIndices = false;
1403 } else {
1404 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1405 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001406 }
1407 }
1408 if (adjustIndices) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001409 void *adjustedIndices =
1410 ctx->recenterIndices(indices,
1411 type,
1412 count,
1413 minIndex);
keunyoungb85b2752013-03-08 12:28:03 -08001414
keunyoungb85b2752013-03-08 12:28:03 -08001415 if (has_indirect_arrays || 1) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001416 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
keunyoungb85b2752013-03-08 12:28:03 -08001417 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
1418 count * glSizeof(type));
1419 // XXX - OPTIMIZATION (see the other else branch) should be implemented
1420 if(!has_indirect_arrays) {
1421 //ALOGD("unoptimized drawelements !!!\n");
1422 }
1423 } else {
1424 // we are all direct arrays and immidate mode index array -
1425 // rebuild the arrays and the index array;
1426 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
1427 }
1428 }
1429}
1430
Lingfeng Yang09545912019-01-30 09:22:38 -08001431void GL2Encoder::s_glDrawArraysNullAEMU(void *self, GLenum mode, GLint first, GLsizei count)
1432{
1433 GL2Encoder *ctx = (GL2Encoder *)self;
1434 assert(ctx->m_state != NULL);
1435 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1436 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
1437
1438 bool has_client_vertex_arrays = false;
1439 bool has_indirect_arrays = false;
1440 ctx->getVBOUsage(&has_client_vertex_arrays,
1441 &has_indirect_arrays);
1442
1443 if (has_client_vertex_arrays ||
1444 (!has_client_vertex_arrays &&
1445 !has_indirect_arrays)) {
1446 ctx->sendVertexAttributes(first, count, true);
1447 ctx->m_glDrawArraysNullAEMU_enc(ctx, mode, 0, count);
1448 } else {
1449 ctx->sendVertexAttributes(0, count, false);
1450 ctx->m_glDrawArraysNullAEMU_enc(ctx, mode, first, count);
1451 }
1452}
1453
1454void GL2Encoder::s_glDrawElementsNullAEMU(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
1455{
1456
1457 GL2Encoder *ctx = (GL2Encoder *)self;
1458 assert(ctx->m_state != NULL);
1459 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1460 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
1461 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
1462 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
1463
1464 bool has_client_vertex_arrays = false;
1465 bool has_indirect_arrays = false;
1466 int nLocations = ctx->m_state->nLocations();
1467 GLintptr offset = 0;
1468
1469 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
1470
1471 if (!has_client_vertex_arrays && !has_indirect_arrays) {
1472 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
1473 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
1474 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
1475 }
1476
1477 BufferData* buf = NULL;
1478 int minIndex = 0, maxIndex = 0;
1479
1480 // For validation/immediate index array purposes,
1481 // we need the min/max vertex index of the index array.
1482 // If the VBO != 0, this may not be the first time we have
1483 // used this particular index buffer. getBufferIndexRange
1484 // can more quickly get min/max vertex index by
1485 // caching previous results.
1486 if (ctx->m_state->currentIndexVbo() != 0) {
1487 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1488 offset = (GLintptr)indices;
1489 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
1490 ctx->getBufferIndexRange(buf,
1491 indices,
1492 type,
1493 (size_t)count,
1494 (size_t)offset,
1495 &minIndex, &maxIndex);
1496 } else {
1497 // In this case, the |indices| field holds a real
1498 // array, so calculate the indices now. They will
1499 // also be needed to know how much data to
1500 // transfer to host.
1501 ctx->calcIndexRange(indices,
1502 type,
1503 count,
1504 &minIndex,
1505 &maxIndex);
1506 }
1507
1508 if (count == 0) return;
1509
1510 bool adjustIndices = true;
1511 if (ctx->m_state->currentIndexVbo() != 0) {
1512 if (!has_client_vertex_arrays) {
1513 ctx->sendVertexAttributes(0, maxIndex + 1, false);
1514 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
1515 ctx->glDrawElementsOffsetNullAEMU(ctx, mode, count, type, offset);
1516 ctx->flushDrawCall();
1517 adjustIndices = false;
1518 } else {
1519 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1520 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
1521 }
1522 }
1523 if (adjustIndices) {
1524 void *adjustedIndices =
1525 ctx->recenterIndices(indices,
1526 type,
1527 count,
1528 minIndex);
1529
1530 if (has_indirect_arrays || 1) {
1531 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
1532 ctx->glDrawElementsDataNullAEMU(ctx, mode, count, type, adjustedIndices,
1533 count * glSizeof(type));
1534 // XXX - OPTIMIZATION (see the other else branch) should be implemented
1535 if(!has_indirect_arrays) {
1536 //ALOGD("unoptimized drawelements !!!\n");
1537 }
1538 } else {
1539 // we are all direct arrays and immidate mode index array -
1540 // rebuild the arrays and the index array;
1541 ALOGE("glDrawElementsNullAEMU: direct index & direct buffer data - will be implemented in later versions;\n");
1542 }
1543 }
1544}
keunyoungb85b2752013-03-08 12:28:03 -08001545
1546GLint * GL2Encoder::getCompressedTextureFormats()
1547{
1548 if (m_compressedTextureFormats == NULL) {
1549 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
1550 &m_num_compressedTextureFormats);
1551 if (m_num_compressedTextureFormats > 0) {
1552 // get number of texture formats;
1553 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
1554 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
1555 }
1556 }
1557 return m_compressedTextureFormats;
1558}
1559
1560// Replace uses of samplerExternalOES with sampler2D, recording the names of
1561// modified shaders in data. Also remove
1562// #extension GL_OES_EGL_image_external : require
1563// statements.
1564//
1565// This implementation assumes the input has already been pre-processed. If not,
1566// a few cases will be mishandled:
1567//
1568// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
1569// the following code:
1570// #if 1
1571// uniform sampler2D mySampler;
1572// #else
1573// uniform samplerExternalOES mySampler;
1574// #endif
1575//
1576// 2. Comments that look like sampler declarations will be incorrectly modified
1577// and recorded:
1578// // samplerExternalOES hahaFooledYou
1579//
1580// 3. However, GLSL ES does not have a concatentation operator, so things like
1581// this (valid in C) are invalid and not a problem:
1582// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
1583// SAMPLER(ExternalOES, mySampler);
1584//
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001585
1586static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
1587static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
1588static const char STR_DEFINE[] = "#define";
1589
1590static std::vector<std::string> getSamplerExternalAliases(char* str) {
1591 std::vector<std::string> res;
1592
1593 res.push_back(STR_SAMPLER_EXTERNAL_OES);
1594
1595 // -- capture #define x samplerExternalOES
1596 char* c = str;
1597 while ((c = strstr(c, STR_DEFINE))) {
1598 // Don't push it if samplerExternalOES is not even there.
1599 char* samplerExternalOES_next = strstr(c, STR_SAMPLER_EXTERNAL_OES);
1600 if (!samplerExternalOES_next) break;
1601
1602 bool prevIdent = false;
1603
1604 std::vector<std::string> idents;
1605 std::string curr;
1606
1607 while (*c != '\0') {
1608
1609 if (isspace(*c)) {
1610 if (prevIdent) {
1611 idents.push_back(curr);
1612 curr = "";
1613 }
1614 }
1615
1616 if (*c == '\n' || idents.size() == 3) break;
1617
1618 if (isalpha(*c) || *c == '_') {
1619 curr.push_back(*c);
1620 prevIdent = true;
1621 }
1622
1623 ++c;
1624 }
1625
1626 if (idents.size() != 3) continue;
1627
1628 const std::string& defineLhs = idents[1];
1629 const std::string& defineRhs = idents[2];
1630
1631 if (defineRhs == STR_SAMPLER_EXTERNAL_OES) {
1632 res.push_back(defineLhs);
1633 }
1634
1635 if (*c == '\0') break;
1636 }
1637
1638 return res;
1639}
1640
1641static bool replaceExternalSamplerUniformDefinition(char* str, const std::string& samplerExternalType, ShaderData* data) {
1642 // -- replace "samplerExternalOES" with "sampler2D" and record name
1643 char* c = str;
1644 while ((c = strstr(c, samplerExternalType.c_str()))) {
1645 // Make sure "samplerExternalOES" isn't a substring of a larger token
1646 if (c == str || !isspace(*(c-1))) {
1647 c++;
1648 continue;
1649 }
1650 char* sampler_start = c;
1651 c += samplerExternalType.size();
1652 if (!isspace(*c) && *c != '\0') {
1653 continue;
1654 }
1655
1656 // capture sampler name
1657 while (isspace(*c) && *c != '\0') {
1658 c++;
1659 }
1660 if (!isalpha(*c) && *c != '_') {
1661 // not an identifier
1662 return false;
1663 }
1664 char* name_start = c;
1665 do {
1666 c++;
1667 } while (isalnum(*c) || *c == '_');
Lingfeng Yang44209df2018-09-21 10:04:17 -07001668
1669 size_t len = (size_t)(c - name_start);
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001670 data->samplerExternalNames.push_back(
Lingfeng Yang44209df2018-09-21 10:04:17 -07001671 std::string(name_start, len));
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001672
1673 // We only need to perform a string replacement for the original
1674 // occurrence of samplerExternalOES if a #define was used.
1675 //
1676 // The important part was to record the name in
1677 // |data->samplerExternalNames|.
1678 if (samplerExternalType == STR_SAMPLER_EXTERNAL_OES) {
1679 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
1680 }
1681 }
1682
1683 return true;
1684}
1685
keunyoungb85b2752013-03-08 12:28:03 -08001686static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
1687{
1688 static const char STR_HASH_EXTENSION[] = "#extension";
1689 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
Lingfeng Yang3546c4d2018-04-10 12:34:30 -07001690 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3[] = "GL_OES_EGL_image_external_essl3";
keunyoungb85b2752013-03-08 12:28:03 -08001691
1692 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
1693 char* c = str;
1694 while ((c = strstr(c, STR_HASH_EXTENSION))) {
1695 char* start = c;
1696 c += sizeof(STR_HASH_EXTENSION)-1;
1697 while (isspace(*c) && *c != '\0') {
1698 c++;
1699 }
Lingfeng Yang3546c4d2018-04-10 12:34:30 -07001700
1701 bool hasBaseImageExternal =
1702 !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
1703 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL) - 1);
1704 bool hasEssl3ImageExternal =
1705 !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3,
1706 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3) - 1);
1707
1708 if (hasBaseImageExternal || hasEssl3ImageExternal)
keunyoungb85b2752013-03-08 12:28:03 -08001709 {
1710 // #extension statements are terminated by end of line
1711 c = start;
1712 while (*c != '\0' && *c != '\r' && *c != '\n') {
1713 *c++ = ' ';
1714 }
1715 }
1716 }
1717
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001718 std::vector<std::string> samplerExternalAliases =
1719 getSamplerExternalAliases(str);
keunyoungb85b2752013-03-08 12:28:03 -08001720
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001721 for (size_t i = 0; i < samplerExternalAliases.size(); i++) {
1722 if (!replaceExternalSamplerUniformDefinition(
1723 str, samplerExternalAliases[i], data))
keunyoungb85b2752013-03-08 12:28:03 -08001724 return false;
keunyoungb85b2752013-03-08 12:28:03 -08001725 }
1726
1727 return true;
1728}
1729
Bo Hu73568cd2015-01-20 16:29:50 -08001730void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
1731{
1732 GL2Encoder* ctx = (GL2Encoder*)self;
1733 // Although it is not supported, need to set proper error code.
1734 SET_ERROR_IF(1, GL_INVALID_ENUM);
1735}
1736
David 'Digit' Turner02fdb692014-10-30 18:07:56 +01001737void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -08001738{
1739 GL2Encoder* ctx = (GL2Encoder*)self;
1740 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001741 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(shader), GL_INVALID_VALUE);
Tina Zhang7a84f652014-12-04 12:37:30 +08001742 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
1743 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001744
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001745 // Track original sources---they may be translated in the backend
1746 std::vector<std::string> orig_sources;
1747 for (int i = 0; i < count; i++) {
1748 orig_sources.push_back(std::string((const char*)(string[i])));
1749 }
1750 shaderData->sources = orig_sources;
1751
keunyoungb85b2752013-03-08 12:28:03 -08001752 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
1753 char *str = new char[len + 1];
1754 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
1755
1756 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
1757 // Perhaps we can borrow Mesa's pre-processor?
1758
1759 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001760 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001761 ctx->setError(GL_OUT_OF_MEMORY);
1762 return;
1763 }
keunyoungb85b2752013-03-08 12:28:03 -08001764 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001765 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001766}
1767
1768void GL2Encoder::s_glFinish(void *self)
1769{
1770 GL2Encoder *ctx = (GL2Encoder *)self;
1771 ctx->glFinishRoundTrip(self);
1772}
1773
1774void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1775{
1776 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -08001777 bool isProgram = ctx->m_shared->isProgram(program);
1778 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
1779 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
1780
keunyoungb85b2752013-03-08 12:28:03 -08001781 ctx->m_glLinkProgram_enc(self, program);
1782
1783 GLint linkStatus = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07001784 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001785 if (!linkStatus) {
keunyoungb85b2752013-03-08 12:28:03 -08001786 return;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001787 }
keunyoungb85b2752013-03-08 12:28:03 -08001788
1789 //get number of active uniforms in the program
1790 GLint numUniforms=0;
1791 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
1792 ctx->m_shared->initProgramData(program,numUniforms);
1793
1794 //get the length of the longest uniform name
1795 GLint maxLength=0;
1796 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
1797
1798 GLint size;
1799 GLenum type;
1800 GLchar *name = new GLchar[maxLength+1];
1801 GLint location;
1802 //for each active uniform, get its size and starting location.
1803 for (GLint i=0 ; i<numUniforms ; ++i)
1804 {
1805 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1806 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1807 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1808 }
1809 ctx->m_shared->setupLocationShiftWAR(program);
1810
1811 delete[] name;
1812}
1813
1814void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1815{
1816 GL2Encoder *ctx = (GL2Encoder*)self;
1817 ctx->m_glDeleteProgram_enc(self, program);
1818
1819 ctx->m_shared->deleteProgramData(program);
1820}
1821
1822void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1823{
1824 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001825 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001826 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001827 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1828 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1829 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1830 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1831}
1832void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1833{
1834 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001835 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001836 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001837 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1838 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1839 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1840 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1841}
1842
1843GLuint GL2Encoder::s_glCreateProgram(void * self)
1844{
1845 GL2Encoder *ctx = (GL2Encoder*)self;
1846 GLuint program = ctx->m_glCreateProgram_enc(self);
1847 if (program!=0)
1848 ctx->m_shared->addProgramData(program);
1849 return program;
1850}
1851
1852GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1853{
1854 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001855 RET_AND_SET_ERROR_IF(!GLESv2Validation::shaderType(ctx, shaderType), GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001856 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1857 if (shader != 0) {
1858 if (!ctx->m_shared->addShaderData(shader)) {
1859 ctx->m_glDeleteShader_enc(self, shader);
1860 return 0;
1861 }
1862 }
1863 return shader;
1864}
1865
bohu56bf82f2014-10-17 15:35:48 -07001866void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1867 GLsizei* count, GLuint* shaders)
1868{
1869 GL2Encoder *ctx = (GL2Encoder*)self;
1870 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1871 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1872}
1873
1874void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1875 GLsizei* length, GLchar* source)
1876{
1877 GL2Encoder *ctx = (GL2Encoder*)self;
1878 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1879 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001880 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
1881 if (shaderData) {
1882 std::string returned;
1883 int curr_len = 0;
1884 for (int i = 0; i < shaderData->sources.size(); i++) {
1885 if (curr_len + shaderData->sources[i].size() < bufsize - 1) {
1886 returned += shaderData->sources[i];
1887 } else {
1888 returned += shaderData->sources[i].substr(0, bufsize - 1 - curr_len);
1889 break;
1890 }
1891 }
1892 memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize);
1893 }
bohu56bf82f2014-10-17 15:35:48 -07001894}
1895
1896void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1897 GLsizei* length, GLchar* infolog)
1898{
1899 GL2Encoder *ctx = (GL2Encoder*)self;
1900 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1901 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1902}
1903
1904void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1905 GLsizei* length, GLchar* infolog)
1906{
1907 GL2Encoder *ctx = (GL2Encoder*)self;
1908 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1909 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1910}
1911
keunyoungb85b2752013-03-08 12:28:03 -08001912void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1913{
1914 GL2Encoder *ctx = (GL2Encoder*)self;
1915 ctx->m_glDeleteShader_enc(self,shader);
1916 ctx->m_shared->unrefShaderData(shader);
1917}
1918
1919void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1920{
1921 GL2Encoder *ctx = (GL2Encoder*)self;
1922 ctx->m_glAttachShader_enc(self, program, shader);
1923 ctx->m_shared->attachShader(program, shader);
1924}
1925
1926void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1927{
1928 GL2Encoder *ctx = (GL2Encoder*)self;
1929 ctx->m_glDetachShader_enc(self, program, shader);
1930 ctx->m_shared->detachShader(program, shader);
1931}
1932
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001933int sArrIndexOfUniformExpr(const char* name, int* err) {
1934 *err = 0;
1935 int arrIndex = 0;
1936 int namelen = strlen(name);
1937 if (name[namelen-1] == ']') {
1938 const char *brace = strrchr(name,'[');
1939 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1940 *err = 1; return 0;
1941 }
1942 }
1943 return arrIndex;
1944}
1945
keunyoungb85b2752013-03-08 12:28:03 -08001946int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1947{
1948 if (!name) return -1;
1949
1950 GL2Encoder *ctx = (GL2Encoder*)self;
1951
1952 // if we need the uniform location WAR
1953 // parse array index from the end of the name string
1954 int arrIndex = 0;
1955 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1956 if (needLocationWAR) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001957 int err;
1958 arrIndex = sArrIndexOfUniformExpr(name, &err);
1959 if (err) return -1;
keunyoungb85b2752013-03-08 12:28:03 -08001960 }
1961
1962 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1963 if (hostLoc >= 0 && needLocationWAR) {
1964 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1965 }
1966 return hostLoc;
1967}
1968
1969bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1970{
1971 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1972 return false;
1973
1974 m_state->setActiveTextureUnit(texUnit);
1975
1976 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1977 if (newTarget != oldTarget) {
1978 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1979 m_state->disableTextureTarget(GL_TEXTURE_2D);
1980 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1981 } else {
1982 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1983 m_state->enableTextureTarget(GL_TEXTURE_2D);
1984 }
1985 m_glActiveTexture_enc(this, texUnit);
1986 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1987 m_state->getBoundTexture(newTarget));
1988 return true;
1989 }
1990
1991 return false;
1992}
1993
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001994void GL2Encoder::updateHostTexture2DBindingsFromProgramData(GLuint program) {
1995 GL2Encoder *ctx = this;
keunyoungb85b2752013-03-08 12:28:03 -08001996 GLClientState* state = ctx->m_state;
1997 GLSharedGroupPtr shared = ctx->m_shared;
1998
keunyoungb85b2752013-03-08 12:28:03 -08001999 GLenum origActiveTexture = state->getActiveTextureUnit();
2000 GLenum hostActiveTexture = origActiveTexture;
2001 GLint samplerIdx = -1;
2002 GLint samplerVal;
2003 GLenum samplerTarget;
2004 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
2005 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
2006 continue;
2007 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002008 samplerTarget))
keunyoungb85b2752013-03-08 12:28:03 -08002009 {
2010 hostActiveTexture = GL_TEXTURE0 + samplerVal;
2011 }
2012 }
2013 state->setActiveTextureUnit(origActiveTexture);
2014 if (hostActiveTexture != origActiveTexture) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002015 ctx->m_glActiveTexture_enc(ctx, origActiveTexture);
keunyoungb85b2752013-03-08 12:28:03 -08002016 }
2017}
2018
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002019void GL2Encoder::s_glUseProgram(void *self, GLuint program)
2020{
2021 GL2Encoder *ctx = (GL2Encoder*)self;
2022 GLSharedGroupPtr shared = ctx->m_shared;
2023
2024 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
2025 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
2026
2027 ctx->m_glUseProgram_enc(self, program);
2028 ctx->m_state->setCurrentProgram(program);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002029 ctx->m_state->setCurrentShaderProgram(program);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002030
2031 ctx->updateHostTexture2DBindingsFromProgramData(program);
2032}
2033
keunyoungb85b2752013-03-08 12:28:03 -08002034void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
2035{
2036 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002037 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002038 ctx->m_glUniform1f_enc(self, hostLoc, x);
2039}
2040
2041void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
2042{
2043 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002044 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002045 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
2046}
2047
2048void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
2049{
2050 GL2Encoder *ctx = (GL2Encoder*)self;
2051 GLClientState* state = ctx->m_state;
2052 GLSharedGroupPtr shared = ctx->m_shared;
2053
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002054 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002055 ctx->m_glUniform1i_enc(self, hostLoc, x);
2056
2057 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002058 if (shared->setSamplerUniform(state->currentShaderProgram(), location, x, &target)) {
keunyoungb85b2752013-03-08 12:28:03 -08002059 GLenum origActiveTexture = state->getActiveTextureUnit();
2060 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
2061 ctx->m_glActiveTexture_enc(self, origActiveTexture);
2062 }
2063 state->setActiveTextureUnit(origActiveTexture);
2064 }
2065}
2066
2067void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
2068{
2069 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002070 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002071 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
2072}
2073
2074void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
2075{
2076 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002077 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002078 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
2079}
2080
2081void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
2082{
2083 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002084 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002085 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
2086}
2087
2088void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
2089{
2090 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002091 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002092 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
2093}
2094
2095void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
2096{
2097 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002098 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002099 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
2100}
2101
2102void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
2103{
2104 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002105 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002106 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
2107}
2108
2109void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
2110{
2111 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002112 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002113 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
2114}
2115
2116void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
2117{
2118 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002119 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002120 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
2121}
2122
2123void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
2124{
2125 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002126 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002127 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
2128}
2129
2130void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
2131{
2132 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002133 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002134 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
2135}
2136
2137void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
2138{
2139 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002140 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002141 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
2142}
2143
2144void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
2145{
2146 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002147 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002148 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
2149}
2150
2151void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
2152{
2153 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002154 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002155 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
2156}
2157
2158void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
2159{
2160 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002161 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002162 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
2163}
2164
2165void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
2166{
2167 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002168 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002169 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
2170}
2171
2172void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
2173{
2174 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002175 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002176 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
2177}
2178
2179void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
2180{
2181 GL2Encoder* ctx = (GL2Encoder*)self;
2182 GLClientState* state = ctx->m_state;
2183 GLenum err;
2184
2185 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
2186
2187 ctx->m_glActiveTexture_enc(ctx, texture);
2188}
2189
2190void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
2191{
2192 GL2Encoder* ctx = (GL2Encoder*)self;
2193 GLClientState* state = ctx->m_state;
2194 GLenum err;
2195 GLboolean firstUse;
2196
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002197 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -08002198 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
2199
2200 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
2201 ctx->m_glBindTexture_enc(ctx, target, texture);
2202 return;
2203 }
2204
2205 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2206
2207 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
2208 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
2209 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
2210 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2211 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
2212 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2213 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
2214 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2215
2216 if (target != priorityTarget) {
2217 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
2218 state->getBoundTexture(GL_TEXTURE_2D));
2219 }
2220 }
2221
2222 if (target == priorityTarget) {
2223 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
2224 }
2225}
2226
2227void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
2228{
2229 GL2Encoder* ctx = (GL2Encoder*)self;
2230 GLClientState* state = ctx->m_state;
2231
2232 state->deleteTextures(n, textures);
2233 ctx->m_glDeleteTextures_enc(ctx, n, textures);
2234}
2235
2236void GL2Encoder::s_glGetTexParameterfv(void* self,
2237 GLenum target, GLenum pname, GLfloat* params)
2238{
2239 GL2Encoder* ctx = (GL2Encoder*)self;
2240 const GLClientState* state = ctx->m_state;
2241
2242 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2243 ctx->override2DTextureTarget(target);
2244 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002245 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002246 } else {
2247 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
2248 }
2249}
2250
2251void GL2Encoder::s_glGetTexParameteriv(void* self,
2252 GLenum target, GLenum pname, GLint* params)
2253{
2254 GL2Encoder* ctx = (GL2Encoder*)self;
2255 const GLClientState* state = ctx->m_state;
2256
2257 switch (pname) {
2258 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
2259 *params = 1;
2260 break;
2261
2262 default:
2263 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2264 ctx->override2DTextureTarget(target);
2265 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002266 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002267 } else {
2268 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
2269 }
2270 break;
2271 }
2272}
2273
2274static bool isValidTextureExternalParam(GLenum pname, GLenum param)
2275{
2276 switch (pname) {
2277 case GL_TEXTURE_MIN_FILTER:
2278 case GL_TEXTURE_MAG_FILTER:
2279 return param == GL_NEAREST || param == GL_LINEAR;
2280
2281 case GL_TEXTURE_WRAP_S:
2282 case GL_TEXTURE_WRAP_T:
2283 return param == GL_CLAMP_TO_EDGE;
2284
2285 default:
2286 return true;
2287 }
2288}
2289
2290void GL2Encoder::s_glTexParameterf(void* self,
2291 GLenum target, GLenum pname, GLfloat param)
2292{
2293 GL2Encoder* ctx = (GL2Encoder*)self;
2294 const GLClientState* state = ctx->m_state;
2295
2296 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2297 !isValidTextureExternalParam(pname, (GLenum)param)),
2298 GL_INVALID_ENUM);
2299
2300 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2301 ctx->override2DTextureTarget(target);
2302 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002303 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002304 } else {
2305 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
2306 }
2307}
2308
2309void GL2Encoder::s_glTexParameterfv(void* self,
2310 GLenum target, GLenum pname, const GLfloat* params)
2311{
2312 GL2Encoder* ctx = (GL2Encoder*)self;
2313 const GLClientState* state = ctx->m_state;
2314
2315 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2316 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2317 GL_INVALID_ENUM);
2318
2319 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2320 ctx->override2DTextureTarget(target);
2321 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002322 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002323 } else {
2324 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
2325 }
2326}
2327
2328void GL2Encoder::s_glTexParameteri(void* self,
2329 GLenum target, GLenum pname, GLint param)
2330{
2331 GL2Encoder* ctx = (GL2Encoder*)self;
2332 const GLClientState* state = ctx->m_state;
2333
2334 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2335 !isValidTextureExternalParam(pname, (GLenum)param)),
2336 GL_INVALID_ENUM);
2337
2338 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2339 ctx->override2DTextureTarget(target);
2340 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002341 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002342 } else {
2343 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
2344 }
2345}
2346
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002347static int ilog2(uint32_t x) {
2348 int p = 0;
2349 while ((1 << p) < x)
2350 p++;
2351 return p;
2352}
2353
bohu26a92982014-11-25 16:50:37 -08002354void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
2355 GLint internalformat, GLsizei width, GLsizei height, GLint border,
2356 GLenum format, GLenum type, const GLvoid* pixels)
2357{
2358 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07002359 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002360
2361 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2362 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2363 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2364 // If unpack buffer is nonzero, verify unmapped state.
2365 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2366
2367 GLint max_texture_size;
2368 GLint max_cube_map_texture_size;
2369 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2370 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2371 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2372 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2373 SET_ERROR_IF((target == GL_TEXTURE_CUBE_MAP) &&
2374 (level > ilog2(max_cube_map_texture_size)), GL_INVALID_VALUE);
2375 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2376 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2377 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2378 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && width > max_cube_map_texture_size, GL_INVALID_VALUE);
2379 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && height > max_cube_map_texture_size, GL_INVALID_VALUE);
2380 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
2381 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2382 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2383 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2384 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 0) >
2385 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2386 GL_INVALID_OPERATION);
2387 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2388 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2389 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2390 glSizeof(type)),
2391 GL_INVALID_OPERATION);
2392 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2393 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2394 ((uintptr_t)pixels % glSizeof(type)),
2395 GL_INVALID_OPERATION);
2396 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
2397
2398 GLenum stateTarget = target;
2399 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2400 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2401 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2402 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2403 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2404 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2405 stateTarget = GL_TEXTURE_CUBE_MAP;
2406
2407 state->setBoundTextureInternalFormat(stateTarget, internalformat);
2408 state->setBoundTextureFormat(stateTarget, format);
2409 state->setBoundTextureType(stateTarget, type);
2410 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2411
bohu26a92982014-11-25 16:50:37 -08002412 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2413 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002414 }
Lingfeng Yang69066602016-04-12 09:29:11 -07002415
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002416 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2417 ctx->glTexImage2DOffsetAEMU(
2418 ctx, target, level, internalformat,
2419 width, height, border,
2420 format, type, (uintptr_t)pixels);
bohu26a92982014-11-25 16:50:37 -08002421 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002422 ctx->m_glTexImage2D_enc(
2423 ctx, target, level, internalformat,
2424 width, height, border,
2425 format, type, pixels);
2426 }
2427
2428 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2429 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08002430 }
2431}
2432
Yahan Zhou2a208292016-06-22 15:36:04 -07002433void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
2434 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
2435 GLenum type, const GLvoid* pixels)
2436{
2437 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002438 GLClientState* state = ctx->m_state;
2439
2440 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2441 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2442 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2443 // If unpack buffer is nonzero, verify unmapped state.
2444 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2445
2446 GLint max_texture_size;
2447 GLint max_cube_map_texture_size;
2448 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2449 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2450 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2451 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2452 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) &&
2453 level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2454 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2455 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2456
2457 GLuint tex = state->getBoundTexture(target);
2458 GLsizei neededWidth = xoffset + width;
2459 GLsizei neededHeight = yoffset + height;
2460 GLsizei neededDepth = 1;
2461
2462 if (tex && !state->queryTexEGLImageBacked(tex)) {
2463 SET_ERROR_IF(
2464 (neededWidth > state->queryTexWidth(level, tex) ||
2465 neededHeight > state->queryTexHeight(level, tex) ||
2466 neededDepth > state->queryTexDepth(level, tex)),
2467 GL_INVALID_VALUE);
2468 }
2469
2470 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2471 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2472 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2473 (state->pboNeededDataSize(width, height, 1, format, type, 0) >
2474 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2475 GL_INVALID_OPERATION);
2476 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2477 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2478 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2479 glSizeof(type)),
2480 GL_INVALID_OPERATION);
2481 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !pixels, GL_INVALID_OPERATION);
Yahan Zhou2a208292016-06-22 15:36:04 -07002482
2483 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2484 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002485 }
2486
2487 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2488 ctx->glTexSubImage2DOffsetAEMU(
2489 ctx, target, level,
2490 xoffset, yoffset, width, height,
2491 format, type, (uintptr_t)pixels);
Yahan Zhou2a208292016-06-22 15:36:04 -07002492 } else {
2493 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
2494 height, format, type, pixels);
2495 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002496
2497 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2498 ctx->restore2DTextureTarget(target);
2499 }
Yahan Zhou2a208292016-06-22 15:36:04 -07002500}
bohu26a92982014-11-25 16:50:37 -08002501
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002502void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
2503 GLenum internalformat, GLint x, GLint y,
2504 GLsizei width, GLsizei height, GLint border)
2505{
2506 GL2Encoder* ctx = (GL2Encoder*)self;
2507 GLClientState* state = ctx->m_state;
2508
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002509 SET_ERROR_IF(ctx->glCheckFramebufferStatus(ctx, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
2510 GL_INVALID_FRAMEBUFFER_OPERATION);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002511 // This is needed to work around underlying OpenGL drivers
2512 // (such as those feeding some some AMD GPUs) that expect
2513 // positive components of cube maps to be defined _before_
2514 // the negative components (otherwise a segfault occurs).
2515 GLenum extraTarget =
2516 state->copyTexImageLuminanceCubeMapAMDWorkaround
2517 (target, level, internalformat);
2518
2519 if (extraTarget) {
2520 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
2521 x, y, width, height, border);
2522 }
2523
2524 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
2525 x, y, width, height, border);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002526
2527 state->setBoundTextureInternalFormat(target, internalformat);
2528 state->setBoundTextureDims(target, level, width, height, 1);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002529}
2530
keunyoungb85b2752013-03-08 12:28:03 -08002531void GL2Encoder::s_glTexParameteriv(void* self,
2532 GLenum target, GLenum pname, const GLint* params)
2533{
2534 GL2Encoder* ctx = (GL2Encoder*)self;
2535 const GLClientState* state = ctx->m_state;
2536
2537 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2538 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2539 GL_INVALID_ENUM);
2540
2541 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2542 ctx->override2DTextureTarget(target);
2543 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002544 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002545 } else {
2546 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
2547 }
2548}
2549
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002550bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
2551 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
2552 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2553}
2554
keunyoungb85b2752013-03-08 12:28:03 -08002555void GL2Encoder::override2DTextureTarget(GLenum target)
2556{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002557 if (texture2DNeedsOverride(target)) {
2558 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2559 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08002560 }
2561}
2562
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002563void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08002564{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002565 if (texture2DNeedsOverride(target)) {
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002566 GLuint priorityEnabledBoundTexture =
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002567 m_state->getBoundTexture(
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002568 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D));
2569 GLuint texture2DBoundTexture =
2570 m_state->getBoundTexture(GL_TEXTURE_2D);
2571 if (!priorityEnabledBoundTexture) {
2572 m_glBindTexture_enc(this, GL_TEXTURE_2D, texture2DBoundTexture);
2573 } else {
2574 m_glBindTexture_enc(this, GL_TEXTURE_2D, priorityEnabledBoundTexture);
2575 }
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002576 }
keunyoungb85b2752013-03-08 12:28:03 -08002577}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002578
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002579void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2580 m_state->setBoundEGLImage(target, eglImage);
2581}
2582
2583
2584GLuint GL2Encoder::boundBuffer(GLenum target) const {
2585 return m_state->getBuffer(target);
2586}
2587
2588BufferData* GL2Encoder::getBufferData(GLenum target) const {
2589 GLuint bufferId = m_state->getBuffer(target);
2590 if (!bufferId) return NULL;
2591 return m_shared->getBufferData(bufferId);
2592}
2593
2594BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2595 if (!bufferId) return NULL;
2596 return m_shared->getBufferData(bufferId);
2597}
2598
2599bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2600 return m_shared->getBufferData(buffer)->m_mapped;
2601}
2602
2603bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2604 BufferData* buf = getBufferData(target);
2605 if (!buf) return false;
2606 return buf->m_mapped;
2607}
2608
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002609void GL2Encoder::s_glGenRenderbuffers(void* self,
2610 GLsizei n, GLuint* renderbuffers) {
2611 GL2Encoder* ctx = (GL2Encoder*)self;
2612 GLClientState* state = ctx->m_state;
2613
2614 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2615
2616 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2617 state->addRenderbuffers(n, renderbuffers);
2618}
2619
2620void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2621 GLsizei n, const GLuint* renderbuffers) {
2622 GL2Encoder* ctx = (GL2Encoder*)self;
2623 GLClientState* state = ctx->m_state;
2624
2625 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2626
2627 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002628
2629 // Nope, lets just leak those for now.
2630 // The spec has an *amazingly* convoluted set of conditions for when
2631 // render buffers are actually deleted:
2632 // 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.
2633 //
2634 // 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***
2635 //
2636 // So, just detach this one from the bound FBO, and ignore the rest.
2637 for (int i = 0; i < n; i++) {
2638 state->detachRbo(renderbuffers[i]);
2639 }
2640 // state->removeRenderbuffers(n, renderbuffers);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002641}
2642
2643void GL2Encoder::s_glBindRenderbuffer(void* self,
2644 GLenum target, GLuint renderbuffer) {
2645 GL2Encoder* ctx = (GL2Encoder*)self;
2646 GLClientState* state = ctx->m_state;
2647
2648 SET_ERROR_IF((target != GL_RENDERBUFFER),
2649 GL_INVALID_ENUM);
2650
2651 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2652 state->bindRenderbuffer(target, renderbuffer);
2653}
2654
Lingfeng Yang69066602016-04-12 09:29:11 -07002655void GL2Encoder::s_glRenderbufferStorage(void* self,
2656 GLenum target, GLenum internalformat,
2657 GLsizei width, GLsizei height) {
2658 GL2Encoder* ctx = (GL2Encoder*) self;
2659 GLClientState* state = ctx->m_state;
2660
2661 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002662 SET_ERROR_IF(
2663 !GLESv2Validation::rboFormat(ctx, internalformat),
2664 GL_INVALID_ENUM);
Lingfeng Yang69066602016-04-12 09:29:11 -07002665
2666 state->setBoundRenderbufferFormat(internalformat);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002667 state->setBoundRenderbufferSamples(0);
2668
Lingfeng Yang69066602016-04-12 09:29:11 -07002669 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
2670 width, height);
2671}
2672
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002673void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
2674 GLenum target, GLenum attachment,
2675 GLenum renderbuffertarget, GLuint renderbuffer) {
2676 GL2Encoder* ctx = (GL2Encoder*)self;
2677 GLClientState* state = ctx->m_state;
2678
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002679 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2680 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2681 state->attachRbo(target, attachment, renderbuffer);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002682
2683 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
2684}
2685
2686void GL2Encoder::s_glGenFramebuffers(void* self,
2687 GLsizei n, GLuint* framebuffers) {
2688 GL2Encoder* ctx = (GL2Encoder*)self;
2689 GLClientState* state = ctx->m_state;
2690
2691 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2692
2693 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2694 state->addFramebuffers(n, framebuffers);
2695}
2696
2697void GL2Encoder::s_glDeleteFramebuffers(void* self,
2698 GLsizei n, const GLuint* framebuffers) {
2699 GL2Encoder* ctx = (GL2Encoder*)self;
2700 GLClientState* state = ctx->m_state;
2701
2702 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2703
2704 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2705 state->removeFramebuffers(n, framebuffers);
2706}
2707
2708void GL2Encoder::s_glBindFramebuffer(void* self,
2709 GLenum target, GLuint framebuffer) {
2710 GL2Encoder* ctx = (GL2Encoder*)self;
2711 GLClientState* state = ctx->m_state;
2712
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002713 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002714
2715 state->bindFramebuffer(target, framebuffer);
2716
2717 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
2718}
2719
2720void GL2Encoder::s_glFramebufferTexture2D(void* self,
2721 GLenum target, GLenum attachment,
2722 GLenum textarget, GLuint texture, GLint level) {
2723 GL2Encoder* ctx = (GL2Encoder*)self;
2724 GLClientState* state = ctx->m_state;
2725
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002726 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2727 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2728 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002729
2730 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
2731}
2732
2733void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2734 GLenum target, GLenum attachment,
2735 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2736 GL2Encoder* ctx = (GL2Encoder*)self;
2737 GLClientState* state = ctx->m_state;
2738
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002739 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002740
2741 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2742}
2743
2744void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2745 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2746 GL2Encoder* ctx = (GL2Encoder*)self;
2747 const GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002748 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2749 SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2750 pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE &&
2751 !state->attachmentHasObject(target, attachment),
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002752 GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002753 SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL ||
2754 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE ||
2755 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) &&
2756 (!state->attachmentHasObject(target, attachment) ||
2757 state->getBoundFramebufferAttachmentType(target, attachment) !=
2758 FBO_ATTACHMENT_TEXTURE),
2759 !state->attachmentHasObject(target, attachment) ?
2760 GL_INVALID_OPERATION : GL_INVALID_ENUM);
2761 SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2762 pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2763 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
2764 state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
2765 GL_INVALID_OPERATION);
2766 SET_ERROR_IF(state->boundFramebuffer(target) &&
2767 (attachment == GL_BACK ||
2768 attachment == GL_FRONT),
2769 GL_INVALID_OPERATION);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002770 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
2771}
Lingfeng Yang69066602016-04-12 09:29:11 -07002772
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002773bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state,
Lingfeng Yang69066602016-04-12 09:29:11 -07002774 GLenum attachment) const {
2775 FboFormatInfo fbo_format_info;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002776 state->getBoundFramebufferFormat(target, attachment, &fbo_format_info);
Lingfeng Yang69066602016-04-12 09:29:11 -07002777
2778 bool res;
2779 switch (fbo_format_info.type) {
2780 case FBO_ATTACHMENT_RENDERBUFFER:
2781 switch (fbo_format_info.rb_format) {
2782 case GL_R16F:
2783 case GL_RG16F:
Lingfeng Yang69066602016-04-12 09:29:11 -07002784 case GL_RGBA16F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002785 case GL_R32F:
2786 case GL_RG32F:
2787 case GL_RGBA32F:
2788 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002789 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002790 break;
2791 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002792 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang69066602016-04-12 09:29:11 -07002793 break;
2794 case GL_STENCIL_INDEX8:
2795 if (attachment == GL_STENCIL_ATTACHMENT) {
2796 res = true;
2797 } else {
2798 res = false;
2799 }
2800 break;
2801 default:
2802 res = true;
2803 }
2804 break;
2805 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002806 switch (fbo_format_info.tex_internalformat) {
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002807 case GL_R16F:
2808 case GL_RG16F:
2809 case GL_RGBA16F:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002810 case GL_R32F:
2811 case GL_RG32F:
2812 case GL_RGBA32F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002813 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002814 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002815 break;
2816 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002817 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002818 break;
2819 case GL_RED:
2820 case GL_RG:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002821 case GL_SRGB8:
2822 case GL_RGB32UI:
2823 case GL_RGB16UI:
2824 case GL_RGB8UI:
2825 case GL_RGB32I:
2826 case GL_RGB16I:
2827 case GL_RGB8I:
2828 case GL_R8_SNORM:
2829 case GL_RG8_SNORM:
2830 case GL_RGB8_SNORM:
2831 case GL_RGBA8_SNORM:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002832 res = false;
2833 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07002834 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002835 case GL_RGB:
2836 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07002837 switch (fbo_format_info.tex_type) {
2838 case GL_FLOAT:
2839 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002840 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002841 case GL_UNSIGNED_INT_2_10_10_10_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07002842 res = false;
2843 break;
2844 default:
2845 res = true;
2846 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002847 break;
2848 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07002849 res = true;
2850 }
2851 break;
2852 case FBO_ATTACHMENT_NONE:
2853 res = true;
2854 break;
2855 default:
2856 res = true;
2857 }
2858 return res;
2859}
2860
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002861bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const {
2862 bool res = true;
2863
2864 for (int i = 0; i < state->getMaxColorAttachments(); i++) {
2865 res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i));
2866 }
2867
2868 res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT);
2869 res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT);
2870
2871 return res;
2872}
2873
Lingfeng Yang69066602016-04-12 09:29:11 -07002874GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
2875 GL2Encoder* ctx = (GL2Encoder*)self;
2876 GLClientState* state = ctx->m_state;
2877
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002878 bool fboCompleteByCodec =
2879 ctx->checkFramebufferCompleteness(target, state);
2880
2881 if (!fboCompleteByCodec) {
2882 state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
Lingfeng Yang69066602016-04-12 09:29:11 -07002883 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2884 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002885 // double check with underlying opengl to avoid craziness.
Lingfeng Yang69066602016-04-12 09:29:11 -07002886 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002887 state->setCheckFramebufferStatus(target, host_checkstatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002888 if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE;
Lingfeng Yang69066602016-04-12 09:29:11 -07002889 return host_checkstatus;
2890 }
2891}
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002892
2893void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2894 GL2Encoder* ctx = (GL2Encoder*)self;
2895 GLClientState* state = ctx->m_state;
2896 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2897
2898 ctx->m_glGenVertexArrays_enc(self, n, arrays);
2899 for (int i = 0; i < n; i++) {
2900 ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2901 }
2902 state->addVertexArrayObjects(n, arrays);
2903}
2904
2905void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2906 GL2Encoder* ctx = (GL2Encoder*)self;
2907 GLClientState* state = ctx->m_state;
2908 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2909
2910 ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2911 for (int i = 0; i < n; i++) {
2912 ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2913 }
2914 state->removeVertexArrayObjects(n, arrays);
2915}
2916
2917void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2918 ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2919 GL2Encoder* ctx = (GL2Encoder*)self;
2920 GLClientState* state = ctx->m_state;
2921 SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2922 ctx->m_glBindVertexArray_enc(self, array);
2923 state->setVertexArrayObject(array);
2924}
2925
Lingfeng Yangfb3d2bb2017-09-07 15:02:04 -07002926void* GL2Encoder::s_glMapBufferOES(void* self, GLenum target, GLenum access) {
2927 GL2Encoder* ctx = (GL2Encoder*)self;
2928
2929 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2930
2931 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2932
2933 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2934
2935 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2936 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2937
2938 return ctx->glMapBufferRange(ctx, target, 0, buf->m_size, access);
2939}
2940
2941GLboolean GL2Encoder::s_glUnmapBufferOES(void* self, GLenum target) {
2942 GL2Encoder* ctx = (GL2Encoder*)self;
2943
2944 return ctx->glUnmapBuffer(ctx, target);
2945}
2946
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07002947void* GL2Encoder::s_glMapBufferRangeAEMUImpl(GL2Encoder* ctx, GLenum target,
2948 GLintptr offset, GLsizeiptr length,
2949 GLbitfield access, BufferData* buf) {
2950 char* bits = (char*)buf->m_fixedBuffer.ptr() + offset;
2951
2952 ctx->glMapBufferRangeAEMU(
2953 ctx, target,
2954 offset, length,
2955 access,
2956 bits);
2957
2958 return bits;
2959}
2960
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002961void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2962 GL2Encoder* ctx = (GL2Encoder*)self;
2963 GLClientState* state = ctx->m_state;
2964
2965 // begin validation (lots)
2966
2967 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2968
2969 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2970
2971 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2972
2973 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2974 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2975
2976 GLsizeiptr bufferDataSize = buf->m_size;
2977
2978 RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2979 RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2980 RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2981 RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2982
2983 RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2984 RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2985 RET_AND_SET_ERROR_IF(
2986 (access & GL_MAP_READ_BIT) &&
2987 ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2988 (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2989 (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2990 (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2991
2992 // end validation; actually do stuff now
2993
2994 buf->m_mapped = true;
2995 buf->m_mappedAccess = access;
2996 buf->m_mappedOffset = offset;
2997 buf->m_mappedLength = length;
2998
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07002999 if (ctx->hasExtension("ANDROID_EMU_dma_v2")) {
3000 if (buf->dma_buffer.get().size < length) {
3001 goldfish_dma_context region;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003002
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07003003 const int PAGE_BITS = 12;
3004 GLsizeiptr aligned_length = (length + (1 << PAGE_BITS) - 1) & ~((1 << PAGE_BITS) - 1);
3005
3006 if (goldfish_dma_create_region(aligned_length, &region)) {
3007 buf->dma_buffer.reset(NULL);
3008 return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
3009 }
3010
3011 if (!goldfish_dma_map(&region)) {
3012 buf->dma_buffer.reset(NULL);
3013 return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
3014 }
3015
3016 buf->m_guest_paddr = goldfish_dma_guest_paddr(&region);
3017 buf->dma_buffer.reset(&region);
3018 }
3019
3020 ctx->glMapBufferRangeDMA(
3021 ctx, target,
3022 offset, length,
3023 access,
3024 buf->m_guest_paddr);
3025
3026 return reinterpret_cast<void*>(buf->dma_buffer.get().mapped_addr);
Lingfeng Yang47d8fff2019-01-23 07:37:12 -08003027 } else if (ctx->hasExtension("ANDROID_EMU_direct_mem_v2")) {
Roman Kiryanovdaecd142018-11-14 14:56:27 -08003028 GoldfishAddressSpaceBlock new_shared_block;
3029
3030 if (new_shared_block.allocate(&ctx->m_goldfish_address_block_provider, length)) {
3031 uint64_t gpu_addr =
3032 ctx->glMapBufferRangeDirect(ctx,
3033 target,
3034 offset,
3035 length,
3036 access,
3037 new_shared_block.physAddr());
3038 if (gpu_addr) {
3039 void *user_ptr = new_shared_block.mmap(gpu_addr);
3040 if (user_ptr) {
3041 buf->shared_block.replace(&new_shared_block);
3042 return user_ptr;
3043 } else {
3044 GLboolean host_res = GL_TRUE;
3045
3046 ctx->glUnmapBufferDirect(
3047 ctx, target,
3048 offset,
3049 length,
3050 access,
3051 new_shared_block.physAddr(),
3052 gpu_addr,
3053 &host_res);
3054
3055 return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
3056 }
3057 } else {
3058 return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
3059 }
3060 } else {
3061 return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
3062 }
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07003063 } else {
3064 return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
3065 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003066}
3067
3068GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
3069 GL2Encoder* ctx = (GL2Encoder*)self;
3070 GLClientState* state = ctx->m_state;
3071
3072 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
3073
3074 GLuint boundBuffer = ctx->m_state->getBuffer(target);
3075
3076 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
3077
3078 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
3079 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
3080 RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
3081
Lingfeng Yang423129e2017-01-18 09:23:12 -08003082 if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
3083 // invalide index range cache here
3084 if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) {
3085 buf->m_indexRangeCache.invalidateRange(0, buf->m_size);
3086 } else {
3087 buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength);
3088 }
3089 }
3090
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003091 GLboolean host_res = GL_TRUE;
3092
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07003093 if (buf->dma_buffer.get().mapped_addr) {
3094 memcpy(static_cast<char*>(buf->m_fixedBuffer.ptr()) + buf->m_mappedOffset,
3095 reinterpret_cast<void*>(buf->dma_buffer.get().mapped_addr),
3096 buf->m_mappedLength);
3097
3098 ctx->glUnmapBufferDMA(
Roman Kiryanovdaecd142018-11-14 14:56:27 -08003099 ctx, target,
3100 buf->m_mappedOffset,
3101 buf->m_mappedLength,
3102 buf->m_mappedAccess,
3103 goldfish_dma_guest_paddr(&buf->dma_buffer.get()),
3104 &host_res);
3105 } else if (buf->shared_block.guestPtr()) {
3106 GoldfishAddressSpaceBlock *shared_block = &buf->shared_block;
3107
3108 memcpy(static_cast<char*>(buf->m_fixedBuffer.ptr()) + buf->m_mappedOffset,
3109 shared_block->guestPtr(),
3110 buf->m_mappedLength);
3111
3112 ctx->glUnmapBufferDirect(
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07003113 ctx, target,
3114 buf->m_mappedOffset,
3115 buf->m_mappedLength,
3116 buf->m_mappedAccess,
Roman Kiryanovdaecd142018-11-14 14:56:27 -08003117 shared_block->physAddr(),
3118 shared_block->hostAddr(),
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07003119 &host_res);
Roman Kiryanovdaecd142018-11-14 14:56:27 -08003120
3121 shared_block->replace(NULL);
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07003122 } else {
3123 ctx->glUnmapBufferAEMU(
3124 ctx, target,
3125 buf->m_mappedOffset,
3126 buf->m_mappedLength,
3127 buf->m_mappedAccess,
3128 (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
3129 &host_res);
3130 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003131
3132 buf->m_mapped = false;
3133 buf->m_mappedAccess = 0;
3134 buf->m_mappedOffset = 0;
3135 buf->m_mappedLength = 0;
3136
3137 return host_res;
3138}
3139
3140void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
3141 GL2Encoder* ctx = (GL2Encoder*)self;
3142 GLClientState* state = ctx->m_state;
3143
3144 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3145
3146 GLuint boundBuffer = ctx->m_state->getBuffer(target);
3147 SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
3148
3149 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
3150 SET_ERROR_IF(!buf, GL_INVALID_VALUE);
3151 SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
3152 SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
3153
3154 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
3155 SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
3156 SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
3157
3158 GLintptr totalOffset = buf->m_mappedOffset + offset;
Lingfeng Yang423129e2017-01-18 09:23:12 -08003159
3160 buf->m_indexRangeCache.invalidateRange(totalOffset, length);
3161
Roman Kiryanovdaecd142018-11-14 14:56:27 -08003162 if (buf->shared_block.guestPtr()) {
3163 ctx->glFlushMappedBufferRangeDirect(
3164 ctx, target,
3165 totalOffset,
3166 length,
3167 buf->m_mappedAccess);
3168 } else {
3169 ctx->glFlushMappedBufferRangeAEMU(
3170 ctx, target,
3171 totalOffset,
3172 length,
3173 buf->m_mappedAccess,
3174 (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
3175 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003176}
3177
3178void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
3179 GL2Encoder* ctx = (GL2Encoder*)self;
3180 GLClientState* state = ctx->m_state;
3181
3182 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3183 // Filter compressed formats support.
3184 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3185 // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
3186 GLint max_texture_size;
3187 GLint max_cube_map_texture_size;
3188 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3189 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
3190 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3191 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3192 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
3193 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
3194 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
3195 SET_ERROR_IF(border, GL_INVALID_VALUE);
3196 // If unpack buffer is nonzero, verify unmapped state.
3197 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3198 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
3199 // If unpack buffer is nonzero, verify buffer data fits.
3200 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3201 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3202 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3203 GL_INVALID_OPERATION);
3204 // TODO: Fix:
3205 // If |imageSize| is inconsistent with compressed dimensions.
3206 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
3207
3208 GLenum stateTarget = target;
3209 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
3210 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
3211 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
3212 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
3213 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
3214 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
3215 stateTarget = GL_TEXTURE_CUBE_MAP;
3216 state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
3217 state->setBoundTextureDims(stateTarget, level, width, height, 1);
3218
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003219 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
3220 ctx->override2DTextureTarget(target);
3221 }
3222
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003223 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3224 ctx->glCompressedTexImage2DOffsetAEMU(
3225 ctx, target, level, internalformat,
3226 width, height, border,
3227 imageSize, (uintptr_t)data);
3228 } else {
3229 ctx->m_glCompressedTexImage2D_enc(
3230 ctx, target, level, internalformat,
3231 width, height, border,
3232 imageSize, data);
3233 }
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003234
3235 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
3236 ctx->restore2DTextureTarget(target);
3237 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003238}
3239
3240void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
3241 GL2Encoder* ctx = (GL2Encoder*)self;
3242 GLClientState* state = ctx->m_state;
3243
3244 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3245 // If unpack buffer is nonzero, verify unmapped state.
3246 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3247 GLint max_texture_size;
3248 GLint max_cube_map_texture_size;
3249 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3250 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
3251 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3252 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3253 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
3254 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
3255 // If unpack buffer is nonzero, verify buffer data fits.
3256 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3257 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3258 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3259 GL_INVALID_OPERATION);
3260 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
3261
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003262 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
3263 ctx->override2DTextureTarget(target);
3264 }
3265
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003266 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3267 ctx->glCompressedTexSubImage2DOffsetAEMU(
3268 ctx, target, level,
3269 xoffset, yoffset,
3270 width, height, format,
3271 imageSize, (uintptr_t)data);
3272 } else {
3273 ctx->m_glCompressedTexSubImage2D_enc(
3274 ctx, target, level,
3275 xoffset, yoffset,
3276 width, height, format,
3277 imageSize, data);
3278 }
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003279
3280 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
3281 ctx->restore2DTextureTarget(target);
3282 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003283}
3284
3285void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
3286 GL2Encoder* ctx = (GL2Encoder*)self;
3287 GLClientState* state = ctx->m_state;
3288
3289 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3290
3291 // Only works with certain targets
3292 SET_ERROR_IF(
3293 !(target == GL_ATOMIC_COUNTER_BUFFER ||
3294 target == GL_SHADER_STORAGE_BUFFER ||
3295 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
3296 target == GL_UNIFORM_BUFFER),
3297 GL_INVALID_ENUM);
3298
3299 // Can't exceed range
3300 SET_ERROR_IF(index < 0 ||
3301 index >= state->getMaxIndexedBufferBindings(target),
3302 GL_INVALID_VALUE);
3303 SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
3304 SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
3305 target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
3306 (size % 4 || offset % 4),
3307 GL_INVALID_VALUE);
3308
3309 GLint ssbo_offset_align, ubo_offset_align;
3310 ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
3311 ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
3312 SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
3313 offset % ssbo_offset_align,
3314 GL_INVALID_VALUE);
3315 SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
3316 offset % ubo_offset_align,
3317 GL_INVALID_VALUE);
3318
3319 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003320 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003321 state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0);
3322 ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size);
3323}
3324
3325void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
3326 GL2Encoder* ctx = (GL2Encoder*)self;
3327 GLClientState* state = ctx->m_state;
3328
3329 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3330
3331 // Only works with certain targets
3332 SET_ERROR_IF(
3333 !(target == GL_ATOMIC_COUNTER_BUFFER ||
3334 target == GL_SHADER_STORAGE_BUFFER ||
3335 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
3336 target == GL_UNIFORM_BUFFER),
3337 GL_INVALID_ENUM);
3338 // Can't exceed range
3339 SET_ERROR_IF(index < 0 ||
3340 index >= state->getMaxIndexedBufferBindings(target),
3341 GL_INVALID_VALUE);
3342
3343 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003344 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003345 BufferData* buf = ctx->getBufferDataById(buffer);
3346 state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0);
3347 ctx->m_glBindBufferBase_enc(self, target, index, buffer);
3348}
3349
3350void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
3351 GL2Encoder* ctx = (GL2Encoder*)self;
3352 GLClientState* state = ctx->m_state;
3353
3354 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
3355 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
3356 SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
3357 readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
3358 readtarget == GL_DRAW_INDIRECT_BUFFER ||
3359 readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
3360 SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
3361 writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
3362 writetarget == GL_DRAW_INDIRECT_BUFFER ||
3363 writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
3364 SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
3365 SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
3366 SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
3367 SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
3368 SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
3369 SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
3370 SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
3371 SET_ERROR_IF(
3372 ctx->getBufferData(readtarget) &&
3373 (readoffset + size > ctx->getBufferData(readtarget)->m_size),
3374 GL_INVALID_VALUE);
3375 SET_ERROR_IF(
3376 ctx->getBufferData(writetarget) &&
3377 (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
3378 GL_INVALID_VALUE);
3379 SET_ERROR_IF(readtarget == writetarget &&
3380 !((writeoffset >= readoffset + size) ||
3381 (readoffset >= writeoffset + size)),
3382 GL_INVALID_VALUE);
3383
3384 ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
3385}
3386
3387void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
3388 GL2Encoder* ctx = (GL2Encoder*)self;
3389
3390 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3391 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003392 target != GL_ARRAY_BUFFER &&
3393 target != GL_ELEMENT_ARRAY_BUFFER &&
3394 target != GL_COPY_READ_BUFFER &&
3395 target != GL_COPY_WRITE_BUFFER &&
3396 target != GL_PIXEL_PACK_BUFFER &&
3397 target != GL_PIXEL_UNPACK_BUFFER &&
3398 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
3399 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003400 GL_INVALID_ENUM);
3401 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
3402 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003403 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
3404 pname != GL_BUFFER_MAPPED &&
3405 pname != GL_BUFFER_SIZE &&
3406 pname != GL_BUFFER_USAGE &&
3407 pname != GL_BUFFER_MAP_LENGTH &&
3408 pname != GL_BUFFER_MAP_OFFSET,
3409 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003410
3411 if (!params) return;
3412
3413 BufferData* buf = ctx->getBufferData(target);
3414
3415 switch (pname) {
3416 case GL_BUFFER_ACCESS_FLAGS:
3417 *params = buf ? buf->m_mappedAccess : 0;
3418 break;
3419 case GL_BUFFER_MAPPED:
3420 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3421 break;
3422 case GL_BUFFER_SIZE:
3423 *params = buf ? buf->m_size : 0;
3424 break;
3425 case GL_BUFFER_USAGE:
3426 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3427 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003428 case GL_BUFFER_MAP_LENGTH:
3429 *params = buf ? buf->m_mappedLength : 0;
3430 break;
3431 case GL_BUFFER_MAP_OFFSET:
3432 *params = buf ? buf->m_mappedOffset : 0;
3433 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003434 default:
3435 break;
3436 }
3437}
3438
3439void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
3440 GL2Encoder* ctx = (GL2Encoder*)self;
3441
3442 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3443 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003444 target != GL_ARRAY_BUFFER &&
3445 target != GL_ELEMENT_ARRAY_BUFFER &&
3446 target != GL_COPY_READ_BUFFER &&
3447 target != GL_COPY_WRITE_BUFFER &&
3448 target != GL_PIXEL_PACK_BUFFER &&
3449 target != GL_PIXEL_UNPACK_BUFFER &&
3450 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
3451 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003452 GL_INVALID_ENUM);
3453 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
3454 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003455 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
3456 pname != GL_BUFFER_MAPPED &&
3457 pname != GL_BUFFER_SIZE &&
3458 pname != GL_BUFFER_USAGE &&
3459 pname != GL_BUFFER_MAP_LENGTH &&
3460 pname != GL_BUFFER_MAP_OFFSET,
3461 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003462
3463 if (!params) return;
3464
3465 BufferData* buf = ctx->getBufferData(target);
3466
3467 switch (pname) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003468 case GL_BUFFER_ACCESS_FLAGS:
3469 *params = buf ? buf->m_mappedAccess : 0;
3470 break;
3471 case GL_BUFFER_MAPPED:
3472 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3473 break;
3474 case GL_BUFFER_SIZE:
3475 *params = buf ? buf->m_size : 0;
3476 break;
3477 case GL_BUFFER_USAGE:
3478 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3479 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003480 case GL_BUFFER_MAP_LENGTH:
3481 *params = buf ? buf->m_mappedLength : 0;
3482 break;
3483 case GL_BUFFER_MAP_OFFSET:
3484 *params = buf ? buf->m_mappedOffset : 0;
3485 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003486 default:
3487 break;
3488 }
3489}
3490
3491void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
3492 GL2Encoder* ctx = (GL2Encoder*)self;
3493 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3494 SET_ERROR_IF(
3495 target == GL_ATOMIC_COUNTER_BUFFER ||
3496 target == GL_DISPATCH_INDIRECT_BUFFER ||
3497 target == GL_DRAW_INDIRECT_BUFFER ||
3498 target == GL_SHADER_STORAGE_BUFFER,
3499 GL_INVALID_ENUM);
3500 SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
3501 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
3502 if (!params) return;
3503
3504 BufferData* buf = ctx->getBufferData(target);
3505
3506 if (!buf || !buf->m_mapped) { *params = NULL; return; }
3507
3508 *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
3509}
3510
3511static const char* const kNameDelimiter = ";";
3512
3513static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
3514
3515#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
3516
3517 std::string packed;
3518 // validate the array of char[]'s
3519 const char* currName;
3520 for (GLsizei i = 0; i < count; i++) {
3521 currName = names[i];
3522 VALIDATE(!currName, GL_INVALID_OPERATION);
3523 // check if has reasonable size
3524 size_t len = strlen(currName);
3525 VALIDATE(!len, GL_INVALID_OPERATION);
3526 // check for our delimiter, which if present
3527 // in the name, means an invalid name anyway.
3528 VALIDATE(strstr(currName, kNameDelimiter),
3529 GL_INVALID_OPERATION);
3530 packed += currName;
3531 packed += ";";
3532 }
3533
3534 *err_out = GL_NO_ERROR;
3535 return packed;
3536}
3537
3538void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
3539 GL2Encoder* ctx = (GL2Encoder*)self;
3540
3541 if (!uniformCount) return;
3542
3543 GLint err = GL_NO_ERROR;
3544 std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
3545 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3546
3547 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
3548 std::vector<int> arrIndices;
3549 for (size_t i = 0; i < uniformCount; i++) {
3550 int err;
3551 arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
3552 if (err) {
3553 ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
3554 return;
3555 }
3556 }
3557
3558 ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
3559
3560 for (int i = 0; i < uniformCount; i++) {
3561 if (uniformIndices[i] >= 0 && needLocationWAR) {
3562 uniformIndices[i] =
3563 ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
3564 }
3565 }
3566}
3567
3568void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
3569 GL2Encoder *ctx = (GL2Encoder*)self;
3570 GLClientState* state = ctx->m_state;
3571 GLSharedGroupPtr shared = ctx->m_shared;
3572
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003573 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003574 ctx->m_glUniform1ui_enc(self, hostLoc, v0);
3575
3576 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003577 if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003578 GLenum origActiveTexture = state->getActiveTextureUnit();
3579 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
3580 ctx->m_glActiveTexture_enc(self, origActiveTexture);
3581 }
3582 state->setActiveTextureUnit(origActiveTexture);
3583 }
3584}
3585
3586void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) {
3587 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003588 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003589 ctx->m_glUniform2ui_enc(self, hostLoc, v0, v1);
3590}
3591
3592void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) {
3593 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003594 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003595 ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2);
3596}
3597
3598void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) {
3599 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003600 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003601 ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3);
3602}
3603
3604void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3605 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003606 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003607 ctx->m_glUniform1uiv_enc(self, hostLoc, count, value);
3608}
3609
3610void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3611 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003612 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003613 ctx->m_glUniform2uiv_enc(self, hostLoc, count, value);
3614}
3615
3616void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3617 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003618 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003619 ctx->m_glUniform3uiv_enc(self, hostLoc, count, value);
3620}
3621
3622void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3623 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003624 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003625 ctx->m_glUniform4uiv_enc(self, hostLoc, count, value);
3626}
3627
3628void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3629 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003630 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003631 ctx->m_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value);
3632}
3633
3634void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3635 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003636 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003637 ctx->m_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value);
3638}
3639
3640void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3641 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003642 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003643 ctx->m_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value);
3644}
3645
3646void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3647 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003648 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003649 ctx->m_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value);
3650}
3651
3652void GL2Encoder::s_glUniformMatrix3x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3653 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003654 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003655 ctx->m_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value);
3656}
3657
3658void GL2Encoder::s_glUniformMatrix4x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3659 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003660 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003661 ctx->m_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value);
3662}
3663
3664void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3665 GL2Encoder *ctx = (GL2Encoder*)self;
3666 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3667 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3668 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3669 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3670 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3671 ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3672}
3673
3674void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3675 GL2Encoder* ctx = (GL2Encoder*)self;
3676 GLClientState* state = ctx->m_state;
3677
3678 // refresh client state's # active uniforms in this block
3679 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3680 // TODO if worth it: cache uniform count and other params,
3681 // invalidate on program relinking.
3682 GLint numActiveUniforms;
3683 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3684 program, uniformBlockIndex,
3685 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3686 &numActiveUniforms);
3687 ctx->m_state->setNumActiveUniformsInUniformBlock(
3688 program, uniformBlockIndex, numActiveUniforms);
3689 }
3690
3691 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3692 program, uniformBlockIndex,
3693 pname, params);
3694}
3695
3696void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3697 GL2Encoder *ctx = (GL2Encoder *)self;
3698 assert(ctx->m_state);
3699 GLint maxIndex;
3700 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3701 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3702
3703 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3704 ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3705 }
3706}
3707
3708void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3709 GL2Encoder *ctx = (GL2Encoder *)self;
3710 assert(ctx->m_state);
3711 GLint maxIndex;
3712 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3713 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3714
3715 if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3716 ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3717 }
3718}
3719
3720void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3721 GL2Encoder *ctx = (GL2Encoder *)self;
3722 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003723 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003724 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
3725 SET_ERROR_IF(
3726 !(type == GL_BYTE ||
3727 type == GL_UNSIGNED_BYTE ||
3728 type == GL_SHORT ||
3729 type == GL_UNSIGNED_SHORT ||
3730 type == GL_INT ||
3731 type == GL_UNSIGNED_INT),
3732 GL_INVALID_ENUM);
3733 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
3734
3735 ctx->m_state->setVertexAttribBinding(index, index);
3736 ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true);
3737 GLsizei effectiveStride = stride;
3738 if (stride == 0) {
3739 effectiveStride = glSizeof(type) * size;
3740 }
3741 ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride);
3742
3743 if (ctx->m_state->currentArrayVbo() != 0) {
3744 ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer);
3745 } else {
3746 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION);
3747 // wait for client-array handler
3748 }
3749}
3750
3751void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) {
3752 GL2Encoder *ctx = (GL2Encoder *)self;
3753 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003754 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003755 ctx->m_state->setVertexAttribBinding(index, index);
3756 ctx->m_state->setVertexBindingDivisor(index, divisor);
3757 ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor);
3758}
3759
3760void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3761 GLenum target, GLsizei samples, GLenum internalformat,
3762 GLsizei width, GLsizei height) {
3763 GL2Encoder *ctx = (GL2Encoder *)self;
3764 GLClientState* state = ctx->m_state;
3765
3766 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3767 SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3768
3769 GLint max_samples;
3770 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3771 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3772
3773 state->setBoundRenderbufferFormat(internalformat);
3774 state->setBoundRenderbufferSamples(samples);
3775 ctx->m_glRenderbufferStorageMultisample_enc(
3776 self, target, samples, internalformat, width, height);
3777}
3778
3779void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3780 GL2Encoder* ctx = (GL2Encoder*)self;
3781 SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3782 SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3783 for (int i = 0; i < n; i++) {
3784 SET_ERROR_IF(
3785 bufs[i] != GL_NONE &&
3786 bufs[i] != GL_BACK &&
3787 glUtilsColorAttachmentIndex(bufs[i]) == -1,
3788 GL_INVALID_ENUM);
3789 SET_ERROR_IF(
3790 !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3791 glUtilsColorAttachmentIndex(bufs[i]) != -1,
3792 GL_INVALID_OPERATION);
3793 SET_ERROR_IF(
3794 ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3795 ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3796 glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3797 (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3798 bufs[i] != GL_NONE)),
3799 GL_INVALID_OPERATION);
3800 }
3801
3802 ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3803}
3804
3805void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3806 GL2Encoder* ctx = (GL2Encoder*)self;
3807
3808 SET_ERROR_IF(
3809 glUtilsColorAttachmentIndex(src) != -1 &&
3810 (glUtilsColorAttachmentIndex(src) >=
3811 ctx->m_state->getMaxColorAttachments()),
3812 GL_INVALID_OPERATION);
3813 SET_ERROR_IF(
3814 src != GL_NONE &&
3815 src != GL_BACK &&
3816 src > GL_COLOR_ATTACHMENT0 &&
3817 src < GL_DEPTH_ATTACHMENT &&
3818 (src - GL_COLOR_ATTACHMENT0) >
3819 ctx->m_state->getMaxColorAttachments(),
3820 GL_INVALID_OPERATION);
3821 SET_ERROR_IF(
3822 src != GL_NONE &&
3823 src != GL_BACK &&
3824 glUtilsColorAttachmentIndex(src) == -1,
3825 GL_INVALID_ENUM);
3826 SET_ERROR_IF(
3827 !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3828 src != GL_NONE &&
3829 src != GL_BACK,
3830 GL_INVALID_OPERATION);
3831 SET_ERROR_IF(
3832 ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3833 src != GL_NONE &&
3834 glUtilsColorAttachmentIndex(src) == -1,
3835 GL_INVALID_OPERATION);
3836
3837 ctx->m_glReadBuffer_enc(ctx, src);
3838}
3839
3840void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3841 GL2Encoder* ctx = (GL2Encoder*)self;
3842 GLClientState* state = ctx->m_state;
3843
3844 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3845 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3846 GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3847 SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3848 lastBoundTarget != GL_TEXTURE_3D,
3849 GL_INVALID_OPERATION);
3850 state->attachTextureObject(target, attachment, texture);
3851
3852 GLint max3DTextureSize;
3853 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3854 SET_ERROR_IF(
3855 layer >= max3DTextureSize,
3856 GL_INVALID_VALUE);
3857
3858 ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3859}
3860
3861void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3862 GL2Encoder* ctx = (GL2Encoder*)self;
3863 GLClientState* state = ctx->m_state;
3864
3865 SET_ERROR_IF(
3866 target != GL_TEXTURE_2D &&
3867 target != GL_TEXTURE_CUBE_MAP,
3868 GL_INVALID_ENUM);
3869 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3870 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3871 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3872 SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3873 GL_INVALID_OPERATION);
3874 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3875
3876 state->setBoundTextureInternalFormat(target, internalformat);
3877 state->setBoundTextureDims(target, -1, width, height, 1);
3878 state->setBoundTextureImmutableFormat(target);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003879
3880 if (target == GL_TEXTURE_2D) {
3881 ctx->override2DTextureTarget(target);
3882 }
3883
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003884 ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003885
3886 if (target == GL_TEXTURE_2D) {
3887 ctx->restore2DTextureTarget(target);
3888 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003889}
3890
3891void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3892 GL2Encoder* ctx = (GL2Encoder*)self;
3893
3894 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3895
3896 GLint maxCount = 0;
3897 ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3898
3899 SET_ERROR_IF(
3900 bufferMode == GL_SEPARATE_ATTRIBS &&
3901 maxCount < count,
3902 GL_INVALID_VALUE);
3903 SET_ERROR_IF(
3904 bufferMode != GL_INTERLEAVED_ATTRIBS &&
3905 bufferMode != GL_SEPARATE_ATTRIBS,
3906 GL_INVALID_ENUM);
3907
3908 if (!count) return;
3909
3910 GLint err = GL_NO_ERROR;
3911 std::string packed = packVarNames(count, varyings, &err);
3912 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3913
3914 ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3915}
3916
3917void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3918 GL2Encoder* ctx = (GL2Encoder*)self;
3919 GLClientState* state = ctx->m_state;
3920 ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3921 state->setTransformFeedbackActiveUnpaused(true);
3922}
3923
3924void GL2Encoder::s_glEndTransformFeedback(void* self) {
3925 GL2Encoder* ctx = (GL2Encoder*)self;
3926 GLClientState* state = ctx->m_state;
3927 ctx->m_glEndTransformFeedback_enc(ctx);
3928 state->setTransformFeedbackActiveUnpaused(false);
3929}
3930
3931void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3932 GL2Encoder* ctx = (GL2Encoder*)self;
3933 GLClientState* state = ctx->m_state;
3934 ctx->m_glPauseTransformFeedback_enc(ctx);
3935 state->setTransformFeedbackActiveUnpaused(false);
3936}
3937
3938void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3939 GL2Encoder* ctx = (GL2Encoder*)self;
3940 GLClientState* state = ctx->m_state;
3941 ctx->m_glResumeTransformFeedback_enc(ctx);
3942 state->setTransformFeedbackActiveUnpaused(true);
3943}
3944
3945void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3946 GLsizei width, GLsizei height, GLsizei depth,
3947 GLint border, GLenum format, GLenum type, const GLvoid* data) {
3948 GL2Encoder* ctx = (GL2Encoder*)self;
3949 GLClientState* state = ctx->m_state;
3950
3951 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3952 target != GL_TEXTURE_2D_ARRAY,
3953 GL_INVALID_ENUM);
3954 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3955 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3956
3957 // If unpack buffer is nonzero, verify unmapped state.
3958 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3959
3960 GLint max_texture_size;
3961 GLint max_3d_texture_size;
3962 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3963 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3964 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3965 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3966 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3967
3968 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3969 SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3970 SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3971 SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3972 SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3973 SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3974 SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3975 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3976 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3977 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3978 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3979 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3980 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3981 GL_INVALID_OPERATION);
3982 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3983 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3984 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3985 glSizeof(type)),
3986 GL_INVALID_OPERATION);
3987 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3988
3989 state->setBoundTextureInternalFormat(target, internalFormat);
3990 state->setBoundTextureFormat(target, format);
3991 state->setBoundTextureType(target, type);
3992 state->setBoundTextureDims(target, level, width, height, depth);
3993
3994 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3995 ctx->glTexImage3DOffsetAEMU(
3996 ctx, target, level, internalFormat,
3997 width, height, depth,
3998 border, format, type, (uintptr_t)data);
3999 } else {
4000 ctx->m_glTexImage3D_enc(ctx,
4001 target, level, internalFormat,
4002 width, height, depth,
4003 border, format, type, data);
4004 }
4005}
4006
4007void 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) {
4008 GL2Encoder* ctx = (GL2Encoder*)self;
4009 GLClientState* state = ctx->m_state;
4010
4011 SET_ERROR_IF(target != GL_TEXTURE_3D &&
4012 target != GL_TEXTURE_2D_ARRAY,
4013 GL_INVALID_ENUM);
4014 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
4015 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
4016 // If unpack buffer is nonzero, verify unmapped state.
4017 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
4018 GLint max_texture_size;
4019 GLint max_3d_texture_size;
4020 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
4021 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
4022 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
4023 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
4024 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
4025 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
4026 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
4027 GLuint tex = state->getBoundTexture(target);
4028 GLsizei neededWidth = xoffset + width;
4029 GLsizei neededHeight = yoffset + height;
4030 GLsizei neededDepth = zoffset + depth;
4031
4032 SET_ERROR_IF(tex &&
4033 (neededWidth > state->queryTexWidth(level, tex) ||
4034 neededHeight > state->queryTexHeight(level, tex) ||
4035 neededDepth > state->queryTexDepth(level, tex)),
4036 GL_INVALID_VALUE);
4037 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
4038 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
4039 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
4040 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
4041 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
4042 GL_INVALID_OPERATION);
4043 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
4044 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
4045 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
4046 glSizeof(type)),
4047 GL_INVALID_OPERATION);
4048 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
4049 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
4050
4051 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
4052 ctx->glTexSubImage3DOffsetAEMU(ctx,
4053 target, level,
4054 xoffset, yoffset, zoffset,
4055 width, height, depth,
4056 format, type, (uintptr_t)data);
4057 } else {
4058 ctx->m_glTexSubImage3D_enc(ctx,
4059 target, level,
4060 xoffset, yoffset, zoffset,
4061 width, height, depth,
4062 format, type, data);
4063 }
4064}
4065
4066void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
4067 GL2Encoder* ctx = (GL2Encoder*)self;
4068 GLClientState* state = ctx->m_state;
4069
4070 // Filter compressed formats support.
4071 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
4072 // If unpack buffer is nonzero, verify unmapped state.
4073 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
4074 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
4075 SET_ERROR_IF(border, GL_INVALID_VALUE);
4076 // If unpack buffer is nonzero, verify buffer data fits.
4077 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
4078 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
4079 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
4080 GL_INVALID_OPERATION);
4081 // TODO: Fix:
4082 // If |imageSize| is too small for compressed dimensions.
4083 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
4084 state->setBoundTextureInternalFormat(target, (GLint)internalformat);
4085 state->setBoundTextureDims(target, level, width, height, depth);
4086
4087 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
4088 ctx->glCompressedTexImage3DOffsetAEMU(
4089 ctx, target, level, internalformat,
4090 width, height, depth, border,
4091 imageSize, (uintptr_t)data);
4092 } else {
4093 ctx->m_glCompressedTexImage3D_enc(
4094 ctx, target, level, internalformat,
4095 width, height, depth, border,
4096 imageSize, data);
4097 }
4098}
4099
4100void 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) {
4101 GL2Encoder* ctx = (GL2Encoder*)self;
4102 GLClientState* state = ctx->m_state;
4103
4104 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
4105 // If unpack buffer is nonzero, verify unmapped state.
4106 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
4107 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
4108 // If unpack buffer is nonzero, verify buffer data fits.
4109 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
4110 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
4111 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
4112 GL_INVALID_OPERATION);
4113 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
4114
4115 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
4116 ctx->glCompressedTexSubImage3DOffsetAEMU(
4117 ctx, target, level,
4118 xoffset, yoffset, zoffset,
4119 width, height, depth,
4120 format, imageSize, (uintptr_t)data);
4121 } else {
4122 ctx->m_glCompressedTexSubImage3D_enc(
4123 ctx, target, level,
4124 xoffset, yoffset, zoffset,
4125 width, height, depth,
4126 format, imageSize, data);
4127
4128 }
4129}
4130
4131void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
4132 GL2Encoder* ctx = (GL2Encoder*)self;
4133 GLClientState* state = ctx->m_state;
4134 SET_ERROR_IF(target != GL_TEXTURE_3D &&
4135 target != GL_TEXTURE_2D_ARRAY,
4136 GL_INVALID_ENUM);
4137 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
4138 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
4139 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
4140 SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
4141 GL_INVALID_OPERATION);
4142 SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
4143 GL_INVALID_OPERATION);
4144 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
4145
4146 state->setBoundTextureInternalFormat(target, internalformat);
4147 state->setBoundTextureDims(target, -1, width, height, depth);
4148 state->setBoundTextureImmutableFormat(target);
4149 ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
4150 state->setBoundTextureImmutableFormat(target);
4151}
4152
4153void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
4154 GL2Encoder *ctx = (GL2Encoder *)self;
4155 assert(ctx->m_state != NULL);
4156 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
4157 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
4158
4159 bool has_client_vertex_arrays = false;
4160 bool has_indirect_arrays = false;
4161 ctx->getVBOUsage(&has_client_vertex_arrays,
4162 &has_indirect_arrays);
4163
4164 if (has_client_vertex_arrays ||
4165 (!has_client_vertex_arrays &&
4166 !has_indirect_arrays)) {
4167 ctx->sendVertexAttributes(first, count, true, primcount);
4168 ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
4169 } else {
4170 ctx->sendVertexAttributes(0, count, false, primcount);
4171 ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
4172 }
4173 ctx->m_stream->flush();
4174}
4175
4176void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
4177{
4178
4179 GL2Encoder *ctx = (GL2Encoder *)self;
4180 assert(ctx->m_state != NULL);
4181 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
4182 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
4183 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
4184 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
4185
4186 bool has_client_vertex_arrays = false;
4187 bool has_indirect_arrays = false;
4188 int nLocations = ctx->m_state->nLocations();
4189 GLintptr offset = 0;
4190
4191 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
4192
4193 if (!has_client_vertex_arrays && !has_indirect_arrays) {
4194 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
4195 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
4196 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
4197 }
4198
4199 BufferData* buf = NULL;
4200 int minIndex = 0, maxIndex = 0;
4201
4202 // For validation/immediate index array purposes,
4203 // we need the min/max vertex index of the index array.
4204 // If the VBO != 0, this may not be the first time we have
4205 // used this particular index buffer. getBufferIndexRange
4206 // can more quickly get min/max vertex index by
4207 // caching previous results.
4208 if (ctx->m_state->currentIndexVbo() != 0) {
4209 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
4210 offset = (GLintptr)indices;
4211 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
4212 ctx->getBufferIndexRange(buf,
4213 indices,
4214 type,
4215 (size_t)count,
4216 (size_t)offset,
4217 &minIndex, &maxIndex);
4218 } else {
4219 // In this case, the |indices| field holds a real
4220 // array, so calculate the indices now. They will
4221 // also be needed to know how much data to
4222 // transfer to host.
4223 ctx->calcIndexRange(indices,
4224 type,
4225 count,
4226 &minIndex,
4227 &maxIndex);
4228 }
4229
Lingfeng Yang26e629a2018-10-13 20:00:12 -07004230 if (count == 0) return;
4231
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004232 bool adjustIndices = true;
4233 if (ctx->m_state->currentIndexVbo() != 0) {
4234 if (!has_client_vertex_arrays) {
4235 ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
4236 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
4237 ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
4238 ctx->flushDrawCall();
4239 adjustIndices = false;
4240 } else {
4241 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
4242 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
4243 }
4244 }
4245 if (adjustIndices) {
4246 void *adjustedIndices =
4247 ctx->recenterIndices(indices,
4248 type,
4249 count,
4250 minIndex);
4251
4252 if (has_indirect_arrays || 1) {
4253 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
4254 ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
4255 ctx->m_stream->flush();
4256 // XXX - OPTIMIZATION (see the other else branch) should be implemented
4257 if(!has_indirect_arrays) {
4258 //ALOGD("unoptimized drawelements !!!\n");
4259 }
4260 } else {
4261 // we are all direct arrays and immidate mode index array -
4262 // rebuild the arrays and the index array;
4263 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
4264 }
4265 }
4266}
4267
4268void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
4269{
4270
4271 GL2Encoder *ctx = (GL2Encoder *)self;
4272 assert(ctx->m_state != NULL);
4273 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
4274 SET_ERROR_IF(end < start, GL_INVALID_VALUE);
4275 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
4276 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
4277 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
4278
4279 bool has_client_vertex_arrays = false;
4280 bool has_indirect_arrays = false;
4281 int nLocations = ctx->m_state->nLocations();
4282 GLintptr offset = 0;
4283
4284 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
4285
4286 if (!has_client_vertex_arrays && !has_indirect_arrays) {
4287 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
4288 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
4289 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
4290 }
4291
4292 BufferData* buf = NULL;
4293 int minIndex = 0, maxIndex = 0;
4294
4295 // For validation/immediate index array purposes,
4296 // we need the min/max vertex index of the index array.
4297 // If the VBO != 0, this may not be the first time we have
4298 // used this particular index buffer. getBufferIndexRange
4299 // can more quickly get min/max vertex index by
4300 // caching previous results.
4301 if (ctx->m_state->currentIndexVbo() != 0) {
4302 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
4303 offset = (GLintptr)indices;
4304 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
4305 ctx->getBufferIndexRange(buf,
4306 indices,
4307 type,
4308 (size_t)count,
4309 (size_t)offset,
4310 &minIndex, &maxIndex);
4311 } else {
4312 // In this case, the |indices| field holds a real
4313 // array, so calculate the indices now. They will
4314 // also be needed to know how much data to
4315 // transfer to host.
4316 ctx->calcIndexRange(indices,
4317 type,
4318 count,
4319 &minIndex,
4320 &maxIndex);
4321 }
4322
Lingfeng Yang26e629a2018-10-13 20:00:12 -07004323 if (count == 0) return;
4324
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004325 bool adjustIndices = true;
4326 if (ctx->m_state->currentIndexVbo() != 0) {
4327 if (!has_client_vertex_arrays) {
4328 ctx->sendVertexAttributes(0, maxIndex + 1, false);
4329 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
4330 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
4331 ctx->flushDrawCall();
4332 adjustIndices = false;
4333 } else {
4334 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
4335 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
4336 }
4337 }
4338 if (adjustIndices) {
4339 void *adjustedIndices =
4340 ctx->recenterIndices(indices,
4341 type,
4342 count,
4343 minIndex);
4344
4345 if (has_indirect_arrays || 1) {
4346 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
4347 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
4348 ctx->m_stream->flush();
4349 // XXX - OPTIMIZATION (see the other else branch) should be implemented
4350 if(!has_indirect_arrays) {
4351 //ALOGD("unoptimized drawelements !!!\n");
4352 }
4353 } else {
4354 // we are all direct arrays and immidate mode index array -
4355 // rebuild the arrays and the index array;
4356 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
4357 }
4358 }
4359}
4360
4361// struct GLStringKey {
4362// GLenum name;
4363// GLuint index;
4364// };
4365//
4366// struct GLStringKeyCompare {
4367// bool operator() (const GLStringKey& a,
4368// const GLStringKey& b) const {
4369// if (a.name != b.name) return a.name < b.name;
4370// if (a.index != b.index) return a.index < b.index;
4371// return false;
4372// }
4373// };
4374//
4375// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
4376//
4377// static GLStringStore sGLStringStore;
4378// bool sGLStringStoreInitialized = false;
4379
4380const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
4381 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004382 const GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004383
4384 RET_AND_SET_ERROR_IF(
4385 name != GL_VENDOR &&
4386 name != GL_RENDERER &&
4387 name != GL_VERSION &&
4388 name != GL_EXTENSIONS,
4389 GL_INVALID_ENUM,
4390 retval);
4391
4392 RET_AND_SET_ERROR_IF(
Lingfeng Yang44209df2018-09-21 10:04:17 -07004393 (name == GL_VENDOR ||
4394 name == GL_RENDERER ||
4395 name == GL_VERSION) &&
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004396 index != 0,
4397 GL_INVALID_VALUE,
4398 retval);
4399
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004400 RET_AND_SET_ERROR_IF(
4401 name == GL_EXTENSIONS &&
4402 index >= ctx->m_currExtensionsArray.size(),
4403 GL_INVALID_VALUE,
4404 retval);
4405
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004406 switch (name) {
4407 case GL_VENDOR:
4408 retval = gVendorString;
4409 break;
4410 case GL_RENDERER:
4411 retval = gRendererString;
4412 break;
4413 case GL_VERSION:
4414 retval = gVersionString;
4415 break;
4416 case GL_EXTENSIONS:
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004417 retval = (const GLubyte*)(ctx->m_currExtensionsArray[index].c_str());
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004418 break;
4419 }
4420
4421 return retval;
4422}
4423
4424void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
4425 GL2Encoder *ctx = (GL2Encoder *)self;
4426
4427 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
4428
4429 GLint linkStatus = 0;
4430 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
4431 GLint properLength = 0;
4432 ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
4433
4434 SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
4435 SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
4436
4437 ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
4438}
4439
4440void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
4441 GL2Encoder *ctx = (GL2Encoder *)self;
4442
4443 SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
4444 SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
4445 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
4446 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
4447 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
4448 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
4449 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
4450 ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
4451 GL_INVALID_OPERATION);
4452 /*
4453GL_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.
4454
4455GL_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.
4456
4457GL_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.
4458
4459GL_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.
4460*/
4461
4462 FboFormatInfo fbo_format_info;
4463 ctx->m_state->getBoundFramebufferFormat(
4464 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
4465 SET_ERROR_IF(
4466 fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4467 !GLESv2Validation::readPixelsFboFormatMatch(
4468 format, type, fbo_format_info.tex_type),
4469 GL_INVALID_OPERATION);
4470
4471 if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
4472 ctx->glReadPixelsOffsetAEMU(
4473 ctx, x, y, width, height,
4474 format, type, (uintptr_t)pixels);
4475 } else {
4476 ctx->m_glReadPixels_enc(
4477 ctx, x, y, width, height,
4478 format, type, pixels);
4479 }
4480}
4481
4482// Track enabled state for some things like:
4483// - Primitive restart
4484void GL2Encoder::s_glEnable(void* self, GLenum what) {
4485 GL2Encoder *ctx = (GL2Encoder *)self;
4486
4487 switch (what) {
4488 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4489 ctx->m_primitiveRestartEnabled = true;
4490 break;
4491 }
4492
4493 ctx->m_glEnable_enc(ctx, what);
4494}
4495
4496void GL2Encoder::s_glDisable(void* self, GLenum what) {
4497 GL2Encoder *ctx = (GL2Encoder *)self;
4498
4499 switch (what) {
4500 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4501 ctx->m_primitiveRestartEnabled = false;
4502 break;
4503 }
4504
4505 ctx->m_glDisable_enc(ctx, what);
4506}
4507
4508void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
4509 GL2Encoder *ctx = (GL2Encoder *)self;
4510
4511 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4512
4513 ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
4514}
4515
4516void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
4517 GL2Encoder *ctx = (GL2Encoder *)self;
4518
4519 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4520
4521 ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
4522}
4523
4524void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
4525 GL2Encoder *ctx = (GL2Encoder *)self;
4526
4527 SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4528
4529 ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
4530}
4531
4532void 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) {
4533 GL2Encoder *ctx = (GL2Encoder *)self;
4534 GLClientState* state = ctx->m_state;
4535
4536 bool validateColor = mask | GL_COLOR_BUFFER_BIT;
4537 bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
4538 bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
4539
4540 FboFormatInfo read_fbo_format_info;
4541 FboFormatInfo draw_fbo_format_info;
4542 if (validateColor) {
4543 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4544 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4545
4546 if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4547 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
4548 SET_ERROR_IF(
4549 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4550 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4551 !GLESv2Validation::blitFramebufferFormat(
4552 read_fbo_format_info.tex_type,
4553 draw_fbo_format_info.tex_type),
4554 GL_INVALID_OPERATION);
4555 }
4556 }
4557
4558 if (validateDepth) {
4559 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
4560 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
4561
4562 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4563 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4564 SET_ERROR_IF(
4565 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4566 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4567 !GLESv2Validation::blitFramebufferFormat(
4568 read_fbo_format_info.rb_format,
4569 draw_fbo_format_info.rb_format),
4570 GL_INVALID_OPERATION);
4571 }
4572 }
4573
4574 if (validateStencil) {
4575 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
4576 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
4577
4578 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4579 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4580 SET_ERROR_IF(
4581 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4582 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4583 !GLESv2Validation::blitFramebufferFormat(
4584 read_fbo_format_info.rb_format,
4585 draw_fbo_format_info.rb_format),
4586 GL_INVALID_OPERATION);
4587 }
4588 }
4589
4590 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4591 SET_ERROR_IF(
4592 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4593 draw_fbo_format_info.rb_multisamples > 0,
4594 GL_INVALID_OPERATION);
4595 SET_ERROR_IF(
4596 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4597 draw_fbo_format_info.tex_multisamples > 0,
4598 GL_INVALID_OPERATION);
4599
4600 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4601 SET_ERROR_IF(
4602 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4603 read_fbo_format_info.rb_multisamples > 0 &&
4604 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4605 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4606 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4607 (read_fbo_format_info.rb_format !=
4608 draw_fbo_format_info.rb_format),
4609 GL_INVALID_OPERATION);
4610 SET_ERROR_IF(
4611 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4612 read_fbo_format_info.rb_multisamples > 0 &&
4613 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4614 (srcX0 != dstX0 || srcY0 != dstY0 ||
4615 srcX1 != dstX1 || srcY1 != dstY1),
4616 GL_INVALID_OPERATION);
4617
4618 ctx->m_glBlitFramebuffer_enc(ctx,
4619 srcX0, srcY0, srcX1, srcY1,
4620 dstX0, dstY0, dstX1, dstY1,
4621 mask, filter);
4622}
4623
4624void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
4625 GL2Encoder *ctx = (GL2Encoder *)self;
4626
4627 SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
4628 pname != GL_SAMPLES,
4629 GL_INVALID_ENUM);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004630 SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004631 SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004632 !GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4633 !GLESv2Validation::depthRenderableFormat(ctx, internalformat) &&
4634 !GLESv2Validation::stencilRenderableFormat(ctx, internalformat),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004635 GL_INVALID_ENUM);
4636 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4637
4638 if (bufSize < 1) return;
4639
4640 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
4641 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
4642 switch (pname) {
4643 case GL_NUM_SAMPLE_COUNTS:
4644 *params = 3;
4645 break;
4646 case GL_SAMPLES:
4647 params[0] = 4;
4648 if (bufSize > 1) params[1] = 2;
4649 if (bufSize > 2) params[2] = 1;
4650 break;
4651 default:
4652 break;
4653 }
4654}
4655
4656void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
4657 GL2Encoder *ctx = (GL2Encoder *)self;
4658 GLClientState* state = ctx->m_state;
4659
4660 SET_ERROR_IF(target != GL_TEXTURE_2D &&
4661 target != GL_TEXTURE_3D &&
Yahan Zhou53c64582018-04-16 15:46:17 -07004662 target != GL_TEXTURE_CUBE_MAP &&
4663 target != GL_TEXTURE_2D_ARRAY,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004664 GL_INVALID_ENUM);
4665
4666 GLuint tex = state->getBoundTexture(target);
4667 GLenum internalformat = state->queryTexInternalFormat(tex);
4668 GLenum format = state->queryTexFormat(tex);
4669
4670 SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
4671 GL_INVALID_OPERATION);
4672 SET_ERROR_IF(tex &&
4673 !GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004674 !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4675 GLESv2Validation::filterableTexFormat(ctx, internalformat)),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004676 GL_INVALID_OPERATION);
4677
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08004678 if (target == GL_TEXTURE_2D) {
4679 ctx->override2DTextureTarget(target);
4680 }
4681
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004682 ctx->m_glGenerateMipmap_enc(ctx, target);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08004683
4684 if (target == GL_TEXTURE_2D) {
4685 ctx->restore2DTextureTarget(target);
4686 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004687}
4688
4689void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4690 GL2Encoder *ctx = (GL2Encoder *)self;
4691 GLint maxCombinedUnits;
4692 ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4693 SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4694
4695 ctx->m_glBindSampler_enc(ctx, unit, sampler);
4696}
4697
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004698GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4699 GL2Encoder *ctx = (GL2Encoder *)self;
4700 uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4701 return (GLsync)(uintptr_t)syncHandle;
4702}
4703
4704GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4705 GL2Encoder *ctx = (GL2Encoder *)self;
4706 return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4707}
4708
4709void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4710 GL2Encoder *ctx = (GL2Encoder *)self;
4711 ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4712}
4713
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004714void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) {
4715 GL2Encoder *ctx = (GL2Encoder *)self;
4716
4717 if (!sync) return;
4718
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004719 ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4720}
4721
4722GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4723 GL2Encoder *ctx = (GL2Encoder *)self;
4724 return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4725}
4726
4727void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4728 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004729
4730 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4731
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004732 return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004733}
4734
4735#define LIMIT_CASE(target, lim) \
4736 case target: \
4737 ctx->glGetIntegerv(ctx, lim, &limit); \
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004738 SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004739 break; \
4740
4741void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) {
4742 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004743 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004744
4745 GLint limit;
4746
4747 switch (target) {
4748 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4749 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4750 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4751 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4752 default:
4753 break;
4754 }
4755
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004756 const GLClientState::VertexAttribBindingVector& currBindings =
4757 state->currentVertexBufferBindings();
4758
4759 switch (target) {
4760 case GL_VERTEX_BINDING_DIVISOR:
4761 case GL_VERTEX_BINDING_OFFSET:
4762 case GL_VERTEX_BINDING_STRIDE:
4763 case GL_VERTEX_BINDING_BUFFER:
4764 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4765 break;
4766 default:
4767 break;
4768 }
4769
4770 switch (target) {
4771 case GL_VERTEX_BINDING_DIVISOR:
4772 *params = currBindings[index].divisor;
4773 return;
4774 case GL_VERTEX_BINDING_OFFSET:
4775 *params = currBindings[index].offset;
4776 return;
4777 case GL_VERTEX_BINDING_STRIDE:
4778 *params = currBindings[index].effectiveStride;
4779 return;
4780 case GL_VERTEX_BINDING_BUFFER:
4781 *params = currBindings[index].buffer;
4782 return;
4783 default:
4784 break;
4785 }
4786
Lingfeng Yang80a36332017-07-09 10:58:07 -07004787 ctx->safe_glGetIntegeri_v(target, index, params);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004788}
4789
4790void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
4791 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004792 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004793
4794 GLint limit;
4795
4796 switch (target) {
4797 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4798 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4799 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4800 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4801 default:
4802 break;
4803 }
4804
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004805 const GLClientState::VertexAttribBindingVector& currBindings =
4806 state->currentVertexBufferBindings();
4807
4808 switch (target) {
4809 case GL_VERTEX_BINDING_DIVISOR:
4810 case GL_VERTEX_BINDING_OFFSET:
4811 case GL_VERTEX_BINDING_STRIDE:
4812 case GL_VERTEX_BINDING_BUFFER:
4813 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4814 break;
4815 default:
4816 break;
4817 }
4818
4819 switch (target) {
4820 case GL_VERTEX_BINDING_DIVISOR:
4821 *params = currBindings[index].divisor;
4822 return;
4823 case GL_VERTEX_BINDING_OFFSET:
4824 *params = currBindings[index].offset;
4825 return;
4826 case GL_VERTEX_BINDING_STRIDE:
4827 *params = currBindings[index].effectiveStride;
4828 return;
4829 case GL_VERTEX_BINDING_BUFFER:
4830 *params = currBindings[index].buffer;
4831 return;
4832 default:
4833 break;
4834 }
4835
Lingfeng Yang80a36332017-07-09 10:58:07 -07004836 ctx->safe_glGetInteger64i_v(target, index, params);
4837}
4838
4839void GL2Encoder::s_glGetInteger64v(void* self, GLenum param, GLint64* val) {
4840 GL2Encoder *ctx = (GL2Encoder *)self;
4841 ctx->safe_glGetInteger64v(param, val);
4842}
4843
4844void GL2Encoder::s_glGetBooleani_v(void* self, GLenum param, GLuint index, GLboolean* val) {
4845 GL2Encoder *ctx = (GL2Encoder *)self;
4846 ctx->safe_glGetBooleani_v(param, index, val);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004847}
4848
4849void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4850 GL2Encoder *ctx = (GL2Encoder *)self;
4851 ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4852 if (pname == GL_SHADER_SOURCE_LENGTH) {
4853 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4854 if (shaderData) {
4855 int totalLen = 0;
4856 for (int i = 0; i < shaderData->sources.size(); i++) {
4857 totalLen += shaderData->sources[i].size();
4858 }
4859 if (totalLen != 0) {
4860 *params = totalLen + 1; // account for null terminator
4861 }
4862 }
4863 }
4864}
4865
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004866void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) {
4867 GL2Encoder *ctx = (GL2Encoder*)self;
4868 GLClientState* state = ctx->m_state;
4869 GLSharedGroupPtr shared = ctx->m_shared;
4870
4871 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4872 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4873 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4874
4875 ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program);
4876 if (!state->currentProgram()) {
4877 state->setCurrentShaderProgram(program);
4878 }
4879}
4880
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004881GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4882
4883 GLint* length = NULL;
4884 GL2Encoder* ctx = (GL2Encoder*)self;
4885
4886 int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
4887 char *str = new char[len + 1];
4888 glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
4889
4890 // Do GLSharedGroup and location WorkARound-specific initialization
4891 // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4892 uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4893 ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004894
Lingfeng Yang44209df2018-09-21 10:04:17 -07004895 if (!replaceSamplerExternalWith2D(str, &spData->shaderData)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004896 delete [] str;
4897 ctx->setError(GL_OUT_OF_MEMORY);
4898 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4899 return -1;
4900 }
4901
4902 GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
4903 delete [] str;
4904
4905 // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4906 GLint linkStatus = 0;
4907 ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4908 if (!linkStatus) {
4909 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4910 return -1;
4911 }
4912
4913 ctx->m_shared->associateGLShaderProgram(res, spDataId);
4914
4915 GLint numUniforms = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07004916 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORMS, &numUniforms);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004917 ctx->m_shared->initShaderProgramData(res, numUniforms);
4918
4919 GLint maxLength=0;
4920 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4921
4922 GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4923
4924 for (GLint i = 0; i < numUniforms; ++i) {
4925 ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4926 GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4927 ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4928 }
4929
4930 ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4931
4932 delete [] name;
4933
4934 return res;
4935}
4936
4937void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4938{
4939 GL2Encoder *ctx = (GL2Encoder*)self;
4940 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4941 ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4942}
4943
4944void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4945{
4946 GL2Encoder *ctx = (GL2Encoder*)self;
4947 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4948 ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4949}
4950
4951void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4952{
4953 GL2Encoder *ctx = (GL2Encoder*)self;
4954 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004955 ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004956
4957 GLClientState* state = ctx->m_state;
4958 GLSharedGroupPtr shared = ctx->m_shared;
4959 GLenum target;
4960
4961 if (shared->setSamplerUniform(program, location, v0, &target)) {
4962 GLenum origActiveTexture = state->getActiveTextureUnit();
4963 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4964 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4965 }
4966 state->setActiveTextureUnit(origActiveTexture);
4967 }
4968}
4969
4970void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4971{
4972 GL2Encoder *ctx = (GL2Encoder*)self;
4973 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4974 ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4975}
4976
4977void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4978{
4979 GL2Encoder *ctx = (GL2Encoder*)self;
4980 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4981 ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4982
4983 GLClientState* state = ctx->m_state;
4984 GLSharedGroupPtr shared = ctx->m_shared;
4985 GLenum target;
4986
4987 if (shared->setSamplerUniform(program, location, v0, &target)) {
4988 GLenum origActiveTexture = state->getActiveTextureUnit();
4989 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4990 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4991 }
4992 state->setActiveTextureUnit(origActiveTexture);
4993 }
4994}
4995
4996void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4997{
4998 GL2Encoder *ctx = (GL2Encoder*)self;
4999 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5000 ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
5001}
5002
5003void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
5004{
5005 GL2Encoder *ctx = (GL2Encoder*)self;
5006 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5007 ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
5008}
5009
5010void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
5011{
5012 GL2Encoder *ctx = (GL2Encoder*)self;
5013 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5014 ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
5015}
5016
5017void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
5018{
5019 GL2Encoder *ctx = (GL2Encoder*)self;
5020 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5021 ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
5022}
5023
5024void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
5025{
5026 GL2Encoder *ctx = (GL2Encoder*)self;
5027 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5028 ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
5029}
5030
5031void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
5032{
5033 GL2Encoder *ctx = (GL2Encoder*)self;
5034 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5035 ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
5036}
5037
5038void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
5039{
5040 GL2Encoder *ctx = (GL2Encoder*)self;
5041 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5042 ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
5043}
5044
5045void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
5046{
5047 GL2Encoder *ctx = (GL2Encoder*)self;
5048 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5049 ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
5050}
5051
5052void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
5053{
5054 GL2Encoder *ctx = (GL2Encoder*)self;
5055 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5056 ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
5057}
5058
5059void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
5060{
5061 GL2Encoder *ctx = (GL2Encoder*)self;
5062 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5063 ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
5064}
5065
5066void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
5067{
5068 GL2Encoder *ctx = (GL2Encoder*)self;
5069 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5070 ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
5071}
5072
5073void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
5074{
5075 GL2Encoder *ctx = (GL2Encoder*)self;
5076 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5077 ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
5078}
5079
5080void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
5081{
5082 GL2Encoder *ctx = (GL2Encoder*)self;
5083 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5084 ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
5085}
5086
5087void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
5088{
5089 GL2Encoder *ctx = (GL2Encoder*)self;
5090 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5091 ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
5092}
5093
5094void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
5095{
5096 GL2Encoder *ctx = (GL2Encoder*)self;
5097 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5098 ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
5099}
5100
5101void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
5102{
5103 GL2Encoder *ctx = (GL2Encoder*)self;
5104 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5105 ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
5106}
5107
5108void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
5109{
5110 GL2Encoder *ctx = (GL2Encoder*)self;
5111 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5112 ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
5113}
5114
5115void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
5116{
5117 GL2Encoder *ctx = (GL2Encoder*)self;
5118 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5119 ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
5120}
5121
5122void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
5123{
5124 GL2Encoder *ctx = (GL2Encoder*)self;
5125 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5126 ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
5127}
5128
5129void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5130{
5131 GL2Encoder *ctx = (GL2Encoder*)self;
5132 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5133 ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
5134}
5135
5136void GL2Encoder::s_glProgramUniformMatrix2x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5137{
5138 GL2Encoder *ctx = (GL2Encoder*)self;
5139 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5140 ctx->m_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
5141}
5142
5143void GL2Encoder::s_glProgramUniformMatrix2x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5144{
5145 GL2Encoder *ctx = (GL2Encoder*)self;
5146 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5147 ctx->m_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
5148}
5149
5150void GL2Encoder::s_glProgramUniformMatrix3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5151{
5152 GL2Encoder *ctx = (GL2Encoder*)self;
5153 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5154 ctx->m_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
5155}
5156
5157void GL2Encoder::s_glProgramUniformMatrix3x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5158{
5159 GL2Encoder *ctx = (GL2Encoder*)self;
5160 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5161 ctx->m_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
5162}
5163
5164void GL2Encoder::s_glProgramUniformMatrix3x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5165{
5166 GL2Encoder *ctx = (GL2Encoder*)self;
5167 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5168 ctx->m_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
5169}
5170
5171void GL2Encoder::s_glProgramUniformMatrix4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5172{
5173 GL2Encoder *ctx = (GL2Encoder*)self;
5174 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5175 ctx->m_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
5176}
5177
5178void GL2Encoder::s_glProgramUniformMatrix4x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5179{
5180 GL2Encoder *ctx = (GL2Encoder*)self;
5181 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5182 ctx->m_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
5183}
5184
5185void GL2Encoder::s_glProgramUniformMatrix4x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5186{
5187 GL2Encoder *ctx = (GL2Encoder*)self;
5188 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5189 ctx->m_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
5190}
5191
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005192void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) {
5193 GL2Encoder* ctx = (GL2Encoder*)self;
5194 ctx->m_glProgramParameteri_enc(self, program, pname, value);
5195}
5196
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005197void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
5198{
5199 GL2Encoder *ctx = (GL2Encoder*)self;
5200 GLClientState* state = ctx->m_state;
5201 GLSharedGroupPtr shared = ctx->m_shared;
5202
5203 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
5204 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
5205 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
5206
5207 ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
5208 state->associateProgramWithPipeline(program, pipeline);
5209
5210 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
5211 if (state->currentProgram()) {
5212 return;
5213 }
5214
5215 // Otherwise, update host texture 2D bindings.
5216 ctx->updateHostTexture2DBindingsFromProgramData(program);
5217}
5218
5219void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
5220{
5221 GL2Encoder *ctx = (GL2Encoder*)self;
5222 GLClientState* state = ctx->m_state;
5223
5224 ctx->m_glBindProgramPipeline_enc(self, pipeline);
5225
5226 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
5227 if (!pipeline || state->currentProgram()) {
5228 return;
5229 }
5230
5231 GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
5232 for (; it != state->programPipelineEnd(); ++it) {
5233 if (it->second == pipeline) {
5234 ctx->updateHostTexture2DBindingsFromProgramData(it->first);
5235 }
5236 }
5237}
5238
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005239void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
5240 GL2Encoder *ctx = (GL2Encoder*)self;
5241 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
5242 if (bufSize == 0) {
5243 if (length) *length = 0;
5244 return;
5245 }
5246
5247 // Avoid modifying |name| if |*length| < bufSize.
5248 GLint* intermediate = new GLint[bufSize];
5249 GLsizei* myLength = length ? length : new GLsizei;
5250 bool needFreeLength = length == NULL;
5251
5252 ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
5253 GLsizei writtenInts = *myLength;
5254 memcpy(params, intermediate, writtenInts * sizeof(GLint));
5255
5256 delete [] intermediate;
5257 if (needFreeLength)
5258 delete myLength;
5259}
5260
5261GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
5262 GL2Encoder *ctx = (GL2Encoder*)self;
5263 return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
5264}
5265
5266GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
5267 GL2Encoder *ctx = (GL2Encoder*)self;
5268 return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
5269}
5270
5271void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
5272 GL2Encoder *ctx = (GL2Encoder*)self;
5273 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
5274 if (bufSize == 0) {
5275 if (length) *length = 0;
5276 return;
5277 }
5278
5279 // Avoid modifying |name| if |*length| < bufSize.
5280 char* intermediate = new char[bufSize];
5281 GLsizei* myLength = length ? length : new GLsizei;
5282 bool needFreeLength = length == NULL;
5283
5284 ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
5285 GLsizei writtenStrLen = *myLength;
5286 memcpy(name, intermediate, writtenStrLen + 1);
5287
5288 delete [] intermediate;
5289 if (needFreeLength)
5290 delete myLength;
5291}
5292
5293void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
5294 GL2Encoder *ctx = (GL2Encoder*)self;
5295 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
5296 if (bufSize == 0) {
5297 if (length) *length = 0;
5298 return;
5299 }
5300
5301 // Avoid modifying |infoLog| if |*length| < bufSize.
5302 GLchar* intermediate = new GLchar[bufSize];
5303 GLsizei* myLength = length ? length : new GLsizei;
5304 bool needFreeLength = length == NULL;
5305
5306 ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
5307 GLsizei writtenStrLen = *myLength;
5308 memcpy(infoLog, intermediate, writtenStrLen + 1);
5309
5310 delete [] intermediate;
5311 if (needFreeLength)
5312 delete myLength;
5313}
5314
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005315void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
5316 GL2Encoder *ctx = (GL2Encoder*)self;
5317 GLClientState* state = ctx->m_state;
5318
Lingfeng Yang07289902017-01-27 12:26:19 -08005319 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005320 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5321
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005322 state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false);
5323 ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset);
5324}
5325
5326void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
5327 GL2Encoder *ctx = (GL2Encoder*)self;
5328 GLClientState* state = ctx->m_state;
5329
Lingfeng Yang07289902017-01-27 12:26:19 -08005330 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005331 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5332
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005333 state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true);
5334 ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset);
5335}
5336
5337void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005338 GL2Encoder *ctx = (GL2Encoder*)self;
5339 GLClientState* state = ctx->m_state;
5340
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005341 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5342
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005343 state->setVertexBindingDivisor(bindingindex, divisor);
5344 ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor);
5345}
5346
5347void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) {
5348 GL2Encoder *ctx = (GL2Encoder*)self;
5349 GLClientState* state = ctx->m_state;
Lingfeng Yang07289902017-01-27 12:26:19 -08005350 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005351 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005352
5353 state->setVertexAttribBinding(attribindex, bindingindex);
5354 ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex);
5355}
5356
5357void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
5358 GL2Encoder *ctx = (GL2Encoder*)self;
5359 GLClientState* state = ctx->m_state;
5360
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005361 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
5362
5363 GLint maxStride;
5364 ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
5365 SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE);
5366
5367 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5368
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005369 state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride);
5370 ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride);
5371}
5372
5373void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) {
5374 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005375 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005376
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005377 bool hasClientArrays = false;
5378 ctx->getVBOUsage(&hasClientArrays, NULL);
5379
5380 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
5381 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5382 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
5383
5384 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005385 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005386 // BufferData* buf = ctx->getBufferData(target);
5387 // if (buf) {
5388 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
5389 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005390 ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect);
5391 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005392 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
5393 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005394 ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize);
5395 }
5396}
5397
5398void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) {
5399 GL2Encoder *ctx = (GL2Encoder*)self;
5400
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005401 GLClientState* state = ctx->m_state;
5402
5403 bool hasClientArrays = false;
5404 ctx->getVBOUsage(&hasClientArrays, NULL);
5405
5406 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
5407 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5408 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
5409
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005410 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005411
5412 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005413 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005414 // BufferData* buf = ctx->getBufferData(target);
5415 // if (buf) {
5416 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
5417 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005418 ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect);
5419 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005420 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
5421 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005422 ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize);
5423 }
5424
5425}
5426
5427void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
5428 GL2Encoder *ctx = (GL2Encoder*)self;
5429 GLClientState* state = ctx->m_state;
5430
5431 SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
5432 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
5433 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
5434 SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
5435 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005436 GLint max_samples;
5437 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
5438 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005439
5440 state->setBoundTextureInternalFormat(target, internalformat);
5441 state->setBoundTextureDims(target, 0, width, height, 1);
5442 state->setBoundTextureImmutableFormat(target);
5443 state->setBoundTextureSamples(target, samples);
5444
5445 ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
5446}
5447
Yahan Zhou72944ba2019-01-02 15:43:46 -08005448GLenum GL2Encoder::s_glGetGraphicsResetStatusEXT(void* self) {
5449 (void)self;
5450 return GL_NO_ERROR;
5451}
5452
5453void GL2Encoder::s_glReadnPixelsEXT(void* self, GLint x, GLint y, GLsizei width,
5454 GLsizei height, GLenum format, GLenum type, GLsizei bufSize,
5455 GLvoid* pixels) {
5456 GL2Encoder *ctx = (GL2Encoder*)self;
5457 SET_ERROR_IF(bufSize < glesv2_enc::pixelDataSize(self, width, height, format,
5458 type, 1), GL_INVALID_OPERATION);
5459 s_glReadPixels(self, x, y, width, height, format, type, pixels);
5460}
5461
5462void GL2Encoder::s_glGetnUniformfvEXT(void *self, GLuint program, GLint location,
5463 GLsizei bufSize, GLfloat* params) {
5464 GL2Encoder *ctx = (GL2Encoder*)self;
5465 SET_ERROR_IF(bufSize < glSizeof(glesv2_enc::uniformType(self, program,
5466 location)), GL_INVALID_OPERATION);
5467 s_glGetUniformfv(self, program, location, params);
5468}
5469
5470void GL2Encoder::s_glGetnUniformivEXT(void *self, GLuint program, GLint location,
5471 GLsizei bufSize, GLint* params) {
5472 GL2Encoder *ctx = (GL2Encoder*)self;
5473 SET_ERROR_IF(bufSize < glSizeof(glesv2_enc::uniformType(self, program,
5474 location)), GL_INVALID_OPERATION);
5475 s_glGetUniformiv(self, program, location, params);
5476}