blob: 31f2c2a4f28d6f1355b43ecd5114cba08ca0be24 [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";
1338 static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
1339 static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
1340
1341 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
1342 char* c = str;
1343 while ((c = strstr(c, STR_HASH_EXTENSION))) {
1344 char* start = c;
1345 c += sizeof(STR_HASH_EXTENSION)-1;
1346 while (isspace(*c) && *c != '\0') {
1347 c++;
1348 }
1349 if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
1350 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
1351 {
1352 // #extension statements are terminated by end of line
1353 c = start;
1354 while (*c != '\0' && *c != '\r' && *c != '\n') {
1355 *c++ = ' ';
1356 }
1357 }
1358 }
1359
1360 // -- replace "samplerExternalOES" with "sampler2D" and record name
1361 c = str;
1362 while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
1363 // Make sure "samplerExternalOES" isn't a substring of a larger token
1364 if (c == str || !isspace(*(c-1))) {
1365 c++;
1366 continue;
1367 }
1368 char* sampler_start = c;
1369 c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
1370 if (!isspace(*c) && *c != '\0') {
1371 continue;
1372 }
1373
1374 // capture sampler name
1375 while (isspace(*c) && *c != '\0') {
1376 c++;
1377 }
1378 if (!isalpha(*c) && *c != '_') {
1379 // not an identifier
1380 return false;
1381 }
1382 char* name_start = c;
1383 do {
1384 c++;
1385 } while (isalnum(*c) || *c == '_');
1386 data->samplerExternalNames.push_back(
1387 android::String8(name_start, c - name_start));
1388
1389 // memcpy instead of strcpy since we don't want the NUL terminator
1390 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
1391 }
1392
1393 return true;
1394}
1395
Bo Hu73568cd2015-01-20 16:29:50 -08001396void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
1397{
1398 GL2Encoder* ctx = (GL2Encoder*)self;
1399 // Although it is not supported, need to set proper error code.
1400 SET_ERROR_IF(1, GL_INVALID_ENUM);
1401}
1402
David 'Digit' Turner02fdb692014-10-30 18:07:56 +01001403void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -08001404{
1405 GL2Encoder* ctx = (GL2Encoder*)self;
1406 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001407 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(shader), GL_INVALID_VALUE);
Tina Zhang7a84f652014-12-04 12:37:30 +08001408 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
1409 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001410
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001411 // Track original sources---they may be translated in the backend
1412 std::vector<std::string> orig_sources;
1413 for (int i = 0; i < count; i++) {
1414 orig_sources.push_back(std::string((const char*)(string[i])));
1415 }
1416 shaderData->sources = orig_sources;
1417
keunyoungb85b2752013-03-08 12:28:03 -08001418 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
1419 char *str = new char[len + 1];
1420 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
1421
1422 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
1423 // Perhaps we can borrow Mesa's pre-processor?
1424
1425 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001426 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001427 ctx->setError(GL_OUT_OF_MEMORY);
1428 return;
1429 }
keunyoungb85b2752013-03-08 12:28:03 -08001430 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001431 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001432}
1433
1434void GL2Encoder::s_glFinish(void *self)
1435{
1436 GL2Encoder *ctx = (GL2Encoder *)self;
1437 ctx->glFinishRoundTrip(self);
1438}
1439
1440void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1441{
1442 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -08001443 bool isProgram = ctx->m_shared->isProgram(program);
1444 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
1445 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
1446
keunyoungb85b2752013-03-08 12:28:03 -08001447 ctx->m_glLinkProgram_enc(self, program);
1448
1449 GLint linkStatus = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07001450 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001451 if (!linkStatus) {
keunyoungb85b2752013-03-08 12:28:03 -08001452 return;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001453 }
keunyoungb85b2752013-03-08 12:28:03 -08001454
1455 //get number of active uniforms in the program
1456 GLint numUniforms=0;
1457 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
1458 ctx->m_shared->initProgramData(program,numUniforms);
1459
1460 //get the length of the longest uniform name
1461 GLint maxLength=0;
1462 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
1463
1464 GLint size;
1465 GLenum type;
1466 GLchar *name = new GLchar[maxLength+1];
1467 GLint location;
1468 //for each active uniform, get its size and starting location.
1469 for (GLint i=0 ; i<numUniforms ; ++i)
1470 {
1471 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1472 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1473 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1474 }
1475 ctx->m_shared->setupLocationShiftWAR(program);
1476
1477 delete[] name;
1478}
1479
1480void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1481{
1482 GL2Encoder *ctx = (GL2Encoder*)self;
1483 ctx->m_glDeleteProgram_enc(self, program);
1484
1485 ctx->m_shared->deleteProgramData(program);
1486}
1487
1488void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1489{
1490 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001491 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001492 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001493 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1494 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1495 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1496 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1497}
1498void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1499{
1500 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001501 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001502 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001503 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1504 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1505 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1506 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1507}
1508
1509GLuint GL2Encoder::s_glCreateProgram(void * self)
1510{
1511 GL2Encoder *ctx = (GL2Encoder*)self;
1512 GLuint program = ctx->m_glCreateProgram_enc(self);
1513 if (program!=0)
1514 ctx->m_shared->addProgramData(program);
1515 return program;
1516}
1517
1518GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1519{
1520 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001521 RET_AND_SET_ERROR_IF(!GLESv2Validation::shaderType(ctx, shaderType), GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001522 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1523 if (shader != 0) {
1524 if (!ctx->m_shared->addShaderData(shader)) {
1525 ctx->m_glDeleteShader_enc(self, shader);
1526 return 0;
1527 }
1528 }
1529 return shader;
1530}
1531
bohu56bf82f2014-10-17 15:35:48 -07001532void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1533 GLsizei* count, GLuint* shaders)
1534{
1535 GL2Encoder *ctx = (GL2Encoder*)self;
1536 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1537 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1538}
1539
1540void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1541 GLsizei* length, GLchar* source)
1542{
1543 GL2Encoder *ctx = (GL2Encoder*)self;
1544 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1545 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001546 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
1547 if (shaderData) {
1548 std::string returned;
1549 int curr_len = 0;
1550 for (int i = 0; i < shaderData->sources.size(); i++) {
1551 if (curr_len + shaderData->sources[i].size() < bufsize - 1) {
1552 returned += shaderData->sources[i];
1553 } else {
1554 returned += shaderData->sources[i].substr(0, bufsize - 1 - curr_len);
1555 break;
1556 }
1557 }
1558 memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize);
1559 }
bohu56bf82f2014-10-17 15:35:48 -07001560}
1561
1562void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1563 GLsizei* length, GLchar* infolog)
1564{
1565 GL2Encoder *ctx = (GL2Encoder*)self;
1566 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1567 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1568}
1569
1570void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, 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_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1576}
1577
keunyoungb85b2752013-03-08 12:28:03 -08001578void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1579{
1580 GL2Encoder *ctx = (GL2Encoder*)self;
1581 ctx->m_glDeleteShader_enc(self,shader);
1582 ctx->m_shared->unrefShaderData(shader);
1583}
1584
1585void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1586{
1587 GL2Encoder *ctx = (GL2Encoder*)self;
1588 ctx->m_glAttachShader_enc(self, program, shader);
1589 ctx->m_shared->attachShader(program, shader);
1590}
1591
1592void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1593{
1594 GL2Encoder *ctx = (GL2Encoder*)self;
1595 ctx->m_glDetachShader_enc(self, program, shader);
1596 ctx->m_shared->detachShader(program, shader);
1597}
1598
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001599int sArrIndexOfUniformExpr(const char* name, int* err) {
1600 *err = 0;
1601 int arrIndex = 0;
1602 int namelen = strlen(name);
1603 if (name[namelen-1] == ']') {
1604 const char *brace = strrchr(name,'[');
1605 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1606 *err = 1; return 0;
1607 }
1608 }
1609 return arrIndex;
1610}
1611
keunyoungb85b2752013-03-08 12:28:03 -08001612int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1613{
1614 if (!name) return -1;
1615
1616 GL2Encoder *ctx = (GL2Encoder*)self;
1617
1618 // if we need the uniform location WAR
1619 // parse array index from the end of the name string
1620 int arrIndex = 0;
1621 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1622 if (needLocationWAR) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001623 int err;
1624 arrIndex = sArrIndexOfUniformExpr(name, &err);
1625 if (err) return -1;
keunyoungb85b2752013-03-08 12:28:03 -08001626 }
1627
1628 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1629 if (hostLoc >= 0 && needLocationWAR) {
1630 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1631 }
1632 return hostLoc;
1633}
1634
1635bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1636{
1637 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1638 return false;
1639
1640 m_state->setActiveTextureUnit(texUnit);
1641
1642 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1643 if (newTarget != oldTarget) {
1644 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1645 m_state->disableTextureTarget(GL_TEXTURE_2D);
1646 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1647 } else {
1648 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1649 m_state->enableTextureTarget(GL_TEXTURE_2D);
1650 }
1651 m_glActiveTexture_enc(this, texUnit);
1652 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1653 m_state->getBoundTexture(newTarget));
1654 return true;
1655 }
1656
1657 return false;
1658}
1659
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001660void GL2Encoder::updateHostTexture2DBindingsFromProgramData(GLuint program) {
1661 GL2Encoder *ctx = this;
keunyoungb85b2752013-03-08 12:28:03 -08001662 GLClientState* state = ctx->m_state;
1663 GLSharedGroupPtr shared = ctx->m_shared;
1664
keunyoungb85b2752013-03-08 12:28:03 -08001665 GLenum origActiveTexture = state->getActiveTextureUnit();
1666 GLenum hostActiveTexture = origActiveTexture;
1667 GLint samplerIdx = -1;
1668 GLint samplerVal;
1669 GLenum samplerTarget;
1670 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1671 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1672 continue;
1673 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001674 samplerTarget))
keunyoungb85b2752013-03-08 12:28:03 -08001675 {
1676 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1677 }
1678 }
1679 state->setActiveTextureUnit(origActiveTexture);
1680 if (hostActiveTexture != origActiveTexture) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001681 ctx->m_glActiveTexture_enc(ctx, origActiveTexture);
keunyoungb85b2752013-03-08 12:28:03 -08001682 }
1683}
1684
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001685void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1686{
1687 GL2Encoder *ctx = (GL2Encoder*)self;
1688 GLSharedGroupPtr shared = ctx->m_shared;
1689
1690 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
1691 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1692
1693 ctx->m_glUseProgram_enc(self, program);
1694 ctx->m_state->setCurrentProgram(program);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001695 ctx->m_state->setCurrentShaderProgram(program);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001696
1697 ctx->updateHostTexture2DBindingsFromProgramData(program);
1698}
1699
keunyoungb85b2752013-03-08 12:28:03 -08001700void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1701{
1702 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001703 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001704 ctx->m_glUniform1f_enc(self, hostLoc, x);
1705}
1706
1707void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1708{
1709 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001710 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001711 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1712}
1713
1714void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1715{
1716 GL2Encoder *ctx = (GL2Encoder*)self;
1717 GLClientState* state = ctx->m_state;
1718 GLSharedGroupPtr shared = ctx->m_shared;
1719
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001720 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001721 ctx->m_glUniform1i_enc(self, hostLoc, x);
1722
1723 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001724 if (shared->setSamplerUniform(state->currentShaderProgram(), location, x, &target)) {
keunyoungb85b2752013-03-08 12:28:03 -08001725 GLenum origActiveTexture = state->getActiveTextureUnit();
1726 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1727 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1728 }
1729 state->setActiveTextureUnit(origActiveTexture);
1730 }
1731}
1732
1733void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1734{
1735 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001736 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001737 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1738}
1739
1740void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1741{
1742 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001743 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001744 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1745}
1746
1747void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1748{
1749 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001750 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001751 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1752}
1753
1754void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1755{
1756 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001757 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001758 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1759}
1760
1761void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1762{
1763 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001764 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001765 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1766}
1767
1768void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1769{
1770 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001771 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001772 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1773}
1774
1775void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1776{
1777 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001778 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001779 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1780}
1781
1782void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
1783{
1784 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001785 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001786 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
1787}
1788
1789void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
1790{
1791 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001792 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001793 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
1794}
1795
1796void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1797{
1798 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001799 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001800 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
1801}
1802
1803void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1804{
1805 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001806 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001807 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
1808}
1809
1810void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
1811{
1812 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001813 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001814 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
1815}
1816
1817void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
1818{
1819 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001820 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001821 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
1822}
1823
1824void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1825{
1826 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001827 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001828 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
1829}
1830
1831void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1832{
1833 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001834 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001835 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
1836}
1837
1838void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1839{
1840 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001841 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001842 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
1843}
1844
1845void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
1846{
1847 GL2Encoder* ctx = (GL2Encoder*)self;
1848 GLClientState* state = ctx->m_state;
1849 GLenum err;
1850
1851 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
1852
1853 ctx->m_glActiveTexture_enc(ctx, texture);
1854}
1855
1856void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
1857{
1858 GL2Encoder* ctx = (GL2Encoder*)self;
1859 GLClientState* state = ctx->m_state;
1860 GLenum err;
1861 GLboolean firstUse;
1862
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001863 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -08001864 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
1865
1866 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
1867 ctx->m_glBindTexture_enc(ctx, target, texture);
1868 return;
1869 }
1870
1871 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1872
1873 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
1874 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1875 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1876 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1877 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1878 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1879 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
1880 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1881
1882 if (target != priorityTarget) {
1883 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
1884 state->getBoundTexture(GL_TEXTURE_2D));
1885 }
1886 }
1887
1888 if (target == priorityTarget) {
1889 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
1890 }
1891}
1892
1893void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
1894{
1895 GL2Encoder* ctx = (GL2Encoder*)self;
1896 GLClientState* state = ctx->m_state;
1897
1898 state->deleteTextures(n, textures);
1899 ctx->m_glDeleteTextures_enc(ctx, n, textures);
1900}
1901
1902void GL2Encoder::s_glGetTexParameterfv(void* self,
1903 GLenum target, GLenum pname, GLfloat* params)
1904{
1905 GL2Encoder* ctx = (GL2Encoder*)self;
1906 const GLClientState* state = ctx->m_state;
1907
1908 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1909 ctx->override2DTextureTarget(target);
1910 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001911 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001912 } else {
1913 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
1914 }
1915}
1916
1917void GL2Encoder::s_glGetTexParameteriv(void* self,
1918 GLenum target, GLenum pname, GLint* params)
1919{
1920 GL2Encoder* ctx = (GL2Encoder*)self;
1921 const GLClientState* state = ctx->m_state;
1922
1923 switch (pname) {
1924 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1925 *params = 1;
1926 break;
1927
1928 default:
1929 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1930 ctx->override2DTextureTarget(target);
1931 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001932 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001933 } else {
1934 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
1935 }
1936 break;
1937 }
1938}
1939
1940static bool isValidTextureExternalParam(GLenum pname, GLenum param)
1941{
1942 switch (pname) {
1943 case GL_TEXTURE_MIN_FILTER:
1944 case GL_TEXTURE_MAG_FILTER:
1945 return param == GL_NEAREST || param == GL_LINEAR;
1946
1947 case GL_TEXTURE_WRAP_S:
1948 case GL_TEXTURE_WRAP_T:
1949 return param == GL_CLAMP_TO_EDGE;
1950
1951 default:
1952 return true;
1953 }
1954}
1955
1956void GL2Encoder::s_glTexParameterf(void* self,
1957 GLenum target, GLenum pname, GLfloat param)
1958{
1959 GL2Encoder* ctx = (GL2Encoder*)self;
1960 const GLClientState* state = ctx->m_state;
1961
1962 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1963 !isValidTextureExternalParam(pname, (GLenum)param)),
1964 GL_INVALID_ENUM);
1965
1966 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1967 ctx->override2DTextureTarget(target);
1968 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001969 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001970 } else {
1971 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
1972 }
1973}
1974
1975void GL2Encoder::s_glTexParameterfv(void* self,
1976 GLenum target, GLenum pname, const GLfloat* params)
1977{
1978 GL2Encoder* ctx = (GL2Encoder*)self;
1979 const GLClientState* state = ctx->m_state;
1980
1981 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
1982 !isValidTextureExternalParam(pname, (GLenum)params[0])),
1983 GL_INVALID_ENUM);
1984
1985 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
1986 ctx->override2DTextureTarget(target);
1987 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07001988 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08001989 } else {
1990 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
1991 }
1992}
1993
1994void GL2Encoder::s_glTexParameteri(void* self,
1995 GLenum target, GLenum pname, GLint param)
1996{
1997 GL2Encoder* ctx = (GL2Encoder*)self;
1998 const GLClientState* state = ctx->m_state;
1999
2000 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2001 !isValidTextureExternalParam(pname, (GLenum)param)),
2002 GL_INVALID_ENUM);
2003
2004 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2005 ctx->override2DTextureTarget(target);
2006 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002007 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002008 } else {
2009 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
2010 }
2011}
2012
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002013static int ilog2(uint32_t x) {
2014 int p = 0;
2015 while ((1 << p) < x)
2016 p++;
2017 return p;
2018}
2019
bohu26a92982014-11-25 16:50:37 -08002020void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
2021 GLint internalformat, GLsizei width, GLsizei height, GLint border,
2022 GLenum format, GLenum type, const GLvoid* pixels)
2023{
2024 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07002025 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002026
2027 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2028 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2029 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2030 // If unpack buffer is nonzero, verify unmapped state.
2031 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2032
2033 GLint max_texture_size;
2034 GLint max_cube_map_texture_size;
2035 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2036 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2037 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2038 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2039 SET_ERROR_IF((target == GL_TEXTURE_CUBE_MAP) &&
2040 (level > ilog2(max_cube_map_texture_size)), GL_INVALID_VALUE);
2041 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2042 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2043 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2044 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && width > max_cube_map_texture_size, GL_INVALID_VALUE);
2045 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && height > max_cube_map_texture_size, GL_INVALID_VALUE);
2046 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
2047 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2048 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2049 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2050 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 0) >
2051 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2052 GL_INVALID_OPERATION);
2053 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2054 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2055 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2056 glSizeof(type)),
2057 GL_INVALID_OPERATION);
2058 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2059 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2060 ((uintptr_t)pixels % glSizeof(type)),
2061 GL_INVALID_OPERATION);
2062 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
2063
2064 GLenum stateTarget = target;
2065 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2066 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2067 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2068 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2069 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2070 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2071 stateTarget = GL_TEXTURE_CUBE_MAP;
2072
2073 state->setBoundTextureInternalFormat(stateTarget, internalformat);
2074 state->setBoundTextureFormat(stateTarget, format);
2075 state->setBoundTextureType(stateTarget, type);
2076 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2077
bohu26a92982014-11-25 16:50:37 -08002078 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2079 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002080 }
Lingfeng Yang69066602016-04-12 09:29:11 -07002081
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002082 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2083 ctx->glTexImage2DOffsetAEMU(
2084 ctx, target, level, internalformat,
2085 width, height, border,
2086 format, type, (uintptr_t)pixels);
bohu26a92982014-11-25 16:50:37 -08002087 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002088 ctx->m_glTexImage2D_enc(
2089 ctx, target, level, internalformat,
2090 width, height, border,
2091 format, type, pixels);
2092 }
2093
2094 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2095 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08002096 }
2097}
2098
Yahan Zhou2a208292016-06-22 15:36:04 -07002099void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
2100 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
2101 GLenum type, const GLvoid* pixels)
2102{
2103 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002104 GLClientState* state = ctx->m_state;
2105
2106 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2107 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2108 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2109 // If unpack buffer is nonzero, verify unmapped state.
2110 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2111
2112 GLint max_texture_size;
2113 GLint max_cube_map_texture_size;
2114 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2115 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2116 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2117 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2118 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) &&
2119 level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2120 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2121 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2122
2123 GLuint tex = state->getBoundTexture(target);
2124 GLsizei neededWidth = xoffset + width;
2125 GLsizei neededHeight = yoffset + height;
2126 GLsizei neededDepth = 1;
2127
2128 if (tex && !state->queryTexEGLImageBacked(tex)) {
2129 SET_ERROR_IF(
2130 (neededWidth > state->queryTexWidth(level, tex) ||
2131 neededHeight > state->queryTexHeight(level, tex) ||
2132 neededDepth > state->queryTexDepth(level, tex)),
2133 GL_INVALID_VALUE);
2134 }
2135
2136 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2137 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2138 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2139 (state->pboNeededDataSize(width, height, 1, format, type, 0) >
2140 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2141 GL_INVALID_OPERATION);
2142 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2143 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2144 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2145 glSizeof(type)),
2146 GL_INVALID_OPERATION);
2147 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !pixels, GL_INVALID_OPERATION);
Yahan Zhou2a208292016-06-22 15:36:04 -07002148
2149 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2150 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002151 }
2152
2153 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2154 ctx->glTexSubImage2DOffsetAEMU(
2155 ctx, target, level,
2156 xoffset, yoffset, width, height,
2157 format, type, (uintptr_t)pixels);
Yahan Zhou2a208292016-06-22 15:36:04 -07002158 } else {
2159 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
2160 height, format, type, pixels);
2161 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002162
2163 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2164 ctx->restore2DTextureTarget(target);
2165 }
Yahan Zhou2a208292016-06-22 15:36:04 -07002166}
bohu26a92982014-11-25 16:50:37 -08002167
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002168void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
2169 GLenum internalformat, GLint x, GLint y,
2170 GLsizei width, GLsizei height, GLint border)
2171{
2172 GL2Encoder* ctx = (GL2Encoder*)self;
2173 GLClientState* state = ctx->m_state;
2174
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002175 SET_ERROR_IF(ctx->glCheckFramebufferStatus(ctx, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
2176 GL_INVALID_FRAMEBUFFER_OPERATION);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002177 // This is needed to work around underlying OpenGL drivers
2178 // (such as those feeding some some AMD GPUs) that expect
2179 // positive components of cube maps to be defined _before_
2180 // the negative components (otherwise a segfault occurs).
2181 GLenum extraTarget =
2182 state->copyTexImageLuminanceCubeMapAMDWorkaround
2183 (target, level, internalformat);
2184
2185 if (extraTarget) {
2186 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
2187 x, y, width, height, border);
2188 }
2189
2190 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
2191 x, y, width, height, border);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002192
2193 state->setBoundTextureInternalFormat(target, internalformat);
2194 state->setBoundTextureDims(target, level, width, height, 1);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002195}
2196
keunyoungb85b2752013-03-08 12:28:03 -08002197void GL2Encoder::s_glTexParameteriv(void* self,
2198 GLenum target, GLenum pname, const GLint* params)
2199{
2200 GL2Encoder* ctx = (GL2Encoder*)self;
2201 const GLClientState* state = ctx->m_state;
2202
2203 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2204 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2205 GL_INVALID_ENUM);
2206
2207 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2208 ctx->override2DTextureTarget(target);
2209 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002210 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002211 } else {
2212 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
2213 }
2214}
2215
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002216bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
2217 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
2218 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2219}
2220
keunyoungb85b2752013-03-08 12:28:03 -08002221void GL2Encoder::override2DTextureTarget(GLenum target)
2222{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002223 if (texture2DNeedsOverride(target)) {
2224 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2225 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08002226 }
2227}
2228
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002229void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08002230{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002231 if (texture2DNeedsOverride(target)) {
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002232 GLuint priorityEnabledBoundTexture =
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002233 m_state->getBoundTexture(
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002234 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D));
2235 GLuint texture2DBoundTexture =
2236 m_state->getBoundTexture(GL_TEXTURE_2D);
2237 if (!priorityEnabledBoundTexture) {
2238 m_glBindTexture_enc(this, GL_TEXTURE_2D, texture2DBoundTexture);
2239 } else {
2240 m_glBindTexture_enc(this, GL_TEXTURE_2D, priorityEnabledBoundTexture);
2241 }
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002242 }
keunyoungb85b2752013-03-08 12:28:03 -08002243}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002244
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002245void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2246 m_state->setBoundEGLImage(target, eglImage);
2247}
2248
2249
2250GLuint GL2Encoder::boundBuffer(GLenum target) const {
2251 return m_state->getBuffer(target);
2252}
2253
2254BufferData* GL2Encoder::getBufferData(GLenum target) const {
2255 GLuint bufferId = m_state->getBuffer(target);
2256 if (!bufferId) return NULL;
2257 return m_shared->getBufferData(bufferId);
2258}
2259
2260BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2261 if (!bufferId) return NULL;
2262 return m_shared->getBufferData(bufferId);
2263}
2264
2265bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2266 return m_shared->getBufferData(buffer)->m_mapped;
2267}
2268
2269bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2270 BufferData* buf = getBufferData(target);
2271 if (!buf) return false;
2272 return buf->m_mapped;
2273}
2274
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002275void GL2Encoder::s_glGenRenderbuffers(void* self,
2276 GLsizei n, GLuint* renderbuffers) {
2277 GL2Encoder* ctx = (GL2Encoder*)self;
2278 GLClientState* state = ctx->m_state;
2279
2280 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2281
2282 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2283 state->addRenderbuffers(n, renderbuffers);
2284}
2285
2286void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2287 GLsizei n, const GLuint* renderbuffers) {
2288 GL2Encoder* ctx = (GL2Encoder*)self;
2289 GLClientState* state = ctx->m_state;
2290
2291 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2292
2293 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002294
2295 // Nope, lets just leak those for now.
2296 // The spec has an *amazingly* convoluted set of conditions for when
2297 // render buffers are actually deleted:
2298 // 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.
2299 //
2300 // 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***
2301 //
2302 // So, just detach this one from the bound FBO, and ignore the rest.
2303 for (int i = 0; i < n; i++) {
2304 state->detachRbo(renderbuffers[i]);
2305 }
2306 // state->removeRenderbuffers(n, renderbuffers);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002307}
2308
2309void GL2Encoder::s_glBindRenderbuffer(void* self,
2310 GLenum target, GLuint renderbuffer) {
2311 GL2Encoder* ctx = (GL2Encoder*)self;
2312 GLClientState* state = ctx->m_state;
2313
2314 SET_ERROR_IF((target != GL_RENDERBUFFER),
2315 GL_INVALID_ENUM);
2316
2317 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2318 state->bindRenderbuffer(target, renderbuffer);
2319}
2320
Lingfeng Yang69066602016-04-12 09:29:11 -07002321void GL2Encoder::s_glRenderbufferStorage(void* self,
2322 GLenum target, GLenum internalformat,
2323 GLsizei width, GLsizei height) {
2324 GL2Encoder* ctx = (GL2Encoder*) self;
2325 GLClientState* state = ctx->m_state;
2326
2327 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002328 SET_ERROR_IF(
2329 !GLESv2Validation::rboFormat(ctx, internalformat),
2330 GL_INVALID_ENUM);
Lingfeng Yang69066602016-04-12 09:29:11 -07002331
2332 state->setBoundRenderbufferFormat(internalformat);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002333 state->setBoundRenderbufferSamples(0);
2334
Lingfeng Yang69066602016-04-12 09:29:11 -07002335 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
2336 width, height);
2337}
2338
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002339void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
2340 GLenum target, GLenum attachment,
2341 GLenum renderbuffertarget, GLuint renderbuffer) {
2342 GL2Encoder* ctx = (GL2Encoder*)self;
2343 GLClientState* state = ctx->m_state;
2344
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002345 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2346 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2347 state->attachRbo(target, attachment, renderbuffer);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002348
2349 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
2350}
2351
2352void GL2Encoder::s_glGenFramebuffers(void* self,
2353 GLsizei n, GLuint* framebuffers) {
2354 GL2Encoder* ctx = (GL2Encoder*)self;
2355 GLClientState* state = ctx->m_state;
2356
2357 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2358
2359 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2360 state->addFramebuffers(n, framebuffers);
2361}
2362
2363void GL2Encoder::s_glDeleteFramebuffers(void* self,
2364 GLsizei n, const GLuint* framebuffers) {
2365 GL2Encoder* ctx = (GL2Encoder*)self;
2366 GLClientState* state = ctx->m_state;
2367
2368 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2369
2370 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2371 state->removeFramebuffers(n, framebuffers);
2372}
2373
2374void GL2Encoder::s_glBindFramebuffer(void* self,
2375 GLenum target, GLuint framebuffer) {
2376 GL2Encoder* ctx = (GL2Encoder*)self;
2377 GLClientState* state = ctx->m_state;
2378
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002379 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002380
2381 state->bindFramebuffer(target, framebuffer);
2382
2383 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
2384}
2385
2386void GL2Encoder::s_glFramebufferTexture2D(void* self,
2387 GLenum target, GLenum attachment,
2388 GLenum textarget, GLuint texture, GLint level) {
2389 GL2Encoder* ctx = (GL2Encoder*)self;
2390 GLClientState* state = ctx->m_state;
2391
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002392 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2393 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2394 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002395
2396 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
2397}
2398
2399void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2400 GLenum target, GLenum attachment,
2401 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2402 GL2Encoder* ctx = (GL2Encoder*)self;
2403 GLClientState* state = ctx->m_state;
2404
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002405 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002406
2407 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2408}
2409
2410void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2411 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2412 GL2Encoder* ctx = (GL2Encoder*)self;
2413 const GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002414 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2415 SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2416 pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE &&
2417 !state->attachmentHasObject(target, attachment),
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002418 GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002419 SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL ||
2420 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE ||
2421 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) &&
2422 (!state->attachmentHasObject(target, attachment) ||
2423 state->getBoundFramebufferAttachmentType(target, attachment) !=
2424 FBO_ATTACHMENT_TEXTURE),
2425 !state->attachmentHasObject(target, attachment) ?
2426 GL_INVALID_OPERATION : GL_INVALID_ENUM);
2427 SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2428 pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2429 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
2430 state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
2431 GL_INVALID_OPERATION);
2432 SET_ERROR_IF(state->boundFramebuffer(target) &&
2433 (attachment == GL_BACK ||
2434 attachment == GL_FRONT),
2435 GL_INVALID_OPERATION);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002436 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
2437}
Lingfeng Yang69066602016-04-12 09:29:11 -07002438
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002439bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state,
Lingfeng Yang69066602016-04-12 09:29:11 -07002440 GLenum attachment) const {
2441 FboFormatInfo fbo_format_info;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002442 state->getBoundFramebufferFormat(target, attachment, &fbo_format_info);
Lingfeng Yang69066602016-04-12 09:29:11 -07002443
2444 bool res;
2445 switch (fbo_format_info.type) {
2446 case FBO_ATTACHMENT_RENDERBUFFER:
2447 switch (fbo_format_info.rb_format) {
2448 case GL_R16F:
2449 case GL_RG16F:
Lingfeng Yang69066602016-04-12 09:29:11 -07002450 case GL_RGBA16F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002451 case GL_R32F:
2452 case GL_RG32F:
2453 case GL_RGBA32F:
2454 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002455 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002456 break;
2457 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002458 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang69066602016-04-12 09:29:11 -07002459 break;
2460 case GL_STENCIL_INDEX8:
2461 if (attachment == GL_STENCIL_ATTACHMENT) {
2462 res = true;
2463 } else {
2464 res = false;
2465 }
2466 break;
2467 default:
2468 res = true;
2469 }
2470 break;
2471 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002472 switch (fbo_format_info.tex_internalformat) {
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002473 case GL_R16F:
2474 case GL_RG16F:
2475 case GL_RGBA16F:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002476 case GL_R32F:
2477 case GL_RG32F:
2478 case GL_RGBA32F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002479 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002480 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002481 break;
2482 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002483 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002484 break;
2485 case GL_RED:
2486 case GL_RG:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002487 case GL_SRGB8:
2488 case GL_RGB32UI:
2489 case GL_RGB16UI:
2490 case GL_RGB8UI:
2491 case GL_RGB32I:
2492 case GL_RGB16I:
2493 case GL_RGB8I:
2494 case GL_R8_SNORM:
2495 case GL_RG8_SNORM:
2496 case GL_RGB8_SNORM:
2497 case GL_RGBA8_SNORM:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002498 res = false;
2499 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07002500 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002501 case GL_RGB:
2502 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07002503 switch (fbo_format_info.tex_type) {
2504 case GL_FLOAT:
2505 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002506 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002507 case GL_UNSIGNED_INT_2_10_10_10_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07002508 res = false;
2509 break;
2510 default:
2511 res = true;
2512 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002513 break;
2514 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07002515 res = true;
2516 }
2517 break;
2518 case FBO_ATTACHMENT_NONE:
2519 res = true;
2520 break;
2521 default:
2522 res = true;
2523 }
2524 return res;
2525}
2526
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002527bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const {
2528 bool res = true;
2529
2530 for (int i = 0; i < state->getMaxColorAttachments(); i++) {
2531 res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i));
2532 }
2533
2534 res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT);
2535 res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT);
2536
2537 return res;
2538}
2539
Lingfeng Yang69066602016-04-12 09:29:11 -07002540GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
2541 GL2Encoder* ctx = (GL2Encoder*)self;
2542 GLClientState* state = ctx->m_state;
2543
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002544 bool fboCompleteByCodec =
2545 ctx->checkFramebufferCompleteness(target, state);
2546
2547 if (!fboCompleteByCodec) {
2548 state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
Lingfeng Yang69066602016-04-12 09:29:11 -07002549 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2550 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002551 // double check with underlying opengl to avoid craziness.
Lingfeng Yang69066602016-04-12 09:29:11 -07002552 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002553 state->setCheckFramebufferStatus(target, host_checkstatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002554 if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE;
Lingfeng Yang69066602016-04-12 09:29:11 -07002555 return host_checkstatus;
2556 }
2557}
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002558
2559void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2560 GL2Encoder* ctx = (GL2Encoder*)self;
2561 GLClientState* state = ctx->m_state;
2562 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2563
2564 ctx->m_glGenVertexArrays_enc(self, n, arrays);
2565 for (int i = 0; i < n; i++) {
2566 ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2567 }
2568 state->addVertexArrayObjects(n, arrays);
2569}
2570
2571void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2572 GL2Encoder* ctx = (GL2Encoder*)self;
2573 GLClientState* state = ctx->m_state;
2574 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2575
2576 ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2577 for (int i = 0; i < n; i++) {
2578 ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2579 }
2580 state->removeVertexArrayObjects(n, arrays);
2581}
2582
2583void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2584 ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2585 GL2Encoder* ctx = (GL2Encoder*)self;
2586 GLClientState* state = ctx->m_state;
2587 SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2588 ctx->m_glBindVertexArray_enc(self, array);
2589 state->setVertexArrayObject(array);
2590}
2591
Lingfeng Yangfb3d2bb2017-09-07 15:02:04 -07002592void* GL2Encoder::s_glMapBufferOES(void* self, GLenum target, GLenum access) {
2593 GL2Encoder* ctx = (GL2Encoder*)self;
2594
2595 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2596
2597 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2598
2599 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2600
2601 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2602 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2603
2604 return ctx->glMapBufferRange(ctx, target, 0, buf->m_size, access);
2605}
2606
2607GLboolean GL2Encoder::s_glUnmapBufferOES(void* self, GLenum target) {
2608 GL2Encoder* ctx = (GL2Encoder*)self;
2609
2610 return ctx->glUnmapBuffer(ctx, target);
2611}
2612
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002613void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2614 GL2Encoder* ctx = (GL2Encoder*)self;
2615 GLClientState* state = ctx->m_state;
2616
2617 // begin validation (lots)
2618
2619 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2620
2621 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2622
2623 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2624
2625 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2626 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2627
2628 GLsizeiptr bufferDataSize = buf->m_size;
2629
2630 RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2631 RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2632 RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2633 RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2634
2635 RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2636 RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2637 RET_AND_SET_ERROR_IF(
2638 (access & GL_MAP_READ_BIT) &&
2639 ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2640 (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2641 (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2642 (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2643
2644 // end validation; actually do stuff now
2645
2646 buf->m_mapped = true;
2647 buf->m_mappedAccess = access;
2648 buf->m_mappedOffset = offset;
2649 buf->m_mappedLength = length;
2650
2651 char* todo = (char*)buf->m_fixedBuffer.ptr() + offset;
2652 ctx->glMapBufferRangeAEMU(
2653 ctx, target,
2654 offset, length,
2655 access,
2656 todo);
2657
2658 return todo;
2659}
2660
2661GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
2662 GL2Encoder* ctx = (GL2Encoder*)self;
2663 GLClientState* state = ctx->m_state;
2664
2665 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
2666
2667 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2668
2669 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
2670
2671 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2672 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
2673 RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
2674
Lingfeng Yang423129e2017-01-18 09:23:12 -08002675 if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
2676 // invalide index range cache here
2677 if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) {
2678 buf->m_indexRangeCache.invalidateRange(0, buf->m_size);
2679 } else {
2680 buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength);
2681 }
2682 }
2683
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002684 GLboolean host_res = GL_TRUE;
2685
2686 ctx->glUnmapBufferAEMU(
2687 ctx, target,
2688 buf->m_mappedOffset,
2689 buf->m_mappedLength,
2690 buf->m_mappedAccess,
2691 (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
2692 &host_res);
2693
2694 buf->m_mapped = false;
2695 buf->m_mappedAccess = 0;
2696 buf->m_mappedOffset = 0;
2697 buf->m_mappedLength = 0;
2698
2699 return host_res;
2700}
2701
2702void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
2703 GL2Encoder* ctx = (GL2Encoder*)self;
2704 GLClientState* state = ctx->m_state;
2705
2706 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2707
2708 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2709 SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
2710
2711 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2712 SET_ERROR_IF(!buf, GL_INVALID_VALUE);
2713 SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
2714 SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
2715
2716 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
2717 SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
2718 SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
2719
2720 GLintptr totalOffset = buf->m_mappedOffset + offset;
Lingfeng Yang423129e2017-01-18 09:23:12 -08002721
2722 buf->m_indexRangeCache.invalidateRange(totalOffset, length);
2723
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002724 ctx->glFlushMappedBufferRangeAEMU(
2725 ctx, target,
2726 totalOffset,
2727 length,
2728 buf->m_mappedAccess,
2729 (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
2730}
2731
2732void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
2733 GL2Encoder* ctx = (GL2Encoder*)self;
2734 GLClientState* state = ctx->m_state;
2735
2736 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2737 // Filter compressed formats support.
2738 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
2739 // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
2740 GLint max_texture_size;
2741 GLint max_cube_map_texture_size;
2742 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2743 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2744 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2745 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2746 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2747 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2748 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2749 SET_ERROR_IF(border, GL_INVALID_VALUE);
2750 // If unpack buffer is nonzero, verify unmapped state.
2751 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2752 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2753 // If unpack buffer is nonzero, verify buffer data fits.
2754 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2755 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2756 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2757 GL_INVALID_OPERATION);
2758 // TODO: Fix:
2759 // If |imageSize| is inconsistent with compressed dimensions.
2760 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
2761
2762 GLenum stateTarget = target;
2763 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2764 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2765 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2766 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2767 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2768 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2769 stateTarget = GL_TEXTURE_CUBE_MAP;
2770 state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
2771 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2772
2773 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2774 ctx->glCompressedTexImage2DOffsetAEMU(
2775 ctx, target, level, internalformat,
2776 width, height, border,
2777 imageSize, (uintptr_t)data);
2778 } else {
2779 ctx->m_glCompressedTexImage2D_enc(
2780 ctx, target, level, internalformat,
2781 width, height, border,
2782 imageSize, data);
2783 }
2784}
2785
2786void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
2787 GL2Encoder* ctx = (GL2Encoder*)self;
2788 GLClientState* state = ctx->m_state;
2789
2790 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2791 // If unpack buffer is nonzero, verify unmapped state.
2792 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2793 GLint max_texture_size;
2794 GLint max_cube_map_texture_size;
2795 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2796 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2797 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2798 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2799 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2800 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2801 // If unpack buffer is nonzero, verify buffer data fits.
2802 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2803 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2804 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2805 GL_INVALID_OPERATION);
2806 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2807
2808 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2809 ctx->glCompressedTexSubImage2DOffsetAEMU(
2810 ctx, target, level,
2811 xoffset, yoffset,
2812 width, height, format,
2813 imageSize, (uintptr_t)data);
2814 } else {
2815 ctx->m_glCompressedTexSubImage2D_enc(
2816 ctx, target, level,
2817 xoffset, yoffset,
2818 width, height, format,
2819 imageSize, data);
2820 }
2821}
2822
2823void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
2824 GL2Encoder* ctx = (GL2Encoder*)self;
2825 GLClientState* state = ctx->m_state;
2826
2827 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2828
2829 // Only works with certain targets
2830 SET_ERROR_IF(
2831 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2832 target == GL_SHADER_STORAGE_BUFFER ||
2833 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2834 target == GL_UNIFORM_BUFFER),
2835 GL_INVALID_ENUM);
2836
2837 // Can't exceed range
2838 SET_ERROR_IF(index < 0 ||
2839 index >= state->getMaxIndexedBufferBindings(target),
2840 GL_INVALID_VALUE);
2841 SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
2842 SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
2843 target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
2844 (size % 4 || offset % 4),
2845 GL_INVALID_VALUE);
2846
2847 GLint ssbo_offset_align, ubo_offset_align;
2848 ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
2849 ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
2850 SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
2851 offset % ssbo_offset_align,
2852 GL_INVALID_VALUE);
2853 SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
2854 offset % ubo_offset_align,
2855 GL_INVALID_VALUE);
2856
2857 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002858 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002859 state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0);
2860 ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size);
2861}
2862
2863void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
2864 GL2Encoder* ctx = (GL2Encoder*)self;
2865 GLClientState* state = ctx->m_state;
2866
2867 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2868
2869 // Only works with certain targets
2870 SET_ERROR_IF(
2871 !(target == GL_ATOMIC_COUNTER_BUFFER ||
2872 target == GL_SHADER_STORAGE_BUFFER ||
2873 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
2874 target == GL_UNIFORM_BUFFER),
2875 GL_INVALID_ENUM);
2876 // Can't exceed range
2877 SET_ERROR_IF(index < 0 ||
2878 index >= state->getMaxIndexedBufferBindings(target),
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 BufferData* buf = ctx->getBufferDataById(buffer);
2884 state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0);
2885 ctx->m_glBindBufferBase_enc(self, target, index, buffer);
2886}
2887
2888void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
2889 GL2Encoder* ctx = (GL2Encoder*)self;
2890 GLClientState* state = ctx->m_state;
2891
2892 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
2893 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
2894 SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
2895 readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
2896 readtarget == GL_DRAW_INDIRECT_BUFFER ||
2897 readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2898 SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
2899 writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
2900 writetarget == GL_DRAW_INDIRECT_BUFFER ||
2901 writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
2902 SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
2903 SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
2904 SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
2905 SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
2906 SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
2907 SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
2908 SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
2909 SET_ERROR_IF(
2910 ctx->getBufferData(readtarget) &&
2911 (readoffset + size > ctx->getBufferData(readtarget)->m_size),
2912 GL_INVALID_VALUE);
2913 SET_ERROR_IF(
2914 ctx->getBufferData(writetarget) &&
2915 (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
2916 GL_INVALID_VALUE);
2917 SET_ERROR_IF(readtarget == writetarget &&
2918 !((writeoffset >= readoffset + size) ||
2919 (readoffset >= writeoffset + size)),
2920 GL_INVALID_VALUE);
2921
2922 ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
2923}
2924
2925void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
2926 GL2Encoder* ctx = (GL2Encoder*)self;
2927
2928 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2929 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002930 target != GL_ARRAY_BUFFER &&
2931 target != GL_ELEMENT_ARRAY_BUFFER &&
2932 target != GL_COPY_READ_BUFFER &&
2933 target != GL_COPY_WRITE_BUFFER &&
2934 target != GL_PIXEL_PACK_BUFFER &&
2935 target != GL_PIXEL_UNPACK_BUFFER &&
2936 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
2937 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002938 GL_INVALID_ENUM);
2939 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
2940 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002941 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
2942 pname != GL_BUFFER_MAPPED &&
2943 pname != GL_BUFFER_SIZE &&
2944 pname != GL_BUFFER_USAGE &&
2945 pname != GL_BUFFER_MAP_LENGTH &&
2946 pname != GL_BUFFER_MAP_OFFSET,
2947 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002948
2949 if (!params) return;
2950
2951 BufferData* buf = ctx->getBufferData(target);
2952
2953 switch (pname) {
2954 case GL_BUFFER_ACCESS_FLAGS:
2955 *params = buf ? buf->m_mappedAccess : 0;
2956 break;
2957 case GL_BUFFER_MAPPED:
2958 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
2959 break;
2960 case GL_BUFFER_SIZE:
2961 *params = buf ? buf->m_size : 0;
2962 break;
2963 case GL_BUFFER_USAGE:
2964 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
2965 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002966 case GL_BUFFER_MAP_LENGTH:
2967 *params = buf ? buf->m_mappedLength : 0;
2968 break;
2969 case GL_BUFFER_MAP_OFFSET:
2970 *params = buf ? buf->m_mappedOffset : 0;
2971 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002972 default:
2973 break;
2974 }
2975}
2976
2977void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
2978 GL2Encoder* ctx = (GL2Encoder*)self;
2979
2980 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
2981 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002982 target != GL_ARRAY_BUFFER &&
2983 target != GL_ELEMENT_ARRAY_BUFFER &&
2984 target != GL_COPY_READ_BUFFER &&
2985 target != GL_COPY_WRITE_BUFFER &&
2986 target != GL_PIXEL_PACK_BUFFER &&
2987 target != GL_PIXEL_UNPACK_BUFFER &&
2988 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
2989 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002990 GL_INVALID_ENUM);
2991 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
2992 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002993 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
2994 pname != GL_BUFFER_MAPPED &&
2995 pname != GL_BUFFER_SIZE &&
2996 pname != GL_BUFFER_USAGE &&
2997 pname != GL_BUFFER_MAP_LENGTH &&
2998 pname != GL_BUFFER_MAP_OFFSET,
2999 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003000
3001 if (!params) return;
3002
3003 BufferData* buf = ctx->getBufferData(target);
3004
3005 switch (pname) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003006 case GL_BUFFER_ACCESS_FLAGS:
3007 *params = buf ? buf->m_mappedAccess : 0;
3008 break;
3009 case GL_BUFFER_MAPPED:
3010 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3011 break;
3012 case GL_BUFFER_SIZE:
3013 *params = buf ? buf->m_size : 0;
3014 break;
3015 case GL_BUFFER_USAGE:
3016 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3017 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003018 case GL_BUFFER_MAP_LENGTH:
3019 *params = buf ? buf->m_mappedLength : 0;
3020 break;
3021 case GL_BUFFER_MAP_OFFSET:
3022 *params = buf ? buf->m_mappedOffset : 0;
3023 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003024 default:
3025 break;
3026 }
3027}
3028
3029void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
3030 GL2Encoder* ctx = (GL2Encoder*)self;
3031 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3032 SET_ERROR_IF(
3033 target == GL_ATOMIC_COUNTER_BUFFER ||
3034 target == GL_DISPATCH_INDIRECT_BUFFER ||
3035 target == GL_DRAW_INDIRECT_BUFFER ||
3036 target == GL_SHADER_STORAGE_BUFFER,
3037 GL_INVALID_ENUM);
3038 SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
3039 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
3040 if (!params) return;
3041
3042 BufferData* buf = ctx->getBufferData(target);
3043
3044 if (!buf || !buf->m_mapped) { *params = NULL; return; }
3045
3046 *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
3047}
3048
3049static const char* const kNameDelimiter = ";";
3050
3051static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
3052
3053#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
3054
3055 std::string packed;
3056 // validate the array of char[]'s
3057 const char* currName;
3058 for (GLsizei i = 0; i < count; i++) {
3059 currName = names[i];
3060 VALIDATE(!currName, GL_INVALID_OPERATION);
3061 // check if has reasonable size
3062 size_t len = strlen(currName);
3063 VALIDATE(!len, GL_INVALID_OPERATION);
3064 // check for our delimiter, which if present
3065 // in the name, means an invalid name anyway.
3066 VALIDATE(strstr(currName, kNameDelimiter),
3067 GL_INVALID_OPERATION);
3068 packed += currName;
3069 packed += ";";
3070 }
3071
3072 *err_out = GL_NO_ERROR;
3073 return packed;
3074}
3075
3076void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
3077 GL2Encoder* ctx = (GL2Encoder*)self;
3078
3079 if (!uniformCount) return;
3080
3081 GLint err = GL_NO_ERROR;
3082 std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
3083 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3084
3085 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
3086 std::vector<int> arrIndices;
3087 for (size_t i = 0; i < uniformCount; i++) {
3088 int err;
3089 arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
3090 if (err) {
3091 ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
3092 return;
3093 }
3094 }
3095
3096 ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
3097
3098 for (int i = 0; i < uniformCount; i++) {
3099 if (uniformIndices[i] >= 0 && needLocationWAR) {
3100 uniformIndices[i] =
3101 ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
3102 }
3103 }
3104}
3105
3106void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
3107 GL2Encoder *ctx = (GL2Encoder*)self;
3108 GLClientState* state = ctx->m_state;
3109 GLSharedGroupPtr shared = ctx->m_shared;
3110
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003111 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003112 ctx->m_glUniform1ui_enc(self, hostLoc, v0);
3113
3114 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003115 if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003116 GLenum origActiveTexture = state->getActiveTextureUnit();
3117 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
3118 ctx->m_glActiveTexture_enc(self, origActiveTexture);
3119 }
3120 state->setActiveTextureUnit(origActiveTexture);
3121 }
3122}
3123
3124void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) {
3125 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003126 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003127 ctx->m_glUniform2ui_enc(self, hostLoc, v0, v1);
3128}
3129
3130void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) {
3131 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003132 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003133 ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2);
3134}
3135
3136void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) {
3137 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003138 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003139 ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3);
3140}
3141
3142void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3143 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003144 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003145 ctx->m_glUniform1uiv_enc(self, hostLoc, count, value);
3146}
3147
3148void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
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_glUniform2uiv_enc(self, hostLoc, count, value);
3152}
3153
3154void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
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_glUniform3uiv_enc(self, hostLoc, count, value);
3158}
3159
3160void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
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_glUniform4uiv_enc(self, hostLoc, count, value);
3164}
3165
3166void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *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_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value);
3170}
3171
3172void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *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_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value);
3176}
3177
3178void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *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_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value);
3182}
3183
3184void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *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_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value);
3188}
3189
3190void GL2Encoder::s_glUniformMatrix3x4fv(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_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value);
3194}
3195
3196void GL2Encoder::s_glUniformMatrix4x3fv(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_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value);
3200}
3201
3202void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3203 GL2Encoder *ctx = (GL2Encoder*)self;
3204 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3205 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3206 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3207 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3208 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3209 ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3210}
3211
3212void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3213 GL2Encoder* ctx = (GL2Encoder*)self;
3214 GLClientState* state = ctx->m_state;
3215
3216 // refresh client state's # active uniforms in this block
3217 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3218 // TODO if worth it: cache uniform count and other params,
3219 // invalidate on program relinking.
3220 GLint numActiveUniforms;
3221 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3222 program, uniformBlockIndex,
3223 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3224 &numActiveUniforms);
3225 ctx->m_state->setNumActiveUniformsInUniformBlock(
3226 program, uniformBlockIndex, numActiveUniforms);
3227 }
3228
3229 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3230 program, uniformBlockIndex,
3231 pname, params);
3232}
3233
3234void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3235 GL2Encoder *ctx = (GL2Encoder *)self;
3236 assert(ctx->m_state);
3237 GLint maxIndex;
3238 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3239 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3240
3241 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3242 ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3243 }
3244}
3245
3246void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3247 GL2Encoder *ctx = (GL2Encoder *)self;
3248 assert(ctx->m_state);
3249 GLint maxIndex;
3250 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3251 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3252
3253 if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3254 ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3255 }
3256}
3257
3258void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3259 GL2Encoder *ctx = (GL2Encoder *)self;
3260 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003261 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003262 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
3263 SET_ERROR_IF(
3264 !(type == GL_BYTE ||
3265 type == GL_UNSIGNED_BYTE ||
3266 type == GL_SHORT ||
3267 type == GL_UNSIGNED_SHORT ||
3268 type == GL_INT ||
3269 type == GL_UNSIGNED_INT),
3270 GL_INVALID_ENUM);
3271 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
3272
3273 ctx->m_state->setVertexAttribBinding(index, index);
3274 ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true);
3275 GLsizei effectiveStride = stride;
3276 if (stride == 0) {
3277 effectiveStride = glSizeof(type) * size;
3278 }
3279 ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride);
3280
3281 if (ctx->m_state->currentArrayVbo() != 0) {
3282 ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer);
3283 } else {
3284 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION);
3285 // wait for client-array handler
3286 }
3287}
3288
3289void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) {
3290 GL2Encoder *ctx = (GL2Encoder *)self;
3291 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003292 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003293 ctx->m_state->setVertexAttribBinding(index, index);
3294 ctx->m_state->setVertexBindingDivisor(index, divisor);
3295 ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor);
3296}
3297
3298void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3299 GLenum target, GLsizei samples, GLenum internalformat,
3300 GLsizei width, GLsizei height) {
3301 GL2Encoder *ctx = (GL2Encoder *)self;
3302 GLClientState* state = ctx->m_state;
3303
3304 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3305 SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3306
3307 GLint max_samples;
3308 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3309 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3310
3311 state->setBoundRenderbufferFormat(internalformat);
3312 state->setBoundRenderbufferSamples(samples);
3313 ctx->m_glRenderbufferStorageMultisample_enc(
3314 self, target, samples, internalformat, width, height);
3315}
3316
3317void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3318 GL2Encoder* ctx = (GL2Encoder*)self;
3319 SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3320 SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3321 for (int i = 0; i < n; i++) {
3322 SET_ERROR_IF(
3323 bufs[i] != GL_NONE &&
3324 bufs[i] != GL_BACK &&
3325 glUtilsColorAttachmentIndex(bufs[i]) == -1,
3326 GL_INVALID_ENUM);
3327 SET_ERROR_IF(
3328 !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3329 glUtilsColorAttachmentIndex(bufs[i]) != -1,
3330 GL_INVALID_OPERATION);
3331 SET_ERROR_IF(
3332 ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3333 ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3334 glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3335 (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3336 bufs[i] != GL_NONE)),
3337 GL_INVALID_OPERATION);
3338 }
3339
3340 ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3341}
3342
3343void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3344 GL2Encoder* ctx = (GL2Encoder*)self;
3345
3346 SET_ERROR_IF(
3347 glUtilsColorAttachmentIndex(src) != -1 &&
3348 (glUtilsColorAttachmentIndex(src) >=
3349 ctx->m_state->getMaxColorAttachments()),
3350 GL_INVALID_OPERATION);
3351 SET_ERROR_IF(
3352 src != GL_NONE &&
3353 src != GL_BACK &&
3354 src > GL_COLOR_ATTACHMENT0 &&
3355 src < GL_DEPTH_ATTACHMENT &&
3356 (src - GL_COLOR_ATTACHMENT0) >
3357 ctx->m_state->getMaxColorAttachments(),
3358 GL_INVALID_OPERATION);
3359 SET_ERROR_IF(
3360 src != GL_NONE &&
3361 src != GL_BACK &&
3362 glUtilsColorAttachmentIndex(src) == -1,
3363 GL_INVALID_ENUM);
3364 SET_ERROR_IF(
3365 !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3366 src != GL_NONE &&
3367 src != GL_BACK,
3368 GL_INVALID_OPERATION);
3369 SET_ERROR_IF(
3370 ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3371 src != GL_NONE &&
3372 glUtilsColorAttachmentIndex(src) == -1,
3373 GL_INVALID_OPERATION);
3374
3375 ctx->m_glReadBuffer_enc(ctx, src);
3376}
3377
3378void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3379 GL2Encoder* ctx = (GL2Encoder*)self;
3380 GLClientState* state = ctx->m_state;
3381
3382 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3383 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3384 GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3385 SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3386 lastBoundTarget != GL_TEXTURE_3D,
3387 GL_INVALID_OPERATION);
3388 state->attachTextureObject(target, attachment, texture);
3389
3390 GLint max3DTextureSize;
3391 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3392 SET_ERROR_IF(
3393 layer >= max3DTextureSize,
3394 GL_INVALID_VALUE);
3395
3396 ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3397}
3398
3399void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3400 GL2Encoder* ctx = (GL2Encoder*)self;
3401 GLClientState* state = ctx->m_state;
3402
3403 SET_ERROR_IF(
3404 target != GL_TEXTURE_2D &&
3405 target != GL_TEXTURE_CUBE_MAP,
3406 GL_INVALID_ENUM);
3407 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3408 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3409 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3410 SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3411 GL_INVALID_OPERATION);
3412 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3413
3414 state->setBoundTextureInternalFormat(target, internalformat);
3415 state->setBoundTextureDims(target, -1, width, height, 1);
3416 state->setBoundTextureImmutableFormat(target);
3417 ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
3418}
3419
3420void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3421 GL2Encoder* ctx = (GL2Encoder*)self;
3422
3423 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3424
3425 GLint maxCount = 0;
3426 ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3427
3428 SET_ERROR_IF(
3429 bufferMode == GL_SEPARATE_ATTRIBS &&
3430 maxCount < count,
3431 GL_INVALID_VALUE);
3432 SET_ERROR_IF(
3433 bufferMode != GL_INTERLEAVED_ATTRIBS &&
3434 bufferMode != GL_SEPARATE_ATTRIBS,
3435 GL_INVALID_ENUM);
3436
3437 if (!count) return;
3438
3439 GLint err = GL_NO_ERROR;
3440 std::string packed = packVarNames(count, varyings, &err);
3441 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3442
3443 ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3444}
3445
3446void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3447 GL2Encoder* ctx = (GL2Encoder*)self;
3448 GLClientState* state = ctx->m_state;
3449 ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3450 state->setTransformFeedbackActiveUnpaused(true);
3451}
3452
3453void GL2Encoder::s_glEndTransformFeedback(void* self) {
3454 GL2Encoder* ctx = (GL2Encoder*)self;
3455 GLClientState* state = ctx->m_state;
3456 ctx->m_glEndTransformFeedback_enc(ctx);
3457 state->setTransformFeedbackActiveUnpaused(false);
3458}
3459
3460void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3461 GL2Encoder* ctx = (GL2Encoder*)self;
3462 GLClientState* state = ctx->m_state;
3463 ctx->m_glPauseTransformFeedback_enc(ctx);
3464 state->setTransformFeedbackActiveUnpaused(false);
3465}
3466
3467void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3468 GL2Encoder* ctx = (GL2Encoder*)self;
3469 GLClientState* state = ctx->m_state;
3470 ctx->m_glResumeTransformFeedback_enc(ctx);
3471 state->setTransformFeedbackActiveUnpaused(true);
3472}
3473
3474void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3475 GLsizei width, GLsizei height, GLsizei depth,
3476 GLint border, GLenum format, GLenum type, const GLvoid* data) {
3477 GL2Encoder* ctx = (GL2Encoder*)self;
3478 GLClientState* state = ctx->m_state;
3479
3480 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3481 target != GL_TEXTURE_2D_ARRAY,
3482 GL_INVALID_ENUM);
3483 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3484 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3485
3486 // If unpack buffer is nonzero, verify unmapped state.
3487 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3488
3489 GLint max_texture_size;
3490 GLint max_3d_texture_size;
3491 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3492 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3493 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3494 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3495 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3496
3497 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3498 SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3499 SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3500 SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3501 SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3502 SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3503 SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3504 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3505 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3506 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3507 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3508 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3509 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3510 GL_INVALID_OPERATION);
3511 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3512 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3513 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3514 glSizeof(type)),
3515 GL_INVALID_OPERATION);
3516 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3517
3518 state->setBoundTextureInternalFormat(target, internalFormat);
3519 state->setBoundTextureFormat(target, format);
3520 state->setBoundTextureType(target, type);
3521 state->setBoundTextureDims(target, level, width, height, depth);
3522
3523 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3524 ctx->glTexImage3DOffsetAEMU(
3525 ctx, target, level, internalFormat,
3526 width, height, depth,
3527 border, format, type, (uintptr_t)data);
3528 } else {
3529 ctx->m_glTexImage3D_enc(ctx,
3530 target, level, internalFormat,
3531 width, height, depth,
3532 border, format, type, data);
3533 }
3534}
3535
3536void 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) {
3537 GL2Encoder* ctx = (GL2Encoder*)self;
3538 GLClientState* state = ctx->m_state;
3539
3540 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3541 target != GL_TEXTURE_2D_ARRAY,
3542 GL_INVALID_ENUM);
3543 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3544 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3545 // If unpack buffer is nonzero, verify unmapped state.
3546 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3547 GLint max_texture_size;
3548 GLint max_3d_texture_size;
3549 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3550 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3551 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3552 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3553 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3554 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3555 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3556 GLuint tex = state->getBoundTexture(target);
3557 GLsizei neededWidth = xoffset + width;
3558 GLsizei neededHeight = yoffset + height;
3559 GLsizei neededDepth = zoffset + depth;
3560
3561 SET_ERROR_IF(tex &&
3562 (neededWidth > state->queryTexWidth(level, tex) ||
3563 neededHeight > state->queryTexHeight(level, tex) ||
3564 neededDepth > state->queryTexDepth(level, tex)),
3565 GL_INVALID_VALUE);
3566 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3567 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3568 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3569 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3570 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3571 GL_INVALID_OPERATION);
3572 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3573 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3574 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3575 glSizeof(type)),
3576 GL_INVALID_OPERATION);
3577 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
3578 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3579
3580 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3581 ctx->glTexSubImage3DOffsetAEMU(ctx,
3582 target, level,
3583 xoffset, yoffset, zoffset,
3584 width, height, depth,
3585 format, type, (uintptr_t)data);
3586 } else {
3587 ctx->m_glTexSubImage3D_enc(ctx,
3588 target, level,
3589 xoffset, yoffset, zoffset,
3590 width, height, depth,
3591 format, type, data);
3592 }
3593}
3594
3595void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
3596 GL2Encoder* ctx = (GL2Encoder*)self;
3597 GLClientState* state = ctx->m_state;
3598
3599 // Filter compressed formats support.
3600 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3601 // If unpack buffer is nonzero, verify unmapped state.
3602 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3603 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3604 SET_ERROR_IF(border, GL_INVALID_VALUE);
3605 // If unpack buffer is nonzero, verify buffer data fits.
3606 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3607 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3608 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3609 GL_INVALID_OPERATION);
3610 // TODO: Fix:
3611 // If |imageSize| is too small for compressed dimensions.
3612 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
3613 state->setBoundTextureInternalFormat(target, (GLint)internalformat);
3614 state->setBoundTextureDims(target, level, width, height, depth);
3615
3616 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3617 ctx->glCompressedTexImage3DOffsetAEMU(
3618 ctx, target, level, internalformat,
3619 width, height, depth, border,
3620 imageSize, (uintptr_t)data);
3621 } else {
3622 ctx->m_glCompressedTexImage3D_enc(
3623 ctx, target, level, internalformat,
3624 width, height, depth, border,
3625 imageSize, data);
3626 }
3627}
3628
3629void 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) {
3630 GL2Encoder* ctx = (GL2Encoder*)self;
3631 GLClientState* state = ctx->m_state;
3632
3633 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), 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 // If unpack buffer is nonzero, verify buffer data fits.
3638 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3639 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3640 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3641 GL_INVALID_OPERATION);
3642 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3643
3644 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3645 ctx->glCompressedTexSubImage3DOffsetAEMU(
3646 ctx, target, level,
3647 xoffset, yoffset, zoffset,
3648 width, height, depth,
3649 format, imageSize, (uintptr_t)data);
3650 } else {
3651 ctx->m_glCompressedTexSubImage3D_enc(
3652 ctx, target, level,
3653 xoffset, yoffset, zoffset,
3654 width, height, depth,
3655 format, imageSize, data);
3656
3657 }
3658}
3659
3660void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
3661 GL2Encoder* ctx = (GL2Encoder*)self;
3662 GLClientState* state = ctx->m_state;
3663 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3664 target != GL_TEXTURE_2D_ARRAY,
3665 GL_INVALID_ENUM);
3666 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3667 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3668 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3669 SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
3670 GL_INVALID_OPERATION);
3671 SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
3672 GL_INVALID_OPERATION);
3673 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3674
3675 state->setBoundTextureInternalFormat(target, internalformat);
3676 state->setBoundTextureDims(target, -1, width, height, depth);
3677 state->setBoundTextureImmutableFormat(target);
3678 ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
3679 state->setBoundTextureImmutableFormat(target);
3680}
3681
3682void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
3683 GL2Encoder *ctx = (GL2Encoder *)self;
3684 assert(ctx->m_state != NULL);
3685 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3686 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3687
3688 bool has_client_vertex_arrays = false;
3689 bool has_indirect_arrays = false;
3690 ctx->getVBOUsage(&has_client_vertex_arrays,
3691 &has_indirect_arrays);
3692
3693 if (has_client_vertex_arrays ||
3694 (!has_client_vertex_arrays &&
3695 !has_indirect_arrays)) {
3696 ctx->sendVertexAttributes(first, count, true, primcount);
3697 ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
3698 } else {
3699 ctx->sendVertexAttributes(0, count, false, primcount);
3700 ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
3701 }
3702 ctx->m_stream->flush();
3703}
3704
3705void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
3706{
3707
3708 GL2Encoder *ctx = (GL2Encoder *)self;
3709 assert(ctx->m_state != NULL);
3710 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3711 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3712 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3713 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3714
3715 bool has_client_vertex_arrays = false;
3716 bool has_indirect_arrays = false;
3717 int nLocations = ctx->m_state->nLocations();
3718 GLintptr offset = 0;
3719
3720 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3721
3722 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3723 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3724 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3725 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3726 }
3727
3728 BufferData* buf = NULL;
3729 int minIndex = 0, maxIndex = 0;
3730
3731 // For validation/immediate index array purposes,
3732 // we need the min/max vertex index of the index array.
3733 // If the VBO != 0, this may not be the first time we have
3734 // used this particular index buffer. getBufferIndexRange
3735 // can more quickly get min/max vertex index by
3736 // caching previous results.
3737 if (ctx->m_state->currentIndexVbo() != 0) {
3738 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3739 offset = (GLintptr)indices;
3740 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3741 ctx->getBufferIndexRange(buf,
3742 indices,
3743 type,
3744 (size_t)count,
3745 (size_t)offset,
3746 &minIndex, &maxIndex);
3747 } else {
3748 // In this case, the |indices| field holds a real
3749 // array, so calculate the indices now. They will
3750 // also be needed to know how much data to
3751 // transfer to host.
3752 ctx->calcIndexRange(indices,
3753 type,
3754 count,
3755 &minIndex,
3756 &maxIndex);
3757 }
3758
3759 bool adjustIndices = true;
3760 if (ctx->m_state->currentIndexVbo() != 0) {
3761 if (!has_client_vertex_arrays) {
3762 ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
3763 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3764 ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
3765 ctx->flushDrawCall();
3766 adjustIndices = false;
3767 } else {
3768 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3769 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3770 }
3771 }
3772 if (adjustIndices) {
3773 void *adjustedIndices =
3774 ctx->recenterIndices(indices,
3775 type,
3776 count,
3777 minIndex);
3778
3779 if (has_indirect_arrays || 1) {
3780 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
3781 ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
3782 ctx->m_stream->flush();
3783 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3784 if(!has_indirect_arrays) {
3785 //ALOGD("unoptimized drawelements !!!\n");
3786 }
3787 } else {
3788 // we are all direct arrays and immidate mode index array -
3789 // rebuild the arrays and the index array;
3790 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3791 }
3792 }
3793}
3794
3795void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
3796{
3797
3798 GL2Encoder *ctx = (GL2Encoder *)self;
3799 assert(ctx->m_state != NULL);
3800 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
3801 SET_ERROR_IF(end < start, GL_INVALID_VALUE);
3802 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
3803 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
3804 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
3805
3806 bool has_client_vertex_arrays = false;
3807 bool has_indirect_arrays = false;
3808 int nLocations = ctx->m_state->nLocations();
3809 GLintptr offset = 0;
3810
3811 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
3812
3813 if (!has_client_vertex_arrays && !has_indirect_arrays) {
3814 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
3815 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
3816 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
3817 }
3818
3819 BufferData* buf = NULL;
3820 int minIndex = 0, maxIndex = 0;
3821
3822 // For validation/immediate index array purposes,
3823 // we need the min/max vertex index of the index array.
3824 // If the VBO != 0, this may not be the first time we have
3825 // used this particular index buffer. getBufferIndexRange
3826 // can more quickly get min/max vertex index by
3827 // caching previous results.
3828 if (ctx->m_state->currentIndexVbo() != 0) {
3829 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3830 offset = (GLintptr)indices;
3831 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
3832 ctx->getBufferIndexRange(buf,
3833 indices,
3834 type,
3835 (size_t)count,
3836 (size_t)offset,
3837 &minIndex, &maxIndex);
3838 } else {
3839 // In this case, the |indices| field holds a real
3840 // array, so calculate the indices now. They will
3841 // also be needed to know how much data to
3842 // transfer to host.
3843 ctx->calcIndexRange(indices,
3844 type,
3845 count,
3846 &minIndex,
3847 &maxIndex);
3848 }
3849
3850 bool adjustIndices = true;
3851 if (ctx->m_state->currentIndexVbo() != 0) {
3852 if (!has_client_vertex_arrays) {
3853 ctx->sendVertexAttributes(0, maxIndex + 1, false);
3854 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
3855 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
3856 ctx->flushDrawCall();
3857 adjustIndices = false;
3858 } else {
3859 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
3860 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
3861 }
3862 }
3863 if (adjustIndices) {
3864 void *adjustedIndices =
3865 ctx->recenterIndices(indices,
3866 type,
3867 count,
3868 minIndex);
3869
3870 if (has_indirect_arrays || 1) {
3871 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
3872 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
3873 ctx->m_stream->flush();
3874 // XXX - OPTIMIZATION (see the other else branch) should be implemented
3875 if(!has_indirect_arrays) {
3876 //ALOGD("unoptimized drawelements !!!\n");
3877 }
3878 } else {
3879 // we are all direct arrays and immidate mode index array -
3880 // rebuild the arrays and the index array;
3881 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
3882 }
3883 }
3884}
3885
3886// struct GLStringKey {
3887// GLenum name;
3888// GLuint index;
3889// };
3890//
3891// struct GLStringKeyCompare {
3892// bool operator() (const GLStringKey& a,
3893// const GLStringKey& b) const {
3894// if (a.name != b.name) return a.name < b.name;
3895// if (a.index != b.index) return a.index < b.index;
3896// return false;
3897// }
3898// };
3899//
3900// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
3901//
3902// static GLStringStore sGLStringStore;
3903// bool sGLStringStoreInitialized = false;
3904
3905const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
3906 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08003907 const GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003908
3909 RET_AND_SET_ERROR_IF(
3910 name != GL_VENDOR &&
3911 name != GL_RENDERER &&
3912 name != GL_VERSION &&
3913 name != GL_EXTENSIONS,
3914 GL_INVALID_ENUM,
3915 retval);
3916
3917 RET_AND_SET_ERROR_IF(
3918 name == GL_VENDOR ||
3919 name == GL_RENDERER ||
3920 name == GL_VERSION ||
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003921 index != 0,
3922 GL_INVALID_VALUE,
3923 retval);
3924
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08003925 RET_AND_SET_ERROR_IF(
3926 name == GL_EXTENSIONS &&
3927 index >= ctx->m_currExtensionsArray.size(),
3928 GL_INVALID_VALUE,
3929 retval);
3930
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003931 switch (name) {
3932 case GL_VENDOR:
3933 retval = gVendorString;
3934 break;
3935 case GL_RENDERER:
3936 retval = gRendererString;
3937 break;
3938 case GL_VERSION:
3939 retval = gVersionString;
3940 break;
3941 case GL_EXTENSIONS:
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08003942 retval = (const GLubyte*)(ctx->m_currExtensionsArray[index].c_str());
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003943 break;
3944 }
3945
3946 return retval;
3947}
3948
3949void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
3950 GL2Encoder *ctx = (GL2Encoder *)self;
3951
3952 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3953
3954 GLint linkStatus = 0;
3955 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
3956 GLint properLength = 0;
3957 ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
3958
3959 SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
3960 SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
3961
3962 ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
3963}
3964
3965void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
3966 GL2Encoder *ctx = (GL2Encoder *)self;
3967
3968 SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
3969 SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
3970 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
3971 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
3972 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
3973 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
3974 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
3975 ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
3976 GL_INVALID_OPERATION);
3977 /*
3978GL_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.
3979
3980GL_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.
3981
3982GL_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.
3983
3984GL_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.
3985*/
3986
3987 FboFormatInfo fbo_format_info;
3988 ctx->m_state->getBoundFramebufferFormat(
3989 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
3990 SET_ERROR_IF(
3991 fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
3992 !GLESv2Validation::readPixelsFboFormatMatch(
3993 format, type, fbo_format_info.tex_type),
3994 GL_INVALID_OPERATION);
3995
3996 if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
3997 ctx->glReadPixelsOffsetAEMU(
3998 ctx, x, y, width, height,
3999 format, type, (uintptr_t)pixels);
4000 } else {
4001 ctx->m_glReadPixels_enc(
4002 ctx, x, y, width, height,
4003 format, type, pixels);
4004 }
4005}
4006
4007// Track enabled state for some things like:
4008// - Primitive restart
4009void GL2Encoder::s_glEnable(void* self, GLenum what) {
4010 GL2Encoder *ctx = (GL2Encoder *)self;
4011
4012 switch (what) {
4013 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4014 ctx->m_primitiveRestartEnabled = true;
4015 break;
4016 }
4017
4018 ctx->m_glEnable_enc(ctx, what);
4019}
4020
4021void GL2Encoder::s_glDisable(void* self, GLenum what) {
4022 GL2Encoder *ctx = (GL2Encoder *)self;
4023
4024 switch (what) {
4025 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4026 ctx->m_primitiveRestartEnabled = false;
4027 break;
4028 }
4029
4030 ctx->m_glDisable_enc(ctx, what);
4031}
4032
4033void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
4034 GL2Encoder *ctx = (GL2Encoder *)self;
4035
4036 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4037
4038 ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
4039}
4040
4041void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
4042 GL2Encoder *ctx = (GL2Encoder *)self;
4043
4044 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4045
4046 ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
4047}
4048
4049void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
4050 GL2Encoder *ctx = (GL2Encoder *)self;
4051
4052 SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4053
4054 ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
4055}
4056
4057void 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) {
4058 GL2Encoder *ctx = (GL2Encoder *)self;
4059 GLClientState* state = ctx->m_state;
4060
4061 bool validateColor = mask | GL_COLOR_BUFFER_BIT;
4062 bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
4063 bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
4064
4065 FboFormatInfo read_fbo_format_info;
4066 FboFormatInfo draw_fbo_format_info;
4067 if (validateColor) {
4068 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4069 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4070
4071 if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4072 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
4073 SET_ERROR_IF(
4074 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4075 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4076 !GLESv2Validation::blitFramebufferFormat(
4077 read_fbo_format_info.tex_type,
4078 draw_fbo_format_info.tex_type),
4079 GL_INVALID_OPERATION);
4080 }
4081 }
4082
4083 if (validateDepth) {
4084 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
4085 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
4086
4087 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4088 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4089 SET_ERROR_IF(
4090 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4091 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4092 !GLESv2Validation::blitFramebufferFormat(
4093 read_fbo_format_info.rb_format,
4094 draw_fbo_format_info.rb_format),
4095 GL_INVALID_OPERATION);
4096 }
4097 }
4098
4099 if (validateStencil) {
4100 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
4101 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
4102
4103 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4104 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4105 SET_ERROR_IF(
4106 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4107 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4108 !GLESv2Validation::blitFramebufferFormat(
4109 read_fbo_format_info.rb_format,
4110 draw_fbo_format_info.rb_format),
4111 GL_INVALID_OPERATION);
4112 }
4113 }
4114
4115 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4116 SET_ERROR_IF(
4117 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4118 draw_fbo_format_info.rb_multisamples > 0,
4119 GL_INVALID_OPERATION);
4120 SET_ERROR_IF(
4121 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4122 draw_fbo_format_info.tex_multisamples > 0,
4123 GL_INVALID_OPERATION);
4124
4125 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4126 SET_ERROR_IF(
4127 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4128 read_fbo_format_info.rb_multisamples > 0 &&
4129 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4130 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4131 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4132 (read_fbo_format_info.rb_format !=
4133 draw_fbo_format_info.rb_format),
4134 GL_INVALID_OPERATION);
4135 SET_ERROR_IF(
4136 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4137 read_fbo_format_info.rb_multisamples > 0 &&
4138 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4139 (srcX0 != dstX0 || srcY0 != dstY0 ||
4140 srcX1 != dstX1 || srcY1 != dstY1),
4141 GL_INVALID_OPERATION);
4142
4143 ctx->m_glBlitFramebuffer_enc(ctx,
4144 srcX0, srcY0, srcX1, srcY1,
4145 dstX0, dstY0, dstX1, dstY1,
4146 mask, filter);
4147}
4148
4149void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
4150 GL2Encoder *ctx = (GL2Encoder *)self;
4151
4152 SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
4153 pname != GL_SAMPLES,
4154 GL_INVALID_ENUM);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004155 SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004156 SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004157 !GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4158 !GLESv2Validation::depthRenderableFormat(ctx, internalformat) &&
4159 !GLESv2Validation::stencilRenderableFormat(ctx, internalformat),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004160 GL_INVALID_ENUM);
4161 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4162
4163 if (bufSize < 1) return;
4164
4165 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
4166 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
4167 switch (pname) {
4168 case GL_NUM_SAMPLE_COUNTS:
4169 *params = 3;
4170 break;
4171 case GL_SAMPLES:
4172 params[0] = 4;
4173 if (bufSize > 1) params[1] = 2;
4174 if (bufSize > 2) params[2] = 1;
4175 break;
4176 default:
4177 break;
4178 }
4179}
4180
4181void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
4182 GL2Encoder *ctx = (GL2Encoder *)self;
4183 GLClientState* state = ctx->m_state;
4184
4185 SET_ERROR_IF(target != GL_TEXTURE_2D &&
4186 target != GL_TEXTURE_3D &&
4187 target != GL_TEXTURE_CUBE_MAP,
4188 GL_INVALID_ENUM);
4189
4190 GLuint tex = state->getBoundTexture(target);
4191 GLenum internalformat = state->queryTexInternalFormat(tex);
4192 GLenum format = state->queryTexFormat(tex);
4193
4194 SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
4195 GL_INVALID_OPERATION);
4196 SET_ERROR_IF(tex &&
4197 !GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004198 !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4199 GLESv2Validation::filterableTexFormat(ctx, internalformat)),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004200 GL_INVALID_OPERATION);
4201
4202 ctx->m_glGenerateMipmap_enc(ctx, target);
4203}
4204
4205void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4206 GL2Encoder *ctx = (GL2Encoder *)self;
4207 GLint maxCombinedUnits;
4208 ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4209 SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4210
4211 ctx->m_glBindSampler_enc(ctx, unit, sampler);
4212}
4213
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004214GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4215 GL2Encoder *ctx = (GL2Encoder *)self;
4216 uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4217 return (GLsync)(uintptr_t)syncHandle;
4218}
4219
4220GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4221 GL2Encoder *ctx = (GL2Encoder *)self;
4222 return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4223}
4224
4225void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4226 GL2Encoder *ctx = (GL2Encoder *)self;
4227 ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4228}
4229
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004230void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) {
4231 GL2Encoder *ctx = (GL2Encoder *)self;
4232
4233 if (!sync) return;
4234
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004235 ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4236}
4237
4238GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4239 GL2Encoder *ctx = (GL2Encoder *)self;
4240 return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4241}
4242
4243void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4244 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004245
4246 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4247
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004248 return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004249}
4250
4251#define LIMIT_CASE(target, lim) \
4252 case target: \
4253 ctx->glGetIntegerv(ctx, lim, &limit); \
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004254 SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004255 break; \
4256
4257void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) {
4258 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004259 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004260
4261 GLint limit;
4262
4263 switch (target) {
4264 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4265 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4266 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4267 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4268 default:
4269 break;
4270 }
4271
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004272 const GLClientState::VertexAttribBindingVector& currBindings =
4273 state->currentVertexBufferBindings();
4274
4275 switch (target) {
4276 case GL_VERTEX_BINDING_DIVISOR:
4277 case GL_VERTEX_BINDING_OFFSET:
4278 case GL_VERTEX_BINDING_STRIDE:
4279 case GL_VERTEX_BINDING_BUFFER:
4280 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4281 break;
4282 default:
4283 break;
4284 }
4285
4286 switch (target) {
4287 case GL_VERTEX_BINDING_DIVISOR:
4288 *params = currBindings[index].divisor;
4289 return;
4290 case GL_VERTEX_BINDING_OFFSET:
4291 *params = currBindings[index].offset;
4292 return;
4293 case GL_VERTEX_BINDING_STRIDE:
4294 *params = currBindings[index].effectiveStride;
4295 return;
4296 case GL_VERTEX_BINDING_BUFFER:
4297 *params = currBindings[index].buffer;
4298 return;
4299 default:
4300 break;
4301 }
4302
Lingfeng Yang80a36332017-07-09 10:58:07 -07004303 ctx->safe_glGetIntegeri_v(target, index, params);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004304}
4305
4306void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
4307 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004308 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004309
4310 GLint limit;
4311
4312 switch (target) {
4313 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4314 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4315 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4316 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4317 default:
4318 break;
4319 }
4320
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004321 const GLClientState::VertexAttribBindingVector& currBindings =
4322 state->currentVertexBufferBindings();
4323
4324 switch (target) {
4325 case GL_VERTEX_BINDING_DIVISOR:
4326 case GL_VERTEX_BINDING_OFFSET:
4327 case GL_VERTEX_BINDING_STRIDE:
4328 case GL_VERTEX_BINDING_BUFFER:
4329 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4330 break;
4331 default:
4332 break;
4333 }
4334
4335 switch (target) {
4336 case GL_VERTEX_BINDING_DIVISOR:
4337 *params = currBindings[index].divisor;
4338 return;
4339 case GL_VERTEX_BINDING_OFFSET:
4340 *params = currBindings[index].offset;
4341 return;
4342 case GL_VERTEX_BINDING_STRIDE:
4343 *params = currBindings[index].effectiveStride;
4344 return;
4345 case GL_VERTEX_BINDING_BUFFER:
4346 *params = currBindings[index].buffer;
4347 return;
4348 default:
4349 break;
4350 }
4351
Lingfeng Yang80a36332017-07-09 10:58:07 -07004352 ctx->safe_glGetInteger64i_v(target, index, params);
4353}
4354
4355void GL2Encoder::s_glGetInteger64v(void* self, GLenum param, GLint64* val) {
4356 GL2Encoder *ctx = (GL2Encoder *)self;
4357 ctx->safe_glGetInteger64v(param, val);
4358}
4359
4360void GL2Encoder::s_glGetBooleani_v(void* self, GLenum param, GLuint index, GLboolean* val) {
4361 GL2Encoder *ctx = (GL2Encoder *)self;
4362 ctx->safe_glGetBooleani_v(param, index, val);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004363}
4364
4365void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4366 GL2Encoder *ctx = (GL2Encoder *)self;
4367 ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4368 if (pname == GL_SHADER_SOURCE_LENGTH) {
4369 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4370 if (shaderData) {
4371 int totalLen = 0;
4372 for (int i = 0; i < shaderData->sources.size(); i++) {
4373 totalLen += shaderData->sources[i].size();
4374 }
4375 if (totalLen != 0) {
4376 *params = totalLen + 1; // account for null terminator
4377 }
4378 }
4379 }
4380}
4381
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004382void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) {
4383 GL2Encoder *ctx = (GL2Encoder*)self;
4384 GLClientState* state = ctx->m_state;
4385 GLSharedGroupPtr shared = ctx->m_shared;
4386
4387 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4388 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4389 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4390
4391 ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program);
4392 if (!state->currentProgram()) {
4393 state->setCurrentShaderProgram(program);
4394 }
4395}
4396
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004397GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4398
4399 GLint* length = NULL;
4400 GL2Encoder* ctx = (GL2Encoder*)self;
4401
4402 int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
4403 char *str = new char[len + 1];
4404 glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
4405
4406 // Do GLSharedGroup and location WorkARound-specific initialization
4407 // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4408 uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4409 ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
4410 ShaderData* sData = spData->shaderData;
4411
4412 if (!replaceSamplerExternalWith2D(str, sData)) {
4413 delete [] str;
4414 ctx->setError(GL_OUT_OF_MEMORY);
4415 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4416 return -1;
4417 }
4418
4419 GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
4420 delete [] str;
4421
4422 // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4423 GLint linkStatus = 0;
4424 ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4425 if (!linkStatus) {
4426 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4427 return -1;
4428 }
4429
4430 ctx->m_shared->associateGLShaderProgram(res, spDataId);
4431
4432 GLint numUniforms = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07004433 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORMS, &numUniforms);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004434 ctx->m_shared->initShaderProgramData(res, numUniforms);
4435
4436 GLint maxLength=0;
4437 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4438
4439 GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4440
4441 for (GLint i = 0; i < numUniforms; ++i) {
4442 ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4443 GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4444 ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4445 }
4446
4447 ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4448
4449 delete [] name;
4450
4451 return res;
4452}
4453
4454void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4455{
4456 GL2Encoder *ctx = (GL2Encoder*)self;
4457 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4458 ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4459}
4460
4461void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4462{
4463 GL2Encoder *ctx = (GL2Encoder*)self;
4464 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4465 ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4466}
4467
4468void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4469{
4470 GL2Encoder *ctx = (GL2Encoder*)self;
4471 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004472 ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004473
4474 GLClientState* state = ctx->m_state;
4475 GLSharedGroupPtr shared = ctx->m_shared;
4476 GLenum target;
4477
4478 if (shared->setSamplerUniform(program, location, v0, &target)) {
4479 GLenum origActiveTexture = state->getActiveTextureUnit();
4480 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4481 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4482 }
4483 state->setActiveTextureUnit(origActiveTexture);
4484 }
4485}
4486
4487void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4488{
4489 GL2Encoder *ctx = (GL2Encoder*)self;
4490 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4491 ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4492}
4493
4494void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4495{
4496 GL2Encoder *ctx = (GL2Encoder*)self;
4497 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4498 ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4499
4500 GLClientState* state = ctx->m_state;
4501 GLSharedGroupPtr shared = ctx->m_shared;
4502 GLenum target;
4503
4504 if (shared->setSamplerUniform(program, location, v0, &target)) {
4505 GLenum origActiveTexture = state->getActiveTextureUnit();
4506 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4507 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4508 }
4509 state->setActiveTextureUnit(origActiveTexture);
4510 }
4511}
4512
4513void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4514{
4515 GL2Encoder *ctx = (GL2Encoder*)self;
4516 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4517 ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
4518}
4519
4520void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
4521{
4522 GL2Encoder *ctx = (GL2Encoder*)self;
4523 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4524 ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
4525}
4526
4527void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4528{
4529 GL2Encoder *ctx = (GL2Encoder*)self;
4530 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4531 ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
4532}
4533
4534void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
4535{
4536 GL2Encoder *ctx = (GL2Encoder*)self;
4537 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4538 ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
4539}
4540
4541void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4542{
4543 GL2Encoder *ctx = (GL2Encoder*)self;
4544 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4545 ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
4546}
4547
4548void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
4549{
4550 GL2Encoder *ctx = (GL2Encoder*)self;
4551 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4552 ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
4553}
4554
4555void GL2Encoder::s_glProgramUniform2uiv(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_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
4560}
4561
4562void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
4563{
4564 GL2Encoder *ctx = (GL2Encoder*)self;
4565 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4566 ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
4567}
4568
4569void GL2Encoder::s_glProgramUniform3fv(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_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
4574}
4575
4576void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
4577{
4578 GL2Encoder *ctx = (GL2Encoder*)self;
4579 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4580 ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
4581}
4582
4583void GL2Encoder::s_glProgramUniform3iv(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_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
4588}
4589
4590void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
4591{
4592 GL2Encoder *ctx = (GL2Encoder*)self;
4593 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4594 ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
4595}
4596
4597void GL2Encoder::s_glProgramUniform3uiv(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_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
4602}
4603
4604void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
4605{
4606 GL2Encoder *ctx = (GL2Encoder*)self;
4607 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4608 ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
4609}
4610
4611void GL2Encoder::s_glProgramUniform4fv(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_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
4616}
4617
4618void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
4619{
4620 GL2Encoder *ctx = (GL2Encoder*)self;
4621 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4622 ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
4623}
4624
4625void GL2Encoder::s_glProgramUniform4iv(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_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
4630}
4631
4632void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
4633{
4634 GL2Encoder *ctx = (GL2Encoder*)self;
4635 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4636 ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
4637}
4638
4639void GL2Encoder::s_glProgramUniform4uiv(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_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
4644}
4645
4646void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4647{
4648 GL2Encoder *ctx = (GL2Encoder*)self;
4649 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4650 ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
4651}
4652
4653void GL2Encoder::s_glProgramUniformMatrix2x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4654{
4655 GL2Encoder *ctx = (GL2Encoder*)self;
4656 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4657 ctx->m_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
4658}
4659
4660void GL2Encoder::s_glProgramUniformMatrix2x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4661{
4662 GL2Encoder *ctx = (GL2Encoder*)self;
4663 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4664 ctx->m_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
4665}
4666
4667void GL2Encoder::s_glProgramUniformMatrix3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4668{
4669 GL2Encoder *ctx = (GL2Encoder*)self;
4670 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4671 ctx->m_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
4672}
4673
4674void GL2Encoder::s_glProgramUniformMatrix3x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4675{
4676 GL2Encoder *ctx = (GL2Encoder*)self;
4677 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4678 ctx->m_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
4679}
4680
4681void GL2Encoder::s_glProgramUniformMatrix3x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
4682{
4683 GL2Encoder *ctx = (GL2Encoder*)self;
4684 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4685 ctx->m_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
4686}
4687
4688void GL2Encoder::s_glProgramUniformMatrix4fv(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_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
4693}
4694
4695void GL2Encoder::s_glProgramUniformMatrix4x2fv(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_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
4700}
4701
4702void GL2Encoder::s_glProgramUniformMatrix4x3fv(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_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
4707}
4708
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004709void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) {
4710 GL2Encoder* ctx = (GL2Encoder*)self;
4711 ctx->m_glProgramParameteri_enc(self, program, pname, value);
4712}
4713
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004714void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
4715{
4716 GL2Encoder *ctx = (GL2Encoder*)self;
4717 GLClientState* state = ctx->m_state;
4718 GLSharedGroupPtr shared = ctx->m_shared;
4719
4720 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4721 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4722 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4723
4724 ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
4725 state->associateProgramWithPipeline(program, pipeline);
4726
4727 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4728 if (state->currentProgram()) {
4729 return;
4730 }
4731
4732 // Otherwise, update host texture 2D bindings.
4733 ctx->updateHostTexture2DBindingsFromProgramData(program);
4734}
4735
4736void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
4737{
4738 GL2Encoder *ctx = (GL2Encoder*)self;
4739 GLClientState* state = ctx->m_state;
4740
4741 ctx->m_glBindProgramPipeline_enc(self, pipeline);
4742
4743 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
4744 if (!pipeline || state->currentProgram()) {
4745 return;
4746 }
4747
4748 GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
4749 for (; it != state->programPipelineEnd(); ++it) {
4750 if (it->second == pipeline) {
4751 ctx->updateHostTexture2DBindingsFromProgramData(it->first);
4752 }
4753 }
4754}
4755
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004756void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
4757 GL2Encoder *ctx = (GL2Encoder*)self;
4758 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4759 if (bufSize == 0) {
4760 if (length) *length = 0;
4761 return;
4762 }
4763
4764 // Avoid modifying |name| if |*length| < bufSize.
4765 GLint* intermediate = new GLint[bufSize];
4766 GLsizei* myLength = length ? length : new GLsizei;
4767 bool needFreeLength = length == NULL;
4768
4769 ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
4770 GLsizei writtenInts = *myLength;
4771 memcpy(params, intermediate, writtenInts * sizeof(GLint));
4772
4773 delete [] intermediate;
4774 if (needFreeLength)
4775 delete myLength;
4776}
4777
4778GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
4779 GL2Encoder *ctx = (GL2Encoder*)self;
4780 return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
4781}
4782
4783GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
4784 GL2Encoder *ctx = (GL2Encoder*)self;
4785 return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
4786}
4787
4788void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
4789 GL2Encoder *ctx = (GL2Encoder*)self;
4790 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4791 if (bufSize == 0) {
4792 if (length) *length = 0;
4793 return;
4794 }
4795
4796 // Avoid modifying |name| if |*length| < bufSize.
4797 char* intermediate = new char[bufSize];
4798 GLsizei* myLength = length ? length : new GLsizei;
4799 bool needFreeLength = length == NULL;
4800
4801 ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
4802 GLsizei writtenStrLen = *myLength;
4803 memcpy(name, intermediate, writtenStrLen + 1);
4804
4805 delete [] intermediate;
4806 if (needFreeLength)
4807 delete myLength;
4808}
4809
4810void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
4811 GL2Encoder *ctx = (GL2Encoder*)self;
4812 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4813 if (bufSize == 0) {
4814 if (length) *length = 0;
4815 return;
4816 }
4817
4818 // Avoid modifying |infoLog| if |*length| < bufSize.
4819 GLchar* intermediate = new GLchar[bufSize];
4820 GLsizei* myLength = length ? length : new GLsizei;
4821 bool needFreeLength = length == NULL;
4822
4823 ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
4824 GLsizei writtenStrLen = *myLength;
4825 memcpy(infoLog, intermediate, writtenStrLen + 1);
4826
4827 delete [] intermediate;
4828 if (needFreeLength)
4829 delete myLength;
4830}
4831
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004832void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
4833 GL2Encoder *ctx = (GL2Encoder*)self;
4834 GLClientState* state = ctx->m_state;
4835
Lingfeng Yang07289902017-01-27 12:26:19 -08004836 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004837 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4838
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004839 state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false);
4840 ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset);
4841}
4842
4843void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
4844 GL2Encoder *ctx = (GL2Encoder*)self;
4845 GLClientState* state = ctx->m_state;
4846
Lingfeng Yang07289902017-01-27 12:26:19 -08004847 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004848 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4849
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004850 state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true);
4851 ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset);
4852}
4853
4854void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004855 GL2Encoder *ctx = (GL2Encoder*)self;
4856 GLClientState* state = ctx->m_state;
4857
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004858 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4859
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004860 state->setVertexBindingDivisor(bindingindex, divisor);
4861 ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor);
4862}
4863
4864void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) {
4865 GL2Encoder *ctx = (GL2Encoder*)self;
4866 GLClientState* state = ctx->m_state;
Lingfeng Yang07289902017-01-27 12:26:19 -08004867 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004868 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004869
4870 state->setVertexAttribBinding(attribindex, bindingindex);
4871 ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex);
4872}
4873
4874void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
4875 GL2Encoder *ctx = (GL2Encoder*)self;
4876 GLClientState* state = ctx->m_state;
4877
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004878 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
4879
4880 GLint maxStride;
4881 ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
4882 SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE);
4883
4884 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4885
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004886 state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride);
4887 ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride);
4888}
4889
4890void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) {
4891 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004892 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004893
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004894 bool hasClientArrays = false;
4895 ctx->getVBOUsage(&hasClientArrays, NULL);
4896
4897 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
4898 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4899 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
4900
4901 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004902 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004903 // BufferData* buf = ctx->getBufferData(target);
4904 // if (buf) {
4905 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
4906 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004907 ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect);
4908 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004909 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
4910 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004911 ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize);
4912 }
4913}
4914
4915void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) {
4916 GL2Encoder *ctx = (GL2Encoder*)self;
4917
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004918 GLClientState* state = ctx->m_state;
4919
4920 bool hasClientArrays = false;
4921 ctx->getVBOUsage(&hasClientArrays, NULL);
4922
4923 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
4924 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
4925 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
4926
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004927 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004928
4929 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004930 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004931 // BufferData* buf = ctx->getBufferData(target);
4932 // if (buf) {
4933 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
4934 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004935 ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect);
4936 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004937 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
4938 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004939 ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize);
4940 }
4941
4942}
4943
4944void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
4945 GL2Encoder *ctx = (GL2Encoder*)self;
4946 GLClientState* state = ctx->m_state;
4947
4948 SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
4949 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
4950 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
4951 SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
4952 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004953 GLint max_samples;
4954 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
4955 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004956
4957 state->setBoundTextureInternalFormat(target, internalformat);
4958 state->setBoundTextureDims(target, 0, width, height, 1);
4959 state->setBoundTextureImmutableFormat(target);
4960 state->setBoundTextureSamples(target, samples);
4961
4962 ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
4963}
4964