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