blob: 50cca08dcdaee138308c6113299f0db119fcabe3 [file] [log] [blame]
keunyoungb85b2752013-03-08 12:28:03 -08001/*
2* Copyright (C) 2011 The Android Open Source Project
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17#include "GL2Encoder.h"
Lingfeng Yang46153ab2017-01-09 13:37:22 -080018#include "GLESv2Validation.h"
19
20#include <string>
21#include <map>
22
keunyoungb85b2752013-03-08 12:28:03 -080023#include <assert.h>
24#include <ctype.h>
25
Lingfeng Yang69066602016-04-12 09:29:11 -070026#include <GLES2/gl2.h>
27#include <GLES2/gl2ext.h>
28#include <GLES2/gl2platform.h>
29
30#include <GLES3/gl3.h>
Lingfeng Yang46153ab2017-01-09 13:37:22 -080031#include <GLES3/gl31.h>
Lingfeng Yang69066602016-04-12 09:29:11 -070032
keunyoungb85b2752013-03-08 12:28:03 -080033#ifndef MIN
34#define MIN(a, b) ((a) < (b) ? (a) : (b))
35#endif
36
37static GLubyte *gVendorString= (GLubyte *) "Android";
Lingfeng Yang46153ab2017-01-09 13:37:22 -080038static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 3.0";
39static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 3.0";
Nicolas Capensfe2d51a2015-11-20 15:10:09 -050040static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external ";
keunyoungb85b2752013-03-08 12:28:03 -080041
Lingfeng Yang07289902017-01-27 12:26:19 -080042#define SET_ERROR_IF(condition, err) if((condition)) { \
keunyoungb85b2752013-03-08 12:28:03 -080043 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
Lingfeng Yang07289902017-01-27 12:26:19 -080044 ctx->setError(err); \
45 return; \
keunyoungb85b2752013-03-08 12:28:03 -080046 }
47
Lingfeng Yang07289902017-01-27 12:26:19 -080048#define SET_ERROR_WITH_MESSAGE_IF(condition, err, generator, genargs) if ((condition)) { \
49 std::string msg = generator genargs; \
50 ALOGE("%s:%s:%d GL error 0x%x\n" \
51 "Info: %s\n", __FILE__, __FUNCTION__, __LINE__, err, msg.c_str()); \
52 ctx->setError(err); \
53 return; \
54 } \
keunyoungb85b2752013-03-08 12:28:03 -080055
Lingfeng Yang07289902017-01-27 12:26:19 -080056#define RET_AND_SET_ERROR_IF(condition, err, ret) if((condition)) { \
keunyoungb85b2752013-03-08 12:28:03 -080057 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
Lingfeng Yang07289902017-01-27 12:26:19 -080058 ctx->setError(err); \
59 return ret; \
60 } \
keunyoungb85b2752013-03-08 12:28:03 -080061
Lingfeng Yang07289902017-01-27 12:26:19 -080062#define RET_AND_SET_ERROR_WITH_MESSAGE_IF(condition, err, ret, generator, genargs) if((condition)) { \
63 std::string msg = generator genargs; \
64 ALOGE("%s:%s:%d GL error 0x%x\n" \
65 "Info: %s\n", __FILE__, __FUNCTION__, __LINE__, err, msg.c_str()); \
66 ctx->setError(err); \
67 return ret; \
68 } \
keunyoungb85b2752013-03-08 12:28:03 -080069
Yahan Zhoub7f09082016-03-10 11:45:02 -080070GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
71 : gl2_encoder_context_t(stream, protocol)
keunyoungb85b2752013-03-08 12:28:03 -080072{
Lingfeng Yange6556dc2017-01-09 12:04:12 -080073 m_currMajorVersion = 2;
74 m_currMinorVersion = 0;
keunyoungb85b2752013-03-08 12:28:03 -080075 m_initialized = false;
Lingfeng Yange980c7a2018-01-12 14:50:18 -080076 m_noHostError = false;
keunyoungb85b2752013-03-08 12:28:03 -080077 m_state = NULL;
78 m_error = GL_NO_ERROR;
Roman Kiryanovdaecd142018-11-14 14:56:27 -080079
keunyoungb85b2752013-03-08 12:28:03 -080080 m_num_compressedTextureFormats = 0;
Lingfeng Yang48685bb2018-10-19 06:44:20 -070081 m_max_combinedTextureImageUnits = 0;
Lingfeng Yanga1edab62018-10-19 07:53:49 -070082 m_max_vertexTextureImageUnits = 0;
83 m_max_textureImageUnits = 0;
Lizhe Liue41f4ef2015-05-27 11:13:23 +080084 m_max_cubeMapTextureSize = 0;
85 m_max_renderBufferSize = 0;
86 m_max_textureSize = 0;
Lingfeng Yang46153ab2017-01-09 13:37:22 -080087 m_max_3d_textureSize = 0;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -080088 m_max_vertexAttribStride = 0;
Lingfeng Yanga1edab62018-10-19 07:53:49 -070089
90 m_max_transformFeedbackSeparateAttribs = 0;
91 m_max_uniformBufferBindings = 0;
92 m_max_colorAttachments = 0;
93 m_max_drawBuffers = 0;
94
95 m_max_atomicCounterBufferBindings = 0;
96 m_max_shaderStorageBufferBindings = 0;
97 m_max_vertexAttribBindings = 0;
98
keunyoungb85b2752013-03-08 12:28:03 -080099 m_compressedTextureFormats = NULL;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100100
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800101 m_ssbo_offset_align = 0;
102 m_ubo_offset_align = 0;
103
Lingfeng Yangde51dfb2016-10-17 22:48:59 -0700104 m_drawCallFlushCount = 0;
105 m_primitiveRestartEnabled = false;
106 m_primitiveRestartIndex = 0;
107
Lingfeng Yang07289902017-01-27 12:26:19 -0800108 // overrides
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100109#define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name
Lingfeng Yange6556dc2017-01-09 12:04:12 -0800110#define OVERRIDE_CUSTOM(name) this-> name = &s_##name
111#define OVERRIDEWITH(name, target) do { \
112 m_##target##_enc = this-> target; \
113 this-> target = &s_##name; \
114} while(0)
115#define OVERRIDEOES(name) OVERRIDEWITH(name, name##OES)
bohu56bf82f2014-10-17 15:35:48 -0700116
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100117 OVERRIDE(glFlush);
118 OVERRIDE(glPixelStorei);
119 OVERRIDE(glGetString);
120 OVERRIDE(glBindBuffer);
121 OVERRIDE(glBufferData);
122 OVERRIDE(glBufferSubData);
123 OVERRIDE(glDeleteBuffers);
124 OVERRIDE(glDrawArrays);
125 OVERRIDE(glDrawElements);
126 OVERRIDE(glGetIntegerv);
127 OVERRIDE(glGetFloatv);
128 OVERRIDE(glGetBooleanv);
129 OVERRIDE(glVertexAttribPointer);
130 OVERRIDE(glEnableVertexAttribArray);
131 OVERRIDE(glDisableVertexAttribArray);
132 OVERRIDE(glGetVertexAttribiv);
133 OVERRIDE(glGetVertexAttribfv);
134 OVERRIDE(glGetVertexAttribPointerv);
keunyoungb85b2752013-03-08 12:28:03 -0800135
Bo Hu73568cd2015-01-20 16:29:50 -0800136 this->glShaderBinary = &s_glShaderBinary;
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100137 this->glShaderSource = &s_glShaderSource;
138 this->glFinish = &s_glFinish;
keunyoungb85b2752013-03-08 12:28:03 -0800139
David 'Digit' Turner3afd44b2014-10-30 18:15:04 +0100140 OVERRIDE(glGetError);
141 OVERRIDE(glLinkProgram);
142 OVERRIDE(glDeleteProgram);
143 OVERRIDE(glGetUniformiv);
144 OVERRIDE(glGetUniformfv);
145 OVERRIDE(glCreateProgram);
146 OVERRIDE(glCreateShader);
147 OVERRIDE(glDeleteShader);
148 OVERRIDE(glAttachShader);
149 OVERRIDE(glDetachShader);
150 OVERRIDE(glGetAttachedShaders);
151 OVERRIDE(glGetShaderSource);
152 OVERRIDE(glGetShaderInfoLog);
153 OVERRIDE(glGetProgramInfoLog);
154
155 OVERRIDE(glGetUniformLocation);
156 OVERRIDE(glUseProgram);
157
158 OVERRIDE(glUniform1f);
159 OVERRIDE(glUniform1fv);
160 OVERRIDE(glUniform1i);
161 OVERRIDE(glUniform1iv);
162 OVERRIDE(glUniform2f);
163 OVERRIDE(glUniform2fv);
164 OVERRIDE(glUniform2i);
165 OVERRIDE(glUniform2iv);
166 OVERRIDE(glUniform3f);
167 OVERRIDE(glUniform3fv);
168 OVERRIDE(glUniform3i);
169 OVERRIDE(glUniform3iv);
170 OVERRIDE(glUniform4f);
171 OVERRIDE(glUniform4fv);
172 OVERRIDE(glUniform4i);
173 OVERRIDE(glUniform4iv);
174 OVERRIDE(glUniformMatrix2fv);
175 OVERRIDE(glUniformMatrix3fv);
176 OVERRIDE(glUniformMatrix4fv);
177
178 OVERRIDE(glActiveTexture);
179 OVERRIDE(glBindTexture);
180 OVERRIDE(glDeleteTextures);
181 OVERRIDE(glGetTexParameterfv);
182 OVERRIDE(glGetTexParameteriv);
183 OVERRIDE(glTexParameterf);
184 OVERRIDE(glTexParameterfv);
185 OVERRIDE(glTexParameteri);
186 OVERRIDE(glTexParameteriv);
bohu26a92982014-11-25 16:50:37 -0800187 OVERRIDE(glTexImage2D);
Yahan Zhou2a208292016-06-22 15:36:04 -0700188 OVERRIDE(glTexSubImage2D);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -0700189 OVERRIDE(glCopyTexImage2D);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700190
191 OVERRIDE(glGenRenderbuffers);
192 OVERRIDE(glDeleteRenderbuffers);
193 OVERRIDE(glBindRenderbuffer);
Lingfeng Yang69066602016-04-12 09:29:11 -0700194 OVERRIDE(glRenderbufferStorage);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -0700195 OVERRIDE(glFramebufferRenderbuffer);
196
197 OVERRIDE(glGenFramebuffers);
198 OVERRIDE(glDeleteFramebuffers);
199 OVERRIDE(glBindFramebuffer);
200 OVERRIDE(glFramebufferTexture2D);
201 OVERRIDE(glFramebufferTexture3DOES);
202 OVERRIDE(glGetFramebufferAttachmentParameteriv);
Lingfeng Yang69066602016-04-12 09:29:11 -0700203
204 OVERRIDE(glCheckFramebufferStatus);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800205
206 OVERRIDE(glGenVertexArrays);
207 OVERRIDE(glDeleteVertexArrays);
208 OVERRIDE(glBindVertexArray);
209 OVERRIDEOES(glGenVertexArrays);
210 OVERRIDEOES(glDeleteVertexArrays);
211 OVERRIDEOES(glBindVertexArray);
212
Lingfeng Yangfb3d2bb2017-09-07 15:02:04 -0700213 OVERRIDE_CUSTOM(glMapBufferOES);
214 OVERRIDE_CUSTOM(glUnmapBufferOES);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800215 OVERRIDE_CUSTOM(glMapBufferRange);
216 OVERRIDE_CUSTOM(glUnmapBuffer);
217 OVERRIDE_CUSTOM(glFlushMappedBufferRange);
218
219 OVERRIDE(glCompressedTexImage2D);
220 OVERRIDE(glCompressedTexSubImage2D);
221
222 OVERRIDE(glBindBufferRange);
223 OVERRIDE(glBindBufferBase);
224
225 OVERRIDE(glCopyBufferSubData);
226
227 OVERRIDE(glGetBufferParameteriv);
228 OVERRIDE(glGetBufferParameteri64v);
229 OVERRIDE(glGetBufferPointerv);
230
231 OVERRIDE_CUSTOM(glGetUniformIndices);
232
233 OVERRIDE(glUniform1ui);
234 OVERRIDE(glUniform2ui);
235 OVERRIDE(glUniform3ui);
236 OVERRIDE(glUniform4ui);
237 OVERRIDE(glUniform1uiv);
238 OVERRIDE(glUniform2uiv);
239 OVERRIDE(glUniform3uiv);
240 OVERRIDE(glUniform4uiv);
241 OVERRIDE(glUniformMatrix2x3fv);
242 OVERRIDE(glUniformMatrix3x2fv);
243 OVERRIDE(glUniformMatrix2x4fv);
244 OVERRIDE(glUniformMatrix4x2fv);
245 OVERRIDE(glUniformMatrix3x4fv);
246 OVERRIDE(glUniformMatrix4x3fv);
247
248 OVERRIDE(glGetUniformuiv);
249 OVERRIDE(glGetActiveUniformBlockiv);
250
251 OVERRIDE(glGetVertexAttribIiv);
252 OVERRIDE(glGetVertexAttribIuiv);
253
254 OVERRIDE_CUSTOM(glVertexAttribIPointer);
255
256 OVERRIDE(glVertexAttribDivisor);
257
258 OVERRIDE(glRenderbufferStorageMultisample);
259 OVERRIDE(glDrawBuffers);
260 OVERRIDE(glReadBuffer);
261 OVERRIDE(glFramebufferTextureLayer);
262 OVERRIDE(glTexStorage2D);
263
264 OVERRIDE_CUSTOM(glTransformFeedbackVaryings);
265 OVERRIDE(glBeginTransformFeedback);
266 OVERRIDE(glEndTransformFeedback);
267 OVERRIDE(glPauseTransformFeedback);
268 OVERRIDE(glResumeTransformFeedback);
269
270 OVERRIDE(glTexImage3D);
271 OVERRIDE(glTexSubImage3D);
272 OVERRIDE(glTexStorage3D);
273 OVERRIDE(glCompressedTexImage3D);
274 OVERRIDE(glCompressedTexSubImage3D);
275
276 OVERRIDE(glDrawArraysInstanced);
277 OVERRIDE_CUSTOM(glDrawElementsInstanced);
278 OVERRIDE_CUSTOM(glDrawRangeElements);
279
280 OVERRIDE_CUSTOM(glGetStringi);
281 OVERRIDE(glGetProgramBinary);
282 OVERRIDE(glReadPixels);
283
284 OVERRIDE(glEnable);
285 OVERRIDE(glDisable);
286 OVERRIDE(glClearBufferiv);
287 OVERRIDE(glClearBufferuiv);
288 OVERRIDE(glClearBufferfv);
289 OVERRIDE(glBlitFramebuffer);
290 OVERRIDE_CUSTOM(glGetInternalformativ);
291
292 OVERRIDE(glGenerateMipmap);
293
294 OVERRIDE(glBindSampler);
295
Lingfeng Yangf000ab42017-01-11 18:31:38 -0800296 OVERRIDE_CUSTOM(glFenceSync);
297 OVERRIDE_CUSTOM(glClientWaitSync);
298 OVERRIDE_CUSTOM(glWaitSync);
299 OVERRIDE_CUSTOM(glDeleteSync);
300 OVERRIDE_CUSTOM(glIsSync);
301 OVERRIDE_CUSTOM(glGetSynciv);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800302
303 OVERRIDE(glGetIntegeri_v);
304 OVERRIDE(glGetInteger64i_v);
Lingfeng Yang80a36332017-07-09 10:58:07 -0700305 OVERRIDE(glGetInteger64v);
306 OVERRIDE(glGetBooleani_v);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800307
308 OVERRIDE(glGetShaderiv);
309
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800310 OVERRIDE(glActiveShaderProgram);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800311 OVERRIDE_CUSTOM(glCreateShaderProgramv);
312 OVERRIDE(glProgramUniform1f);
313 OVERRIDE(glProgramUniform1fv);
314 OVERRIDE(glProgramUniform1i);
315 OVERRIDE(glProgramUniform1iv);
316 OVERRIDE(glProgramUniform1ui);
317 OVERRIDE(glProgramUniform1uiv);
318 OVERRIDE(glProgramUniform2f);
319 OVERRIDE(glProgramUniform2fv);
320 OVERRIDE(glProgramUniform2i);
321 OVERRIDE(glProgramUniform2iv);
322 OVERRIDE(glProgramUniform2ui);
323 OVERRIDE(glProgramUniform2uiv);
324 OVERRIDE(glProgramUniform3f);
325 OVERRIDE(glProgramUniform3fv);
326 OVERRIDE(glProgramUniform3i);
327 OVERRIDE(glProgramUniform3iv);
328 OVERRIDE(glProgramUniform3ui);
329 OVERRIDE(glProgramUniform3uiv);
330 OVERRIDE(glProgramUniform4f);
331 OVERRIDE(glProgramUniform4fv);
332 OVERRIDE(glProgramUniform4i);
333 OVERRIDE(glProgramUniform4iv);
334 OVERRIDE(glProgramUniform4ui);
335 OVERRIDE(glProgramUniform4uiv);
336 OVERRIDE(glProgramUniformMatrix2fv);
337 OVERRIDE(glProgramUniformMatrix2x3fv);
338 OVERRIDE(glProgramUniformMatrix2x4fv);
339 OVERRIDE(glProgramUniformMatrix3fv);
340 OVERRIDE(glProgramUniformMatrix3x2fv);
341 OVERRIDE(glProgramUniformMatrix3x4fv);
342 OVERRIDE(glProgramUniformMatrix4fv);
343 OVERRIDE(glProgramUniformMatrix4x2fv);
344 OVERRIDE(glProgramUniformMatrix4x3fv);
345
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800346 OVERRIDE(glProgramParameteri);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800347 OVERRIDE(glUseProgramStages);
348 OVERRIDE(glBindProgramPipeline);
349
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800350 OVERRIDE(glGetProgramResourceiv);
351 OVERRIDE(glGetProgramResourceIndex);
352 OVERRIDE(glGetProgramResourceLocation);
353 OVERRIDE(glGetProgramResourceName);
354 OVERRIDE(glGetProgramPipelineInfoLog);
355
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800356 OVERRIDE(glVertexAttribFormat);
357 OVERRIDE(glVertexAttribIFormat);
358 OVERRIDE(glVertexBindingDivisor);
359 OVERRIDE(glVertexAttribBinding);
360 OVERRIDE(glBindVertexBuffer);
361
362 OVERRIDE_CUSTOM(glDrawArraysIndirect);
363 OVERRIDE_CUSTOM(glDrawElementsIndirect);
364
365 OVERRIDE(glTexStorage2DMultisample);
Yahan Zhou72944ba2019-01-02 15:43:46 -0800366
367 OVERRIDE_CUSTOM(glGetGraphicsResetStatusEXT);
368 OVERRIDE_CUSTOM(glReadnPixelsEXT);
369 OVERRIDE_CUSTOM(glGetnUniformfvEXT);
370 OVERRIDE_CUSTOM(glGetnUniformivEXT);
keunyoungb85b2752013-03-08 12:28:03 -0800371}
372
373GL2Encoder::~GL2Encoder()
374{
375 delete m_compressedTextureFormats;
376}
377
378GLenum GL2Encoder::s_glGetError(void * self)
379{
380 GL2Encoder *ctx = (GL2Encoder *)self;
381 GLenum err = ctx->getError();
382 if(err != GL_NO_ERROR) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700383 ctx->m_glGetError_enc(ctx); // also clear host error
keunyoungb85b2752013-03-08 12:28:03 -0800384 ctx->setError(GL_NO_ERROR);
385 return err;
386 }
387
Lingfeng Yange980c7a2018-01-12 14:50:18 -0800388 if (ctx->m_noHostError) {
389 return GL_NO_ERROR;
390 } else {
391 return ctx->m_glGetError_enc(self);
392 }
Lingfeng Yang80a36332017-07-09 10:58:07 -0700393}
Yahan Zhouae30fe82016-08-10 21:15:45 +0000394
Lingfeng Yang80a36332017-07-09 10:58:07 -0700395class GL2Encoder::ErrorUpdater {
396public:
397 ErrorUpdater(GL2Encoder* ctx) :
398 mCtx(ctx),
399 guest_error(ctx->getError()),
400 host_error(ctx->m_glGetError_enc(ctx)) {
401 // Preserve any existing GL error in the guest:
402 // OpenGL ES 3.0.5 spec:
403 // The command enum GetError( void ); is used to obtain error information.
404 // Each detectable error is assigned a numeric code. When an error is
405 // detected, a flag is set and the code is recorded. Further errors, if
406 // they occur, do not affect this recorded code. When GetError is called,
407 // the code is returned and the flag is cleared, so that a further error
408 // will again record its code. If a call to GetError returns NO_ERROR, then
409 // there has been no detectable error since the last call to GetError (or
410 // since the GL was initialized).
411 if (guest_error == GL_NO_ERROR) {
412 guest_error = host_error;
413 }
414 }
415
416 GLenum getHostErrorAndUpdate() {
417 host_error = mCtx->m_glGetError_enc(mCtx);
418 if (guest_error == GL_NO_ERROR) {
419 guest_error = host_error;
420 }
421 return host_error;
422 }
423
424 void updateGuestErrorState() {
425 mCtx->setError(guest_error);
426 }
427
428private:
429 GL2Encoder* mCtx;
430 GLenum guest_error;
431 GLenum host_error;
432};
433
434template<class T>
435class GL2Encoder::ScopedQueryUpdate {
436public:
437 ScopedQueryUpdate(GL2Encoder* ctx, uint32_t bytes, T* target) :
438 mCtx(ctx),
439 mBuf(bytes, 0),
440 mTarget(target),
441 mErrorUpdater(ctx) {
442 }
443 T* hostStagingBuffer() {
444 return (T*)&mBuf[0];
445 }
446 ~ScopedQueryUpdate() {
447 GLint hostError = mErrorUpdater.getHostErrorAndUpdate();
Lingfeng Yang72ecf472018-06-11 14:20:14 -0700448 if (hostError == GL_NO_ERROR && mTarget) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700449 memcpy(mTarget, &mBuf[0], mBuf.size());
450 }
451 mErrorUpdater.updateGuestErrorState();
452 }
453private:
454 GL2Encoder* mCtx;
455 std::vector<char> mBuf;
456 T* mTarget;
457 ErrorUpdater mErrorUpdater;
458};
459
460void GL2Encoder::safe_glGetBooleanv(GLenum param, GLboolean* val) {
461 ScopedQueryUpdate<GLboolean> query(this, glUtilsParamSize(param) * sizeof(GLboolean), val);
462 m_glGetBooleanv_enc(this, param, query.hostStagingBuffer());
463}
464
465void GL2Encoder::safe_glGetFloatv(GLenum param, GLfloat* val) {
466 ScopedQueryUpdate<GLfloat> query(this, glUtilsParamSize(param) * sizeof(GLfloat), val);
467 m_glGetFloatv_enc(this, param, query.hostStagingBuffer());
468}
469
470void GL2Encoder::safe_glGetIntegerv(GLenum param, GLint* val) {
471 ScopedQueryUpdate<GLint> query(this, glUtilsParamSize(param) * sizeof(GLint), val);
472 m_glGetIntegerv_enc(this, param, query.hostStagingBuffer());
473}
474
475void GL2Encoder::safe_glGetInteger64v(GLenum param, GLint64* val) {
476 ScopedQueryUpdate<GLint64> query(this, glUtilsParamSize(param) * sizeof(GLint64), val);
477 m_glGetInteger64v_enc(this, param, query.hostStagingBuffer());
478}
479
480void GL2Encoder::safe_glGetIntegeri_v(GLenum param, GLuint index, GLint* val) {
481 ScopedQueryUpdate<GLint> query(this, sizeof(GLint), val);
482 m_glGetIntegeri_v_enc(this, param, index, query.hostStagingBuffer());
483}
484
485void GL2Encoder::safe_glGetInteger64i_v(GLenum param, GLuint index, GLint64* val) {
486 ScopedQueryUpdate<GLint64> query(this, sizeof(GLint64), val);
487 m_glGetInteger64i_v_enc(this, param, index, query.hostStagingBuffer());
488}
489
490void GL2Encoder::safe_glGetBooleani_v(GLenum param, GLuint index, GLboolean* val) {
491 ScopedQueryUpdate<GLboolean> query(this, sizeof(GLboolean), val);
492 m_glGetBooleani_v_enc(this, param, index, query.hostStagingBuffer());
keunyoungb85b2752013-03-08 12:28:03 -0800493}
494
495void GL2Encoder::s_glFlush(void *self)
496{
497 GL2Encoder *ctx = (GL2Encoder *) self;
498 ctx->m_glFlush_enc(self);
499 ctx->m_stream->flush();
500}
501
502const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
503{
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800504 GL2Encoder *ctx = (GL2Encoder *)self;
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +0100505
keunyoungb85b2752013-03-08 12:28:03 -0800506 GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800507 RET_AND_SET_ERROR_IF(
508 name != GL_VENDOR &&
509 name != GL_RENDERER &&
510 name != GL_VERSION &&
511 name != GL_EXTENSIONS,
512 GL_INVALID_ENUM,
513 retval);
keunyoungb85b2752013-03-08 12:28:03 -0800514 switch(name) {
515 case GL_VENDOR:
516 retval = gVendorString;
517 break;
518 case GL_RENDERER:
519 retval = gRendererString;
520 break;
521 case GL_VERSION:
522 retval = gVersionString;
523 break;
524 case GL_EXTENSIONS:
525 retval = gExtensionsString;
526 break;
527 }
528 return retval;
529}
530
531void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
532{
533 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800534 SET_ERROR_IF(!GLESv2Validation::pixelStoreParam(ctx, param), GL_INVALID_ENUM);
535 SET_ERROR_IF(!GLESv2Validation::pixelStoreValue(param, value), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -0800536 ctx->m_glPixelStorei_enc(ctx, param, value);
537 assert(ctx->m_state != NULL);
538 ctx->m_state->setPixelStore(param, value);
539}
keunyoungb85b2752013-03-08 12:28:03 -0800540void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
541{
542 GL2Encoder *ctx = (GL2Encoder *) self;
543 assert(ctx->m_state != NULL);
544 ctx->m_state->bindBuffer(target, id);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800545 ctx->m_state->addBuffer(id);
keunyoungb85b2752013-03-08 12:28:03 -0800546 // TODO set error state if needed;
547 ctx->m_glBindBuffer_enc(self, target, id);
548}
549
550void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
551{
552 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800553 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800554 GLuint bufferId = ctx->m_state->getBuffer(target);
555 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
556 SET_ERROR_IF(size<0, GL_INVALID_VALUE);
557
Roman Kiryanovfb903d62018-09-19 13:38:53 -0700558 ctx->m_shared->updateBufferData(bufferId, size, data);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800559 ctx->m_shared->setBufferUsage(bufferId, usage);
keunyoungb85b2752013-03-08 12:28:03 -0800560 ctx->m_glBufferData_enc(self, target, size, data, usage);
561}
562
563void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
564{
565 GL2Encoder *ctx = (GL2Encoder *) self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800566 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -0800567 GLuint bufferId = ctx->m_state->getBuffer(target);
568 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800569 SET_ERROR_IF(ctx->isBufferTargetMapped(target), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800570
Roman Kiryanovfb903d62018-09-19 13:38:53 -0700571 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, data);
keunyoungb85b2752013-03-08 12:28:03 -0800572 SET_ERROR_IF(res, res);
573
574 ctx->m_glBufferSubData_enc(self, target, offset, size, data);
575}
576
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800577void GL2Encoder::s_glGenBuffers(void* self, GLsizei n, GLuint* buffers) {
578 GL2Encoder *ctx = (GL2Encoder *) self;
579 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
580 ctx->m_glGenBuffers_enc(self, n, buffers);
581 for (int i = 0; i < n; i++) {
582 ctx->m_state->addBuffer(buffers[i]);
583 }
584}
585
keunyoungb85b2752013-03-08 12:28:03 -0800586void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
587{
588 GL2Encoder *ctx = (GL2Encoder *) self;
589 SET_ERROR_IF(n<0, GL_INVALID_VALUE);
590 for (int i=0; i<n; i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800591 // Technically if the buffer is mapped, we should unmap it, but we won't
592 // use it anymore after this :)
keunyoungb85b2752013-03-08 12:28:03 -0800593 ctx->m_shared->deleteBufferData(buffers[i]);
bohub0f0cdf2014-11-06 18:08:07 -0800594 ctx->m_state->unBindBuffer(buffers[i]);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800595 ctx->m_state->removeBuffer(buffers[i]);
keunyoungb85b2752013-03-08 12:28:03 -0800596 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
597 }
598}
599
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700600static bool isValidVertexAttribIndex(void *self, GLuint indx)
601{
Lingfeng Yang07289902017-01-27 12:26:19 -0800602 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700603 GLint maxIndex;
604 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
605 return indx < maxIndex;
606}
607
Lingfeng Yang07289902017-01-27 12:26:19 -0800608#define VALIDATE_VERTEX_ATTRIB_INDEX(index) \
609 SET_ERROR_WITH_MESSAGE_IF( \
610 !isValidVertexAttribIndex(self, index), GL_INVALID_VALUE, \
611 GLESv2Validation::vertexAttribIndexRangeErrorMsg, (ctx, index)); \
612
David 'Digit' Turner02fdb692014-10-30 18:07:56 +0100613void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
keunyoungb85b2752013-03-08 12:28:03 -0800614{
615 GL2Encoder *ctx = (GL2Encoder *)self;
616 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -0800617 VALIDATE_VERTEX_ATTRIB_INDEX(indx);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700618 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800619 SET_ERROR_IF(!GLESv2Validation::vertexAttribType(ctx, type), GL_INVALID_ENUM);
Evan Birenbaumd51386b2016-04-13 12:53:09 -0700620 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800621 SET_ERROR_IF((type == GL_INT_2_10_10_10_REV ||
622 type == GL_UNSIGNED_INT_2_10_10_10_REV) &&
623 size != 4,
624 GL_INVALID_OPERATION);
625 ctx->m_state->setVertexAttribBinding(indx, indx);
626 ctx->m_state->setVertexAttribFormat(indx, size, type, normalized, 0, false);
627
628 GLsizei effectiveStride = stride;
629 if (stride == 0) {
630 effectiveStride = glSizeof(type) * size;
631 switch (type) {
632 case GL_INT_2_10_10_10_REV:
633 case GL_UNSIGNED_INT_2_10_10_10_REV:
634 effectiveStride /= 4;
635 break;
636 default:
637 break;
638 }
639 }
640
641 ctx->m_state->bindIndexedBuffer(0, indx, ctx->m_state->currentArrayVbo(), (uintptr_t)ptr, 0, stride, effectiveStride);
642
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800643 if (ctx->m_state->currentArrayVbo() != 0) {
644 ctx->glVertexAttribPointerOffset(ctx, indx, size, type, normalized, stride, (uintptr_t)ptr);
645 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800646 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && ptr, GL_INVALID_OPERATION);
647 // wait for client-array handler
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -0800648 }
keunyoungb85b2752013-03-08 12:28:03 -0800649}
650
651void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
652{
653 GL2Encoder *ctx = (GL2Encoder *) self;
keunyoungb85b2752013-03-08 12:28:03 -0800654 GLClientState* state = ctx->m_state;
655
656 switch (param) {
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -0800657 case GL_NUM_EXTENSIONS:
658 *ptr = (int)ctx->m_currExtensionsArray.size();
659 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800660 case GL_MAJOR_VERSION:
Lingfeng Yang324c8452017-02-17 09:56:26 -0800661 *ptr = ctx->m_deviceMajorVersion;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800662 break;
663 case GL_MINOR_VERSION:
Lingfeng Yang324c8452017-02-17 09:56:26 -0800664 *ptr = ctx->m_deviceMinorVersion;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800665 break;
keunyoungb85b2752013-03-08 12:28:03 -0800666 case GL_NUM_SHADER_BINARY_FORMATS:
667 *ptr = 0;
668 break;
669 case GL_SHADER_BINARY_FORMATS:
670 // do nothing
671 break;
672
673 case GL_COMPRESSED_TEXTURE_FORMATS: {
674 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
675 if (ctx->m_num_compressedTextureFormats > 0 &&
676 compressedTextureFormats != NULL) {
677 memcpy(ptr, compressedTextureFormats,
678 ctx->m_num_compressedTextureFormats * sizeof(GLint));
679 }
680 break;
681 }
682
683 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
Lingfeng Yang48685bb2018-10-19 06:44:20 -0700684 if (ctx->m_max_combinedTextureImageUnits != 0) {
685 *ptr = ctx->m_max_combinedTextureImageUnits;
686 } else {
687 ctx->safe_glGetIntegerv(param, ptr);
688 ctx->m_max_combinedTextureImageUnits = *ptr;
689 }
690 break;
keunyoungb85b2752013-03-08 12:28:03 -0800691 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700692 if (ctx->m_max_vertexTextureImageUnits != 0) {
693 *ptr = ctx->m_max_vertexTextureImageUnits;
694 } else {
695 ctx->safe_glGetIntegerv(param, ptr);
696 ctx->m_max_vertexTextureImageUnits = *ptr;
697 }
keunyoungb85b2752013-03-08 12:28:03 -0800698 break;
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700699 case GL_MAX_TEXTURE_IMAGE_UNITS:
700 if (ctx->m_max_textureImageUnits != 0) {
701 *ptr = ctx->m_max_textureImageUnits;
702 } else {
703 ctx->safe_glGetIntegerv(param, ptr);
704 ctx->m_max_textureImageUnits = *ptr;
705 }
706 break;
keunyoungb85b2752013-03-08 12:28:03 -0800707 case GL_TEXTURE_BINDING_2D:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700708 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800709 *ptr = state->getBoundTexture(GL_TEXTURE_2D);
710 break;
711 case GL_TEXTURE_BINDING_EXTERNAL_OES:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700712 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -0800713 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
714 break;
715
Lingfeng Yangb0176982016-03-01 21:27:49 -0800716 case GL_MAX_VERTEX_ATTRIBS:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700717 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
718 if (!state->getClientStateParameter<GLint>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700719 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700720 state->setMaxVertexAttribs(*ptr);
Yahan Zhoua5c36842016-06-01 12:49:39 -0700721 }
722 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800723 case GL_MAX_VERTEX_ATTRIB_STRIDE:
724 if (ctx->m_max_vertexAttribStride != 0) {
725 *ptr = ctx->m_max_vertexAttribStride;
726 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700727 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800728 ctx->m_max_vertexAttribStride = *ptr;
729 }
730 break;
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800731 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
732 if (ctx->m_max_cubeMapTextureSize != 0) {
733 *ptr = ctx->m_max_cubeMapTextureSize;
734 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700735 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800736 ctx->m_max_cubeMapTextureSize = *ptr;
737 }
738 break;
739 case GL_MAX_RENDERBUFFER_SIZE:
740 if (ctx->m_max_renderBufferSize != 0) {
741 *ptr = ctx->m_max_renderBufferSize;
742 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700743 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800744 ctx->m_max_renderBufferSize = *ptr;
745 }
746 break;
747 case GL_MAX_TEXTURE_SIZE:
748 if (ctx->m_max_textureSize != 0) {
749 *ptr = ctx->m_max_textureSize;
750 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700751 ctx->safe_glGetIntegerv(param, ptr);
Lizhe Liue41f4ef2015-05-27 11:13:23 +0800752 ctx->m_max_textureSize = *ptr;
Lingfeng Yangb0176982016-03-01 21:27:49 -0800753 }
754 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800755 case GL_MAX_3D_TEXTURE_SIZE:
756 if (ctx->m_max_3d_textureSize != 0) {
757 *ptr = ctx->m_max_3d_textureSize;
758 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700759 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800760 ctx->m_max_3d_textureSize = *ptr;
761 }
762 break;
763 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
764 if (ctx->m_ssbo_offset_align != 0) {
765 *ptr = ctx->m_ssbo_offset_align;
766 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700767 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800768 ctx->m_ssbo_offset_align = *ptr;
769 }
770 break;
771 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
772 if (ctx->m_ubo_offset_align != 0) {
773 *ptr = ctx->m_ubo_offset_align;
774 } else {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700775 ctx->safe_glGetIntegerv(param, ptr);
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800776 ctx->m_ubo_offset_align = *ptr;
777 }
778 break;
779 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
780 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
781 case GL_MAX_SAMPLES:
Lingfeng Yangd3ae1062017-01-18 11:42:04 -0800782 case GL_MAX_COLOR_TEXTURE_SAMPLES:
783 case GL_MAX_INTEGER_SAMPLES:
784 case GL_MAX_DEPTH_TEXTURE_SAMPLES:
Lingfeng Yang46153ab2017-01-09 13:37:22 -0800785 *ptr = 4;
786 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700787 // Checks for version-incompatible enums.
788 // Not allowed in vanilla ES 2.0.
789 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700790 SET_ERROR_IF(ctx->majorVersion() < 3, GL_INVALID_ENUM);
791 if (ctx->m_max_transformFeedbackSeparateAttribs != 0) {
792 *ptr = ctx->m_max_transformFeedbackSeparateAttribs;
793 } else {
794 ctx->safe_glGetIntegerv(param, ptr);
795 ctx->m_max_transformFeedbackSeparateAttribs = *ptr;
796 }
797 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700798 case GL_MAX_UNIFORM_BUFFER_BINDINGS:
799 SET_ERROR_IF(ctx->majorVersion() < 3, GL_INVALID_ENUM);
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700800 if (ctx->m_max_uniformBufferBindings != 0) {
801 *ptr = ctx->m_max_uniformBufferBindings;
802 } else {
803 ctx->safe_glGetIntegerv(param, ptr);
804 ctx->m_max_uniformBufferBindings = *ptr;
805 }
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700806 break;
807 case GL_MAX_COLOR_ATTACHMENTS:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700808 SET_ERROR_IF(ctx->majorVersion() < 3 &&
809 !ctx->hasExtension("GL_EXT_draw_buffers"), GL_INVALID_ENUM);
810 if (ctx->m_max_colorAttachments != 0) {
811 *ptr = ctx->m_max_colorAttachments;
812 } else {
813 ctx->safe_glGetIntegerv(param, ptr);
814 ctx->m_max_colorAttachments = *ptr;
815 }
816 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700817 case GL_MAX_DRAW_BUFFERS:
818 SET_ERROR_IF(ctx->majorVersion() < 3 &&
819 !ctx->hasExtension("GL_EXT_draw_buffers"), GL_INVALID_ENUM);
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700820 if (ctx->m_max_drawBuffers != 0) {
821 *ptr = ctx->m_max_drawBuffers;
822 } else {
823 ctx->safe_glGetIntegerv(param, ptr);
824 ctx->m_max_drawBuffers = *ptr;
825 }
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700826 break;
827 // Not allowed in ES 3.0.
828 case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700829 SET_ERROR_IF(ctx->majorVersion() < 3 ||
830 (ctx->majorVersion() == 3 &&
831 ctx->minorVersion() == 0), GL_INVALID_ENUM);
832 if (ctx->m_max_atomicCounterBufferBindings != 0) {
833 *ptr = ctx->m_max_atomicCounterBufferBindings;
834 } else {
835 ctx->safe_glGetIntegerv(param, ptr);
836 ctx->m_max_atomicCounterBufferBindings = *ptr;
837 }
838 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700839 case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700840 SET_ERROR_IF(ctx->majorVersion() < 3 ||
841 (ctx->majorVersion() == 3 &&
842 ctx->minorVersion() == 0), GL_INVALID_ENUM);
843 if (ctx->m_max_shaderStorageBufferBindings != 0) {
844 *ptr = ctx->m_max_shaderStorageBufferBindings;
845 } else {
846 ctx->safe_glGetIntegerv(param, ptr);
847 ctx->m_max_shaderStorageBufferBindings = *ptr;
848 }
849 break;
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700850 case GL_MAX_VERTEX_ATTRIB_BINDINGS:
851 SET_ERROR_IF(ctx->majorVersion() < 3 ||
852 (ctx->majorVersion() == 3 &&
853 ctx->minorVersion() == 0), GL_INVALID_ENUM);
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700854 if (ctx->m_max_vertexAttribBindings != 0) {
855 *ptr = ctx->m_max_vertexAttribBindings;
856 } else {
857 ctx->safe_glGetIntegerv(param, ptr);
858 ctx->m_max_vertexAttribBindings = *ptr;
859 }
Lingfeng Yangc9b597b2017-07-08 17:21:03 -0700860 break;
Yahan Zhou72944ba2019-01-02 15:43:46 -0800861 case GL_RESET_NOTIFICATION_STRATEGY_EXT:
862 // BUG: 121414786
863 *ptr = GL_LOSE_CONTEXT_ON_RESET_EXT;
864 break;
keunyoungb85b2752013-03-08 12:28:03 -0800865 default:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700866 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
867 if (!state->getClientStateParameter<GLint>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700868 ctx->safe_glGetIntegerv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800869 }
870 break;
871 }
872}
873
874
875void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
876{
877 GL2Encoder *ctx = (GL2Encoder *)self;
keunyoungb85b2752013-03-08 12:28:03 -0800878 GLClientState* state = ctx->m_state;
879
880 switch (param) {
881 case GL_NUM_SHADER_BINARY_FORMATS:
882 *ptr = 0;
883 break;
884 case GL_SHADER_BINARY_FORMATS:
885 // do nothing
886 break;
887
888 case GL_COMPRESSED_TEXTURE_FORMATS: {
889 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
890 if (ctx->m_num_compressedTextureFormats > 0 &&
891 compressedTextureFormats != NULL) {
892 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
893 ptr[i] = (GLfloat) compressedTextureFormats[i];
894 }
895 }
896 break;
897 }
898
899 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
900 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
901 case GL_MAX_TEXTURE_IMAGE_UNITS:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700902 case GL_MAX_VERTEX_ATTRIBS:
903 case GL_MAX_VERTEX_ATTRIB_STRIDE:
904 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
905 case GL_MAX_RENDERBUFFER_SIZE:
906 case GL_MAX_TEXTURE_SIZE:
907 case GL_MAX_3D_TEXTURE_SIZE:
908 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
909 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
910 case GL_MAX_SAMPLES:
911 case GL_MAX_COLOR_TEXTURE_SAMPLES:
912 case GL_MAX_INTEGER_SAMPLES:
913 case GL_MAX_DEPTH_TEXTURE_SAMPLES:
914 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
915 case GL_MAX_UNIFORM_BUFFER_BINDINGS:
916 case GL_MAX_COLOR_ATTACHMENTS:
917 case GL_MAX_DRAW_BUFFERS:
918 case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
919 case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
920 case GL_MAX_VERTEX_ATTRIB_BINDINGS:
keunyoungb85b2752013-03-08 12:28:03 -0800921 case GL_TEXTURE_BINDING_2D:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700922 case GL_TEXTURE_BINDING_EXTERNAL_OES: {
923 GLint res;
924 s_glGetIntegerv(ctx, param, &res);
925 *ptr = (GLfloat)res;
keunyoungb85b2752013-03-08 12:28:03 -0800926 break;
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700927 }
keunyoungb85b2752013-03-08 12:28:03 -0800928
929 default:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700930 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
931 if (!state->getClientStateParameter<GLfloat>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700932 ctx->safe_glGetFloatv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800933 }
934 break;
935 }
936}
937
938
939void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
940{
941 GL2Encoder *ctx = (GL2Encoder *)self;
keunyoungb85b2752013-03-08 12:28:03 -0800942 GLClientState* state = ctx->m_state;
943
944 switch (param) {
945 case GL_NUM_SHADER_BINARY_FORMATS:
946 *ptr = GL_FALSE;
947 break;
948 case GL_SHADER_BINARY_FORMATS:
949 // do nothing
950 break;
951
952 case GL_COMPRESSED_TEXTURE_FORMATS: {
953 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
954 if (ctx->m_num_compressedTextureFormats > 0 &&
955 compressedTextureFormats != NULL) {
956 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
957 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
958 }
959 }
960 break;
961 }
962
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700963 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
964 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
965 case GL_MAX_TEXTURE_IMAGE_UNITS:
966 case GL_MAX_VERTEX_ATTRIBS:
967 case GL_MAX_VERTEX_ATTRIB_STRIDE:
968 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
969 case GL_MAX_RENDERBUFFER_SIZE:
970 case GL_MAX_TEXTURE_SIZE:
971 case GL_MAX_3D_TEXTURE_SIZE:
972 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
973 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
974 case GL_MAX_SAMPLES:
975 case GL_MAX_COLOR_TEXTURE_SAMPLES:
976 case GL_MAX_INTEGER_SAMPLES:
977 case GL_MAX_DEPTH_TEXTURE_SAMPLES:
978 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
979 case GL_MAX_UNIFORM_BUFFER_BINDINGS:
980 case GL_MAX_COLOR_ATTACHMENTS:
981 case GL_MAX_DRAW_BUFFERS:
982 case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
983 case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
984 case GL_MAX_VERTEX_ATTRIB_BINDINGS:
keunyoungb85b2752013-03-08 12:28:03 -0800985 case GL_TEXTURE_BINDING_2D:
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700986 case GL_TEXTURE_BINDING_EXTERNAL_OES: {
987 GLint res;
988 s_glGetIntegerv(ctx, param, &res);
989 *ptr = res == 0 ? GL_FALSE : GL_TRUE;
keunyoungb85b2752013-03-08 12:28:03 -0800990 break;
Lingfeng Yanga1edab62018-10-19 07:53:49 -0700991 }
keunyoungb85b2752013-03-08 12:28:03 -0800992
993 default:
Lingfeng Yang83de3d12018-10-17 10:57:53 -0700994 SET_ERROR_IF(!state, GL_INVALID_OPERATION);
995 if (!state->getClientStateParameter<GLboolean>(param, ptr)) {
Lingfeng Yang80a36332017-07-09 10:58:07 -0700996 ctx->safe_glGetBooleanv(param, ptr);
keunyoungb85b2752013-03-08 12:28:03 -0800997 }
bohu05101d22014-11-17 16:28:42 -0800998 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
keunyoungb85b2752013-03-08 12:28:03 -0800999 break;
1000 }
1001}
1002
1003
1004void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
1005{
1006 GL2Encoder *ctx = (GL2Encoder *)self;
1007 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -08001008 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001009 ctx->m_glEnableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -08001010 ctx->m_state->enable(index, 1);
1011}
1012
1013void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
1014{
1015 GL2Encoder *ctx = (GL2Encoder *)self;
1016 assert(ctx->m_state);
Lingfeng Yang07289902017-01-27 12:26:19 -08001017 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001018 ctx->m_glDisableVertexAttribArray_enc(ctx, index);
keunyoungb85b2752013-03-08 12:28:03 -08001019 ctx->m_state->enable(index, 0);
1020}
1021
1022
1023void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
1024{
1025 GL2Encoder *ctx = (GL2Encoder *)self;
1026 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -07001027 GLint maxIndex;
1028 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
1029 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001030
1031 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
1032 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
1033 }
1034}
1035
1036void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
1037{
1038 GL2Encoder *ctx = (GL2Encoder *)self;
1039 assert(ctx->m_state);
Lingfeng Yang0f508082016-04-08 12:38:35 -07001040 GLint maxIndex;
1041 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
1042 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001043
1044 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
1045 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
1046 }
1047}
1048
1049void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
1050{
1051 GL2Encoder *ctx = (GL2Encoder *)self;
1052 if (ctx->m_state == NULL) return;
Lingfeng Yang5e100432016-04-08 12:46:42 -07001053 GLint maxIndex;
1054 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
1055 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
1056 SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
David 'Digit' Turnere01d5f42014-10-30 21:32:28 +01001057 (void)pname;
1058
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001059 *pointer = (GLvoid*)(ctx->m_state->getCurrAttributeBindingInfo(index).offset);
keunyoungb85b2752013-03-08 12:28:03 -08001060}
1061
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001062void GL2Encoder::calcIndexRange(const void* indices,
1063 GLenum type,
1064 GLsizei count,
1065 int* minIndex_out,
1066 int* maxIndex_out) {
1067 switch(type) {
1068 case GL_BYTE:
1069 case GL_UNSIGNED_BYTE:
1070 GLUtils::minmaxExcept(
1071 (unsigned char *)indices, count,
1072 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001073 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned char>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001074 break;
1075 case GL_SHORT:
1076 case GL_UNSIGNED_SHORT:
1077 GLUtils::minmaxExcept(
1078 (unsigned short *)indices, count,
1079 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001080 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned short>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001081 break;
1082 case GL_INT:
1083 case GL_UNSIGNED_INT:
1084 GLUtils::minmaxExcept(
1085 (unsigned int *)indices, count,
1086 minIndex_out, maxIndex_out,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001087 m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned int>());
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001088 break;
1089 default:
1090 ALOGE("unsupported index buffer type %d\n", type);
1091 }
1092}
1093
1094void* GL2Encoder::recenterIndices(const void* src,
1095 GLenum type,
1096 GLsizei count,
1097 int minIndex) {
1098
1099 void* adjustedIndices = (void*)src;
1100
1101 if (minIndex != 0) {
1102 adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count);
1103 switch(type) {
1104 case GL_BYTE:
1105 case GL_UNSIGNED_BYTE:
1106 GLUtils::shiftIndicesExcept(
1107 (unsigned char *)src,
1108 (unsigned char *)adjustedIndices,
1109 count, -minIndex,
1110 m_primitiveRestartEnabled,
1111 (unsigned char)m_primitiveRestartIndex);
1112 break;
1113 case GL_SHORT:
1114 case GL_UNSIGNED_SHORT:
1115 GLUtils::shiftIndicesExcept(
1116 (unsigned short *)src,
1117 (unsigned short *)adjustedIndices,
1118 count, -minIndex,
1119 m_primitiveRestartEnabled,
1120 (unsigned short)m_primitiveRestartIndex);
1121 break;
1122 case GL_INT:
1123 case GL_UNSIGNED_INT:
1124 GLUtils::shiftIndicesExcept(
1125 (unsigned int *)src,
1126 (unsigned int *)adjustedIndices,
1127 count, -minIndex,
1128 m_primitiveRestartEnabled,
1129 (unsigned int)m_primitiveRestartIndex);
1130 break;
1131 default:
1132 ALOGE("unsupported index buffer type %d\n", type);
1133 }
1134 }
1135
1136 return adjustedIndices;
1137}
1138
1139void GL2Encoder::getBufferIndexRange(BufferData* buf,
1140 const void* dataWithOffset,
1141 GLenum type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001142 size_t count,
1143 size_t offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001144 int* minIndex_out,
1145 int* maxIndex_out) {
1146
1147 if (buf->m_indexRangeCache.findRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001148 type, offset, count,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001149 m_primitiveRestartEnabled,
1150 minIndex_out,
1151 maxIndex_out)) {
1152 return;
1153 }
1154
1155 calcIndexRange(dataWithOffset, type, count, minIndex_out, maxIndex_out);
1156
1157 buf->m_indexRangeCache.addRange(
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001158 type, offset, count, m_primitiveRestartEnabled,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001159 *minIndex_out, *maxIndex_out);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001160
1161 ALOGV("%s: got range [%u %u] pr? %d", __FUNCTION__, *minIndex_out, *maxIndex_out, m_primitiveRestartEnabled);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001162}
keunyoungb85b2752013-03-08 12:28:03 -08001163
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001164// For detecting legacy usage of glVertexAttribPointer
1165void GL2Encoder::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) const {
1166 if (hasClientArrays) *hasClientArrays = false;
1167 if (hasVBOs) *hasVBOs = false;
1168
1169 for (int i = 0; i < m_state->nLocations(); i++) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001170 const GLClientState::VertexAttribState& state = m_state->getState(i);
1171 if (state.enabled) {
1172 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
1173 GLuint bufferObject = curr_binding.buffer;
1174 if (bufferObject == 0 && curr_binding.offset && hasClientArrays) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001175 *hasClientArrays = true;
1176 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001177 if (bufferObject != 0 && hasVBOs) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001178 *hasVBOs = true;
1179 }
1180 }
1181 }
1182}
1183
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001184void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count, bool hasClientArrays, GLsizei primcount)
keunyoungb85b2752013-03-08 12:28:03 -08001185{
1186 assert(m_state);
1187
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001188 GLuint currentVao = m_state->currentVertexArrayObject();
Lingfeng Yang398162b2016-05-26 14:18:33 -07001189 GLuint lastBoundVbo = m_state->currentArrayVbo();
keunyoungb85b2752013-03-08 12:28:03 -08001190 for (int i = 0; i < m_state->nLocations(); i++) {
1191 bool enableDirty;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001192 const GLClientState::VertexAttribState& state = m_state->getStateAndEnableDirty(i, &enableDirty);
keunyoungb85b2752013-03-08 12:28:03 -08001193
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001194 if (!enableDirty && !state.enabled) {
keunyoungb85b2752013-03-08 12:28:03 -08001195 continue;
1196 }
1197
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001198 if (state.enabled) {
1199 const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i);
1200 GLuint bufferObject = curr_binding.buffer;
1201 if (hasClientArrays && lastBoundVbo != bufferObject) {
1202 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, bufferObject);
1203 lastBoundVbo = bufferObject;
Lingfeng Yang398162b2016-05-26 14:18:33 -07001204 }
keunyoungb85b2752013-03-08 12:28:03 -08001205
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001206 int divisor = curr_binding.divisor;
1207 int stride = curr_binding.stride;
1208 int effectiveStride = curr_binding.effectiveStride;
1209 uintptr_t offset = curr_binding.offset;
Lingfeng Yang4e5446b2017-02-15 08:44:21 -08001210
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001211 int firstIndex = effectiveStride * first;
Lingfeng Yang4e5446b2017-02-15 08:44:21 -08001212 if (firstIndex && divisor && !primcount) {
1213 // If firstIndex != 0 according to effectiveStride * first,
1214 // it needs to be adjusted if a divisor has been specified,
1215 // even if we are not in glDraw***Instanced.
1216 firstIndex = 0;
1217 }
keunyoungb85b2752013-03-08 12:28:03 -08001218
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001219 if (bufferObject == 0) {
1220 unsigned int datalen = state.elementSize * count;
Yahan Zhoufe1820e2018-12-06 17:18:12 -08001221 if (divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001222 ALOGV("%s: divisor for att %d: %d, w/ stride %d (effective stride %d) size %d type 0x%x) datalen %u",
1223 __FUNCTION__, i, divisor, state.stride, effectiveStride, state.elementSize, state.type, datalen);
1224 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
1225 datalen = state.elementSize * actual_count;
1226 ALOGV("%s: actual datalen %u", __FUNCTION__, datalen);
1227 }
1228 if (state.elementSize == 0) {
Yahan Zhou3f2f1b42016-12-01 13:49:44 -08001229 // The vertex attribute array is uninitialized. Abandon it.
1230 ALOGE("a vertex attribute array is uninitialized. Skipping corresponding vertex attribute.");
1231 this->m_glDisableVertexAttribArray_enc(this, i);
1232 continue;
1233 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001234 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang000cf4c2017-01-25 08:09:02 -08001235
1236 if (datalen && (!offset || !((unsigned char*)offset + firstIndex))) {
1237 ALOGD("%s: bad offset / len!!!!!", __FUNCTION__);
1238 continue;
1239 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001240 if (state.isInt) {
1241 this->glVertexAttribIPointerDataAEMU(this, i, state.size, state.type, stride, (unsigned char *)offset + firstIndex, datalen);
1242 } else {
1243 this->glVertexAttribPointerData(this, i, state.size, state.type, state.normalized, stride, (unsigned char *)offset + firstIndex, datalen);
1244 }
keunyoungb85b2752013-03-08 12:28:03 -08001245 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001246 const BufferData* buf = m_shared->getBufferData(bufferObject);
Yahan Zhou5507c042016-06-01 17:24:28 -07001247 // The following expression actually means bufLen = stride*count;
1248 // But the last element doesn't have to fill up the whole stride.
1249 // So it becomes the current form.
Lingfeng Yang5fe99012017-01-18 09:17:09 -08001250 unsigned int bufLen = effectiveStride * (count ? (count - 1) : 0) + state.elementSize;
Yahan Zhoufe1820e2018-12-06 17:18:12 -08001251 if (divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001252 int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor));
Lingfeng Yang5fe99012017-01-18 09:17:09 -08001253 bufLen = effectiveStride * (actual_count ? (actual_count - 1) : 0) + state.elementSize;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001254 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001255 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001256 if (hasClientArrays) {
1257 m_glEnableVertexAttribArray_enc(this, i);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001258 if (state.isInt) {
1259 this->glVertexAttribIPointerOffsetAEMU(this, i, state.size, state.type, stride, offset + firstIndex);
1260 } else {
1261 this->glVertexAttribPointerOffset(this, i, state.size, state.type, state.normalized, stride, offset + firstIndex);
1262 }
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001263 }
Yahan Zhou5507c042016-06-01 17:24:28 -07001264 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001265 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=%p", buf);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -08001266 if (buf) {
1267 ALOGE("Out of bounds vertex attribute info: "
1268 "clientArray? %d attribute %d vbo %u allocedBufferSize %u bufferDataSpecified? %d wantedStart %u wantedEnd %u",
Lingfeng Yangddfb4452018-09-24 17:26:07 -07001269 hasClientArrays, i, bufferObject, (unsigned int)buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen);
Lingfeng Yang8d9d6c62017-01-18 09:26:19 -08001270 }
1271 m_glDisableVertexAttribArray_enc(this, i);
Yahan Zhou5507c042016-06-01 17:24:28 -07001272 }
keunyoungb85b2752013-03-08 12:28:03 -08001273 }
1274 } else {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001275 if (hasClientArrays) {
1276 this->m_glDisableVertexAttribArray_enc(this, i);
1277 }
keunyoungb85b2752013-03-08 12:28:03 -08001278 }
1279 }
Lingfeng Yang398162b2016-05-26 14:18:33 -07001280
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001281 if (hasClientArrays && lastBoundVbo != m_state->currentArrayVbo()) {
Lingfeng Yang398162b2016-05-26 14:18:33 -07001282 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
1283 }
keunyoungb85b2752013-03-08 12:28:03 -08001284}
1285
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001286void GL2Encoder::flushDrawCall() {
Lingfeng Yang1ebb33c2017-01-19 08:04:48 -08001287 // This used to be every other draw call, but
1288 // now that we are using real GPU buffers on host,
1289 // set this to every 200 draw calls
1290 // (tuned on z840 linux NVIDIA Quadro K2200)
1291 if (m_drawCallFlushCount % 200 == 0) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001292 m_stream->flush();
1293 }
1294 m_drawCallFlushCount++;
1295}
1296
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001297static bool isValidDrawMode(GLenum mode)
1298{
1299 bool retval = false;
1300 switch (mode) {
1301 case GL_POINTS:
1302 case GL_LINE_STRIP:
1303 case GL_LINE_LOOP:
1304 case GL_LINES:
1305 case GL_TRIANGLE_STRIP:
1306 case GL_TRIANGLE_FAN:
1307 case GL_TRIANGLES:
1308 retval = true;
1309 }
1310 return retval;
1311}
1312
keunyoungb85b2752013-03-08 12:28:03 -08001313void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
1314{
1315 GL2Encoder *ctx = (GL2Encoder *)self;
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001316 assert(ctx->m_state != NULL);
1317 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1318 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhoud6217a52016-02-10 16:10:46 -08001319
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001320 bool has_client_vertex_arrays = false;
1321 bool has_indirect_arrays = false;
1322 ctx->getVBOUsage(&has_client_vertex_arrays,
1323 &has_indirect_arrays);
1324
1325 if (has_client_vertex_arrays ||
1326 (!has_client_vertex_arrays &&
1327 !has_indirect_arrays)) {
1328 ctx->sendVertexAttributes(first, count, true);
1329 ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
1330 } else {
1331 ctx->sendVertexAttributes(0, count, false);
1332 ctx->m_glDrawArrays_enc(ctx, mode, first, count);
1333 }
keunyoungb85b2752013-03-08 12:28:03 -08001334}
1335
1336
1337void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
1338{
1339
1340 GL2Encoder *ctx = (GL2Encoder *)self;
1341 assert(ctx->m_state != NULL);
Evan Birenbaumd51386b2016-04-13 12:53:09 -07001342 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
1343 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
Yahan Zhou4520fc92016-04-20 16:02:10 -07001344 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 -08001345 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001346
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001347 bool has_client_vertex_arrays = false;
keunyoungb85b2752013-03-08 12:28:03 -08001348 bool has_indirect_arrays = false;
1349 int nLocations = ctx->m_state->nLocations();
Yahan Zhou5507c042016-06-01 17:24:28 -07001350 GLintptr offset = 0;
keunyoungb85b2752013-03-08 12:28:03 -08001351
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001352 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
keunyoungb85b2752013-03-08 12:28:03 -08001353
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001354 if (!has_client_vertex_arrays && !has_indirect_arrays) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001355 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
Evan Birenbaum82885a62016-04-28 12:47:57 -07001356 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
1357 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001358 }
1359
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001360 BufferData* buf = NULL;
Yahan Zhou5507c042016-06-01 17:24:28 -07001361 int minIndex = 0, maxIndex = 0;
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001362
1363 // For validation/immediate index array purposes,
1364 // we need the min/max vertex index of the index array.
1365 // If the VBO != 0, this may not be the first time we have
1366 // used this particular index buffer. getBufferIndexRange
1367 // can more quickly get min/max vertex index by
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001368 // caching previous results.
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001369 if (ctx->m_state->currentIndexVbo() != 0) {
1370 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1371 offset = (GLintptr)indices;
1372 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
1373 ctx->getBufferIndexRange(buf,
1374 indices,
1375 type,
Lingfeng Yang1ae9d732016-12-12 16:17:02 -08001376 (size_t)count,
1377 (size_t)offset,
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001378 &minIndex, &maxIndex);
1379 } else {
1380 // In this case, the |indices| field holds a real
1381 // array, so calculate the indices now. They will
1382 // also be needed to know how much data to
1383 // transfer to host.
1384 ctx->calcIndexRange(indices,
1385 type,
1386 count,
1387 &minIndex,
1388 &maxIndex);
Yahan Zhou5507c042016-06-01 17:24:28 -07001389 }
1390
Lingfeng Yang26e629a2018-10-13 20:00:12 -07001391 if (count == 0) return;
1392
keunyoungb85b2752013-03-08 12:28:03 -08001393 bool adjustIndices = true;
1394 if (ctx->m_state->currentIndexVbo() != 0) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001395 if (!has_client_vertex_arrays) {
1396 ctx->sendVertexAttributes(0, maxIndex + 1, false);
keunyoungb85b2752013-03-08 12:28:03 -08001397 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
Yahan Zhou5507c042016-06-01 17:24:28 -07001398 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001399 ctx->flushDrawCall();
keunyoungb85b2752013-03-08 12:28:03 -08001400 adjustIndices = false;
1401 } else {
1402 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
1403 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001404 }
1405 }
1406 if (adjustIndices) {
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -07001407 void *adjustedIndices =
1408 ctx->recenterIndices(indices,
1409 type,
1410 count,
1411 minIndex);
keunyoungb85b2752013-03-08 12:28:03 -08001412
keunyoungb85b2752013-03-08 12:28:03 -08001413 if (has_indirect_arrays || 1) {
Lingfeng Yangfe2a31d2016-12-02 08:02:15 -08001414 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
keunyoungb85b2752013-03-08 12:28:03 -08001415 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
1416 count * glSizeof(type));
1417 // XXX - OPTIMIZATION (see the other else branch) should be implemented
1418 if(!has_indirect_arrays) {
1419 //ALOGD("unoptimized drawelements !!!\n");
1420 }
1421 } else {
1422 // we are all direct arrays and immidate mode index array -
1423 // rebuild the arrays and the index array;
1424 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
1425 }
1426 }
1427}
1428
1429
1430GLint * GL2Encoder::getCompressedTextureFormats()
1431{
1432 if (m_compressedTextureFormats == NULL) {
1433 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
1434 &m_num_compressedTextureFormats);
1435 if (m_num_compressedTextureFormats > 0) {
1436 // get number of texture formats;
1437 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
1438 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
1439 }
1440 }
1441 return m_compressedTextureFormats;
1442}
1443
1444// Replace uses of samplerExternalOES with sampler2D, recording the names of
1445// modified shaders in data. Also remove
1446// #extension GL_OES_EGL_image_external : require
1447// statements.
1448//
1449// This implementation assumes the input has already been pre-processed. If not,
1450// a few cases will be mishandled:
1451//
1452// 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
1453// the following code:
1454// #if 1
1455// uniform sampler2D mySampler;
1456// #else
1457// uniform samplerExternalOES mySampler;
1458// #endif
1459//
1460// 2. Comments that look like sampler declarations will be incorrectly modified
1461// and recorded:
1462// // samplerExternalOES hahaFooledYou
1463//
1464// 3. However, GLSL ES does not have a concatentation operator, so things like
1465// this (valid in C) are invalid and not a problem:
1466// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
1467// SAMPLER(ExternalOES, mySampler);
1468//
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001469
1470static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
1471static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
1472static const char STR_DEFINE[] = "#define";
1473
1474static std::vector<std::string> getSamplerExternalAliases(char* str) {
1475 std::vector<std::string> res;
1476
1477 res.push_back(STR_SAMPLER_EXTERNAL_OES);
1478
1479 // -- capture #define x samplerExternalOES
1480 char* c = str;
1481 while ((c = strstr(c, STR_DEFINE))) {
1482 // Don't push it if samplerExternalOES is not even there.
1483 char* samplerExternalOES_next = strstr(c, STR_SAMPLER_EXTERNAL_OES);
1484 if (!samplerExternalOES_next) break;
1485
1486 bool prevIdent = false;
1487
1488 std::vector<std::string> idents;
1489 std::string curr;
1490
1491 while (*c != '\0') {
1492
1493 if (isspace(*c)) {
1494 if (prevIdent) {
1495 idents.push_back(curr);
1496 curr = "";
1497 }
1498 }
1499
1500 if (*c == '\n' || idents.size() == 3) break;
1501
1502 if (isalpha(*c) || *c == '_') {
1503 curr.push_back(*c);
1504 prevIdent = true;
1505 }
1506
1507 ++c;
1508 }
1509
1510 if (idents.size() != 3) continue;
1511
1512 const std::string& defineLhs = idents[1];
1513 const std::string& defineRhs = idents[2];
1514
1515 if (defineRhs == STR_SAMPLER_EXTERNAL_OES) {
1516 res.push_back(defineLhs);
1517 }
1518
1519 if (*c == '\0') break;
1520 }
1521
1522 return res;
1523}
1524
1525static bool replaceExternalSamplerUniformDefinition(char* str, const std::string& samplerExternalType, ShaderData* data) {
1526 // -- replace "samplerExternalOES" with "sampler2D" and record name
1527 char* c = str;
1528 while ((c = strstr(c, samplerExternalType.c_str()))) {
1529 // Make sure "samplerExternalOES" isn't a substring of a larger token
1530 if (c == str || !isspace(*(c-1))) {
1531 c++;
1532 continue;
1533 }
1534 char* sampler_start = c;
1535 c += samplerExternalType.size();
1536 if (!isspace(*c) && *c != '\0') {
1537 continue;
1538 }
1539
1540 // capture sampler name
1541 while (isspace(*c) && *c != '\0') {
1542 c++;
1543 }
1544 if (!isalpha(*c) && *c != '_') {
1545 // not an identifier
1546 return false;
1547 }
1548 char* name_start = c;
1549 do {
1550 c++;
1551 } while (isalnum(*c) || *c == '_');
Lingfeng Yang44209df2018-09-21 10:04:17 -07001552
1553 size_t len = (size_t)(c - name_start);
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001554 data->samplerExternalNames.push_back(
Lingfeng Yang44209df2018-09-21 10:04:17 -07001555 std::string(name_start, len));
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001556
1557 // We only need to perform a string replacement for the original
1558 // occurrence of samplerExternalOES if a #define was used.
1559 //
1560 // The important part was to record the name in
1561 // |data->samplerExternalNames|.
1562 if (samplerExternalType == STR_SAMPLER_EXTERNAL_OES) {
1563 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
1564 }
1565 }
1566
1567 return true;
1568}
1569
keunyoungb85b2752013-03-08 12:28:03 -08001570static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
1571{
1572 static const char STR_HASH_EXTENSION[] = "#extension";
1573 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
Lingfeng Yang3546c4d2018-04-10 12:34:30 -07001574 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3[] = "GL_OES_EGL_image_external_essl3";
keunyoungb85b2752013-03-08 12:28:03 -08001575
1576 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
1577 char* c = str;
1578 while ((c = strstr(c, STR_HASH_EXTENSION))) {
1579 char* start = c;
1580 c += sizeof(STR_HASH_EXTENSION)-1;
1581 while (isspace(*c) && *c != '\0') {
1582 c++;
1583 }
Lingfeng Yang3546c4d2018-04-10 12:34:30 -07001584
1585 bool hasBaseImageExternal =
1586 !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
1587 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL) - 1);
1588 bool hasEssl3ImageExternal =
1589 !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3,
1590 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3) - 1);
1591
1592 if (hasBaseImageExternal || hasEssl3ImageExternal)
keunyoungb85b2752013-03-08 12:28:03 -08001593 {
1594 // #extension statements are terminated by end of line
1595 c = start;
1596 while (*c != '\0' && *c != '\r' && *c != '\n') {
1597 *c++ = ' ';
1598 }
1599 }
1600 }
1601
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001602 std::vector<std::string> samplerExternalAliases =
1603 getSamplerExternalAliases(str);
keunyoungb85b2752013-03-08 12:28:03 -08001604
Lingfeng Yangcc22a7a2018-05-15 12:15:57 -07001605 for (size_t i = 0; i < samplerExternalAliases.size(); i++) {
1606 if (!replaceExternalSamplerUniformDefinition(
1607 str, samplerExternalAliases[i], data))
keunyoungb85b2752013-03-08 12:28:03 -08001608 return false;
keunyoungb85b2752013-03-08 12:28:03 -08001609 }
1610
1611 return true;
1612}
1613
Bo Hu73568cd2015-01-20 16:29:50 -08001614void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
1615{
1616 GL2Encoder* ctx = (GL2Encoder*)self;
1617 // Although it is not supported, need to set proper error code.
1618 SET_ERROR_IF(1, GL_INVALID_ENUM);
1619}
1620
David 'Digit' Turner02fdb692014-10-30 18:07:56 +01001621void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
keunyoungb85b2752013-03-08 12:28:03 -08001622{
1623 GL2Encoder* ctx = (GL2Encoder*)self;
1624 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001625 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(shader), GL_INVALID_VALUE);
Tina Zhang7a84f652014-12-04 12:37:30 +08001626 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
1627 SET_ERROR_IF((count<0), GL_INVALID_VALUE);
keunyoungb85b2752013-03-08 12:28:03 -08001628
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001629 // Track original sources---they may be translated in the backend
1630 std::vector<std::string> orig_sources;
1631 for (int i = 0; i < count; i++) {
1632 orig_sources.push_back(std::string((const char*)(string[i])));
1633 }
1634 shaderData->sources = orig_sources;
1635
keunyoungb85b2752013-03-08 12:28:03 -08001636 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
1637 char *str = new char[len + 1];
1638 glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
1639
1640 // TODO: pre-process str before calling replaceSamplerExternalWith2D().
1641 // Perhaps we can borrow Mesa's pre-processor?
1642
1643 if (!replaceSamplerExternalWith2D(str, shaderData)) {
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001644 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001645 ctx->setError(GL_OUT_OF_MEMORY);
1646 return;
1647 }
keunyoungb85b2752013-03-08 12:28:03 -08001648 ctx->glShaderString(ctx, shader, str, len + 1);
Adam Buchbinder9ae14692016-05-20 15:25:59 -07001649 delete[] str;
keunyoungb85b2752013-03-08 12:28:03 -08001650}
1651
1652void GL2Encoder::s_glFinish(void *self)
1653{
1654 GL2Encoder *ctx = (GL2Encoder *)self;
1655 ctx->glFinishRoundTrip(self);
1656}
1657
1658void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
1659{
1660 GL2Encoder *ctx = (GL2Encoder *)self;
Yahan Zhoub99406c2016-11-22 14:03:56 -08001661 bool isProgram = ctx->m_shared->isProgram(program);
1662 SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE);
1663 SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION);
1664
keunyoungb85b2752013-03-08 12:28:03 -08001665 ctx->m_glLinkProgram_enc(self, program);
1666
1667 GLint linkStatus = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07001668 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001669 if (!linkStatus) {
keunyoungb85b2752013-03-08 12:28:03 -08001670 return;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001671 }
keunyoungb85b2752013-03-08 12:28:03 -08001672
1673 //get number of active uniforms in the program
1674 GLint numUniforms=0;
1675 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
1676 ctx->m_shared->initProgramData(program,numUniforms);
1677
1678 //get the length of the longest uniform name
1679 GLint maxLength=0;
1680 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
1681
1682 GLint size;
1683 GLenum type;
1684 GLchar *name = new GLchar[maxLength+1];
1685 GLint location;
1686 //for each active uniform, get its size and starting location.
1687 for (GLint i=0 ; i<numUniforms ; ++i)
1688 {
1689 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
1690 location = ctx->m_glGetUniformLocation_enc(self, program, name);
1691 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
1692 }
1693 ctx->m_shared->setupLocationShiftWAR(program);
1694
1695 delete[] name;
1696}
1697
1698void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
1699{
1700 GL2Encoder *ctx = (GL2Encoder*)self;
1701 ctx->m_glDeleteProgram_enc(self, program);
1702
1703 ctx->m_shared->deleteProgramData(program);
1704}
1705
1706void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
1707{
1708 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001709 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001710 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001711 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1712 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
1713 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1714 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
1715}
1716void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
1717{
1718 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001719 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
Lingfeng Yang35b0fda2016-04-08 12:21:13 -07001720 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
keunyoungb85b2752013-03-08 12:28:03 -08001721 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
1722 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
1723 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
1724 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
1725}
1726
1727GLuint GL2Encoder::s_glCreateProgram(void * self)
1728{
1729 GL2Encoder *ctx = (GL2Encoder*)self;
1730 GLuint program = ctx->m_glCreateProgram_enc(self);
1731 if (program!=0)
1732 ctx->m_shared->addProgramData(program);
1733 return program;
1734}
1735
1736GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
1737{
1738 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001739 RET_AND_SET_ERROR_IF(!GLESv2Validation::shaderType(ctx, shaderType), GL_INVALID_ENUM, 0);
keunyoungb85b2752013-03-08 12:28:03 -08001740 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
1741 if (shader != 0) {
1742 if (!ctx->m_shared->addShaderData(shader)) {
1743 ctx->m_glDeleteShader_enc(self, shader);
1744 return 0;
1745 }
1746 }
1747 return shader;
1748}
1749
bohu56bf82f2014-10-17 15:35:48 -07001750void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
1751 GLsizei* count, GLuint* shaders)
1752{
1753 GL2Encoder *ctx = (GL2Encoder*)self;
1754 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
1755 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
1756}
1757
1758void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
1759 GLsizei* length, GLchar* source)
1760{
1761 GL2Encoder *ctx = (GL2Encoder*)self;
1762 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1763 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001764 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
1765 if (shaderData) {
1766 std::string returned;
1767 int curr_len = 0;
1768 for (int i = 0; i < shaderData->sources.size(); i++) {
1769 if (curr_len + shaderData->sources[i].size() < bufsize - 1) {
1770 returned += shaderData->sources[i];
1771 } else {
1772 returned += shaderData->sources[i].substr(0, bufsize - 1 - curr_len);
1773 break;
1774 }
1775 }
1776 memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize);
1777 }
bohu56bf82f2014-10-17 15:35:48 -07001778}
1779
1780void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
1781 GLsizei* length, GLchar* infolog)
1782{
1783 GL2Encoder *ctx = (GL2Encoder*)self;
1784 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1785 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
1786}
1787
1788void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
1789 GLsizei* length, GLchar* infolog)
1790{
1791 GL2Encoder *ctx = (GL2Encoder*)self;
1792 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
1793 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
1794}
1795
keunyoungb85b2752013-03-08 12:28:03 -08001796void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
1797{
1798 GL2Encoder *ctx = (GL2Encoder*)self;
1799 ctx->m_glDeleteShader_enc(self,shader);
1800 ctx->m_shared->unrefShaderData(shader);
1801}
1802
1803void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
1804{
1805 GL2Encoder *ctx = (GL2Encoder*)self;
1806 ctx->m_glAttachShader_enc(self, program, shader);
1807 ctx->m_shared->attachShader(program, shader);
1808}
1809
1810void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
1811{
1812 GL2Encoder *ctx = (GL2Encoder*)self;
1813 ctx->m_glDetachShader_enc(self, program, shader);
1814 ctx->m_shared->detachShader(program, shader);
1815}
1816
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001817int sArrIndexOfUniformExpr(const char* name, int* err) {
1818 *err = 0;
1819 int arrIndex = 0;
1820 int namelen = strlen(name);
1821 if (name[namelen-1] == ']') {
1822 const char *brace = strrchr(name,'[');
1823 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
1824 *err = 1; return 0;
1825 }
1826 }
1827 return arrIndex;
1828}
1829
keunyoungb85b2752013-03-08 12:28:03 -08001830int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
1831{
1832 if (!name) return -1;
1833
1834 GL2Encoder *ctx = (GL2Encoder*)self;
1835
1836 // if we need the uniform location WAR
1837 // parse array index from the end of the name string
1838 int arrIndex = 0;
1839 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
1840 if (needLocationWAR) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001841 int err;
1842 arrIndex = sArrIndexOfUniformExpr(name, &err);
1843 if (err) return -1;
keunyoungb85b2752013-03-08 12:28:03 -08001844 }
1845
1846 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
1847 if (hostLoc >= 0 && needLocationWAR) {
1848 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
1849 }
1850 return hostLoc;
1851}
1852
1853bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
1854{
1855 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
1856 return false;
1857
1858 m_state->setActiveTextureUnit(texUnit);
1859
1860 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
1861 if (newTarget != oldTarget) {
1862 if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
1863 m_state->disableTextureTarget(GL_TEXTURE_2D);
1864 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1865 } else {
1866 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
1867 m_state->enableTextureTarget(GL_TEXTURE_2D);
1868 }
1869 m_glActiveTexture_enc(this, texUnit);
1870 m_glBindTexture_enc(this, GL_TEXTURE_2D,
1871 m_state->getBoundTexture(newTarget));
1872 return true;
1873 }
1874
1875 return false;
1876}
1877
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001878void GL2Encoder::updateHostTexture2DBindingsFromProgramData(GLuint program) {
1879 GL2Encoder *ctx = this;
keunyoungb85b2752013-03-08 12:28:03 -08001880 GLClientState* state = ctx->m_state;
1881 GLSharedGroupPtr shared = ctx->m_shared;
1882
keunyoungb85b2752013-03-08 12:28:03 -08001883 GLenum origActiveTexture = state->getActiveTextureUnit();
1884 GLenum hostActiveTexture = origActiveTexture;
1885 GLint samplerIdx = -1;
1886 GLint samplerVal;
1887 GLenum samplerTarget;
1888 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
1889 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
1890 continue;
1891 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001892 samplerTarget))
keunyoungb85b2752013-03-08 12:28:03 -08001893 {
1894 hostActiveTexture = GL_TEXTURE0 + samplerVal;
1895 }
1896 }
1897 state->setActiveTextureUnit(origActiveTexture);
1898 if (hostActiveTexture != origActiveTexture) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001899 ctx->m_glActiveTexture_enc(ctx, origActiveTexture);
keunyoungb85b2752013-03-08 12:28:03 -08001900 }
1901}
1902
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001903void GL2Encoder::s_glUseProgram(void *self, GLuint program)
1904{
1905 GL2Encoder *ctx = (GL2Encoder*)self;
1906 GLSharedGroupPtr shared = ctx->m_shared;
1907
1908 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
1909 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
1910
1911 ctx->m_glUseProgram_enc(self, program);
1912 ctx->m_state->setCurrentProgram(program);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001913 ctx->m_state->setCurrentShaderProgram(program);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08001914
1915 ctx->updateHostTexture2DBindingsFromProgramData(program);
1916}
1917
keunyoungb85b2752013-03-08 12:28:03 -08001918void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
1919{
1920 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001921 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001922 ctx->m_glUniform1f_enc(self, hostLoc, x);
1923}
1924
1925void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1926{
1927 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001928 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001929 ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
1930}
1931
1932void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
1933{
1934 GL2Encoder *ctx = (GL2Encoder*)self;
1935 GLClientState* state = ctx->m_state;
1936 GLSharedGroupPtr shared = ctx->m_shared;
1937
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001938 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001939 ctx->m_glUniform1i_enc(self, hostLoc, x);
1940
1941 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001942 if (shared->setSamplerUniform(state->currentShaderProgram(), location, x, &target)) {
keunyoungb85b2752013-03-08 12:28:03 -08001943 GLenum origActiveTexture = state->getActiveTextureUnit();
1944 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
1945 ctx->m_glActiveTexture_enc(self, origActiveTexture);
1946 }
1947 state->setActiveTextureUnit(origActiveTexture);
1948 }
1949}
1950
1951void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
1952{
1953 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001954 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001955 ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
1956}
1957
1958void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
1959{
1960 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001961 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001962 ctx->m_glUniform2f_enc(self, hostLoc, x, y);
1963}
1964
1965void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1966{
1967 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001968 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001969 ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
1970}
1971
1972void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
1973{
1974 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001975 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001976 ctx->m_glUniform2i_enc(self, hostLoc, x, y);
1977}
1978
1979void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
1980{
1981 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001982 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001983 ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
1984}
1985
1986void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
1987{
1988 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001989 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001990 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
1991}
1992
1993void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
1994{
1995 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08001996 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08001997 ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
1998}
1999
2000void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
2001{
2002 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002003 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002004 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
2005}
2006
2007void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
2008{
2009 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002010 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002011 ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
2012}
2013
2014void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
2015{
2016 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002017 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002018 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
2019}
2020
2021void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
2022{
2023 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002024 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002025 ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
2026}
2027
2028void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
2029{
2030 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002031 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002032 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
2033}
2034
2035void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
2036{
2037 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002038 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002039 ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
2040}
2041
2042void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
2043{
2044 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002045 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002046 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
2047}
2048
2049void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
2050{
2051 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002052 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002053 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
2054}
2055
2056void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
2057{
2058 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002059 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
keunyoungb85b2752013-03-08 12:28:03 -08002060 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
2061}
2062
2063void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
2064{
2065 GL2Encoder* ctx = (GL2Encoder*)self;
2066 GLClientState* state = ctx->m_state;
2067 GLenum err;
2068
2069 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
2070
2071 ctx->m_glActiveTexture_enc(ctx, texture);
2072}
2073
2074void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
2075{
2076 GL2Encoder* ctx = (GL2Encoder*)self;
2077 GLClientState* state = ctx->m_state;
2078 GLenum err;
2079 GLboolean firstUse;
2080
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002081 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
keunyoungb85b2752013-03-08 12:28:03 -08002082 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
2083
2084 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
2085 ctx->m_glBindTexture_enc(ctx, target, texture);
2086 return;
2087 }
2088
2089 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2090
2091 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
2092 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
2093 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
2094 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2095 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
2096 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2097 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
2098 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2099
2100 if (target != priorityTarget) {
2101 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
2102 state->getBoundTexture(GL_TEXTURE_2D));
2103 }
2104 }
2105
2106 if (target == priorityTarget) {
2107 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
2108 }
2109}
2110
2111void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
2112{
2113 GL2Encoder* ctx = (GL2Encoder*)self;
2114 GLClientState* state = ctx->m_state;
2115
2116 state->deleteTextures(n, textures);
2117 ctx->m_glDeleteTextures_enc(ctx, n, textures);
2118}
2119
2120void GL2Encoder::s_glGetTexParameterfv(void* self,
2121 GLenum target, GLenum pname, GLfloat* params)
2122{
2123 GL2Encoder* ctx = (GL2Encoder*)self;
2124 const GLClientState* state = ctx->m_state;
2125
2126 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2127 ctx->override2DTextureTarget(target);
2128 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002129 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002130 } else {
2131 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
2132 }
2133}
2134
2135void GL2Encoder::s_glGetTexParameteriv(void* self,
2136 GLenum target, GLenum pname, GLint* params)
2137{
2138 GL2Encoder* ctx = (GL2Encoder*)self;
2139 const GLClientState* state = ctx->m_state;
2140
2141 switch (pname) {
2142 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
2143 *params = 1;
2144 break;
2145
2146 default:
2147 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2148 ctx->override2DTextureTarget(target);
2149 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002150 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002151 } else {
2152 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
2153 }
2154 break;
2155 }
2156}
2157
2158static bool isValidTextureExternalParam(GLenum pname, GLenum param)
2159{
2160 switch (pname) {
2161 case GL_TEXTURE_MIN_FILTER:
2162 case GL_TEXTURE_MAG_FILTER:
2163 return param == GL_NEAREST || param == GL_LINEAR;
2164
2165 case GL_TEXTURE_WRAP_S:
2166 case GL_TEXTURE_WRAP_T:
2167 return param == GL_CLAMP_TO_EDGE;
2168
2169 default:
2170 return true;
2171 }
2172}
2173
2174void GL2Encoder::s_glTexParameterf(void* self,
2175 GLenum target, GLenum pname, GLfloat param)
2176{
2177 GL2Encoder* ctx = (GL2Encoder*)self;
2178 const GLClientState* state = ctx->m_state;
2179
2180 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2181 !isValidTextureExternalParam(pname, (GLenum)param)),
2182 GL_INVALID_ENUM);
2183
2184 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2185 ctx->override2DTextureTarget(target);
2186 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002187 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002188 } else {
2189 ctx->m_glTexParameterf_enc(ctx, target, pname, param);
2190 }
2191}
2192
2193void GL2Encoder::s_glTexParameterfv(void* self,
2194 GLenum target, GLenum pname, const GLfloat* params)
2195{
2196 GL2Encoder* ctx = (GL2Encoder*)self;
2197 const GLClientState* state = ctx->m_state;
2198
2199 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2200 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2201 GL_INVALID_ENUM);
2202
2203 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2204 ctx->override2DTextureTarget(target);
2205 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002206 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002207 } else {
2208 ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
2209 }
2210}
2211
2212void GL2Encoder::s_glTexParameteri(void* self,
2213 GLenum target, GLenum pname, GLint param)
2214{
2215 GL2Encoder* ctx = (GL2Encoder*)self;
2216 const GLClientState* state = ctx->m_state;
2217
2218 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2219 !isValidTextureExternalParam(pname, (GLenum)param)),
2220 GL_INVALID_ENUM);
2221
2222 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2223 ctx->override2DTextureTarget(target);
2224 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002225 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002226 } else {
2227 ctx->m_glTexParameteri_enc(ctx, target, pname, param);
2228 }
2229}
2230
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002231static int ilog2(uint32_t x) {
2232 int p = 0;
2233 while ((1 << p) < x)
2234 p++;
2235 return p;
2236}
2237
bohu26a92982014-11-25 16:50:37 -08002238void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
2239 GLint internalformat, GLsizei width, GLsizei height, GLint border,
2240 GLenum format, GLenum type, const GLvoid* pixels)
2241{
2242 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang69066602016-04-12 09:29:11 -07002243 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002244
2245 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2246 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2247 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2248 // If unpack buffer is nonzero, verify unmapped state.
2249 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2250
2251 GLint max_texture_size;
2252 GLint max_cube_map_texture_size;
2253 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2254 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2255 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2256 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2257 SET_ERROR_IF((target == GL_TEXTURE_CUBE_MAP) &&
2258 (level > ilog2(max_cube_map_texture_size)), GL_INVALID_VALUE);
2259 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2260 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
2261 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
2262 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && width > max_cube_map_texture_size, GL_INVALID_VALUE);
2263 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && height > max_cube_map_texture_size, GL_INVALID_VALUE);
2264 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
2265 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2266 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2267 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2268 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 0) >
2269 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2270 GL_INVALID_OPERATION);
2271 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2272 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2273 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2274 glSizeof(type)),
2275 GL_INVALID_OPERATION);
2276 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2277 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2278 ((uintptr_t)pixels % glSizeof(type)),
2279 GL_INVALID_OPERATION);
2280 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
2281
2282 GLenum stateTarget = target;
2283 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
2284 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
2285 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
2286 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
2287 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
2288 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2289 stateTarget = GL_TEXTURE_CUBE_MAP;
2290
2291 state->setBoundTextureInternalFormat(stateTarget, internalformat);
2292 state->setBoundTextureFormat(stateTarget, format);
2293 state->setBoundTextureType(stateTarget, type);
2294 state->setBoundTextureDims(stateTarget, level, width, height, 1);
2295
bohu26a92982014-11-25 16:50:37 -08002296 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2297 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002298 }
Lingfeng Yang69066602016-04-12 09:29:11 -07002299
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002300 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2301 ctx->glTexImage2DOffsetAEMU(
2302 ctx, target, level, internalformat,
2303 width, height, border,
2304 format, type, (uintptr_t)pixels);
bohu26a92982014-11-25 16:50:37 -08002305 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002306 ctx->m_glTexImage2D_enc(
2307 ctx, target, level, internalformat,
2308 width, height, border,
2309 format, type, pixels);
2310 }
2311
2312 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2313 ctx->restore2DTextureTarget(target);
bohu26a92982014-11-25 16:50:37 -08002314 }
2315}
2316
Yahan Zhou2a208292016-06-22 15:36:04 -07002317void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
2318 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
2319 GLenum type, const GLvoid* pixels)
2320{
2321 GL2Encoder* ctx = (GL2Encoder*)self;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002322 GLClientState* state = ctx->m_state;
2323
2324 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
2325 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
2326 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
2327 // If unpack buffer is nonzero, verify unmapped state.
2328 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
2329
2330 GLint max_texture_size;
2331 GLint max_cube_map_texture_size;
2332 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
2333 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
2334 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
2335 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
2336 SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) &&
2337 level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
2338 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
2339 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
2340
2341 GLuint tex = state->getBoundTexture(target);
2342 GLsizei neededWidth = xoffset + width;
2343 GLsizei neededHeight = yoffset + height;
2344 GLsizei neededDepth = 1;
2345
2346 if (tex && !state->queryTexEGLImageBacked(tex)) {
2347 SET_ERROR_IF(
2348 (neededWidth > state->queryTexWidth(level, tex) ||
2349 neededHeight > state->queryTexHeight(level, tex) ||
2350 neededDepth > state->queryTexDepth(level, tex)),
2351 GL_INVALID_VALUE);
2352 }
2353
2354 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
2355 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2356 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2357 (state->pboNeededDataSize(width, height, 1, format, type, 0) >
2358 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
2359 GL_INVALID_OPERATION);
2360 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
2361 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
2362 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
2363 glSizeof(type)),
2364 GL_INVALID_OPERATION);
2365 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !pixels, GL_INVALID_OPERATION);
Yahan Zhou2a208292016-06-22 15:36:04 -07002366
2367 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2368 ctx->override2DTextureTarget(target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002369 }
2370
2371 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
2372 ctx->glTexSubImage2DOffsetAEMU(
2373 ctx, target, level,
2374 xoffset, yoffset, width, height,
2375 format, type, (uintptr_t)pixels);
Yahan Zhou2a208292016-06-22 15:36:04 -07002376 } else {
2377 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
2378 height, format, type, pixels);
2379 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002380
2381 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2382 ctx->restore2DTextureTarget(target);
2383 }
Yahan Zhou2a208292016-06-22 15:36:04 -07002384}
bohu26a92982014-11-25 16:50:37 -08002385
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002386void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
2387 GLenum internalformat, GLint x, GLint y,
2388 GLsizei width, GLsizei height, GLint border)
2389{
2390 GL2Encoder* ctx = (GL2Encoder*)self;
2391 GLClientState* state = ctx->m_state;
2392
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002393 SET_ERROR_IF(ctx->glCheckFramebufferStatus(ctx, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
2394 GL_INVALID_FRAMEBUFFER_OPERATION);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002395 // This is needed to work around underlying OpenGL drivers
2396 // (such as those feeding some some AMD GPUs) that expect
2397 // positive components of cube maps to be defined _before_
2398 // the negative components (otherwise a segfault occurs).
2399 GLenum extraTarget =
2400 state->copyTexImageLuminanceCubeMapAMDWorkaround
2401 (target, level, internalformat);
2402
2403 if (extraTarget) {
2404 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
2405 x, y, width, height, border);
2406 }
2407
2408 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
2409 x, y, width, height, border);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002410
2411 state->setBoundTextureInternalFormat(target, internalformat);
2412 state->setBoundTextureDims(target, level, width, height, 1);
Lingfeng Yange00ec9d2016-09-16 08:54:03 -07002413}
2414
keunyoungb85b2752013-03-08 12:28:03 -08002415void GL2Encoder::s_glTexParameteriv(void* self,
2416 GLenum target, GLenum pname, const GLint* params)
2417{
2418 GL2Encoder* ctx = (GL2Encoder*)self;
2419 const GLClientState* state = ctx->m_state;
2420
2421 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
2422 !isValidTextureExternalParam(pname, (GLenum)params[0])),
2423 GL_INVALID_ENUM);
2424
2425 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
2426 ctx->override2DTextureTarget(target);
2427 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002428 ctx->restore2DTextureTarget(target);
keunyoungb85b2752013-03-08 12:28:03 -08002429 } else {
2430 ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
2431 }
2432}
2433
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002434bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
2435 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
2436 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
2437}
2438
keunyoungb85b2752013-03-08 12:28:03 -08002439void GL2Encoder::override2DTextureTarget(GLenum target)
2440{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002441 if (texture2DNeedsOverride(target)) {
2442 m_glBindTexture_enc(this, GL_TEXTURE_2D,
2443 m_state->getBoundTexture(target));
keunyoungb85b2752013-03-08 12:28:03 -08002444 }
2445}
2446
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002447void GL2Encoder::restore2DTextureTarget(GLenum target)
keunyoungb85b2752013-03-08 12:28:03 -08002448{
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002449 if (texture2DNeedsOverride(target)) {
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002450 GLuint priorityEnabledBoundTexture =
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002451 m_state->getBoundTexture(
Lingfeng Yang5bbf5292017-04-24 18:52:56 -07002452 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D));
2453 GLuint texture2DBoundTexture =
2454 m_state->getBoundTexture(GL_TEXTURE_2D);
2455 if (!priorityEnabledBoundTexture) {
2456 m_glBindTexture_enc(this, GL_TEXTURE_2D, texture2DBoundTexture);
2457 } else {
2458 m_glBindTexture_enc(this, GL_TEXTURE_2D, priorityEnabledBoundTexture);
2459 }
Lingfeng Yangb5c03d52016-09-07 14:40:03 -07002460 }
keunyoungb85b2752013-03-08 12:28:03 -08002461}
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002462
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002463void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
2464 m_state->setBoundEGLImage(target, eglImage);
2465}
2466
2467
2468GLuint GL2Encoder::boundBuffer(GLenum target) const {
2469 return m_state->getBuffer(target);
2470}
2471
2472BufferData* GL2Encoder::getBufferData(GLenum target) const {
2473 GLuint bufferId = m_state->getBuffer(target);
2474 if (!bufferId) return NULL;
2475 return m_shared->getBufferData(bufferId);
2476}
2477
2478BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const {
2479 if (!bufferId) return NULL;
2480 return m_shared->getBufferData(bufferId);
2481}
2482
2483bool GL2Encoder::isBufferMapped(GLuint buffer) const {
2484 return m_shared->getBufferData(buffer)->m_mapped;
2485}
2486
2487bool GL2Encoder::isBufferTargetMapped(GLenum target) const {
2488 BufferData* buf = getBufferData(target);
2489 if (!buf) return false;
2490 return buf->m_mapped;
2491}
2492
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002493void GL2Encoder::s_glGenRenderbuffers(void* self,
2494 GLsizei n, GLuint* renderbuffers) {
2495 GL2Encoder* ctx = (GL2Encoder*)self;
2496 GLClientState* state = ctx->m_state;
2497
2498 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2499
2500 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
2501 state->addRenderbuffers(n, renderbuffers);
2502}
2503
2504void GL2Encoder::s_glDeleteRenderbuffers(void* self,
2505 GLsizei n, const GLuint* renderbuffers) {
2506 GL2Encoder* ctx = (GL2Encoder*)self;
2507 GLClientState* state = ctx->m_state;
2508
2509 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2510
2511 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002512
2513 // Nope, lets just leak those for now.
2514 // The spec has an *amazingly* convoluted set of conditions for when
2515 // render buffers are actually deleted:
2516 // 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.
2517 //
2518 // 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***
2519 //
2520 // So, just detach this one from the bound FBO, and ignore the rest.
2521 for (int i = 0; i < n; i++) {
2522 state->detachRbo(renderbuffers[i]);
2523 }
2524 // state->removeRenderbuffers(n, renderbuffers);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002525}
2526
2527void GL2Encoder::s_glBindRenderbuffer(void* self,
2528 GLenum target, GLuint renderbuffer) {
2529 GL2Encoder* ctx = (GL2Encoder*)self;
2530 GLClientState* state = ctx->m_state;
2531
2532 SET_ERROR_IF((target != GL_RENDERBUFFER),
2533 GL_INVALID_ENUM);
2534
2535 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
2536 state->bindRenderbuffer(target, renderbuffer);
2537}
2538
Lingfeng Yang69066602016-04-12 09:29:11 -07002539void GL2Encoder::s_glRenderbufferStorage(void* self,
2540 GLenum target, GLenum internalformat,
2541 GLsizei width, GLsizei height) {
2542 GL2Encoder* ctx = (GL2Encoder*) self;
2543 GLClientState* state = ctx->m_state;
2544
2545 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002546 SET_ERROR_IF(
2547 !GLESv2Validation::rboFormat(ctx, internalformat),
2548 GL_INVALID_ENUM);
Lingfeng Yang69066602016-04-12 09:29:11 -07002549
2550 state->setBoundRenderbufferFormat(internalformat);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002551 state->setBoundRenderbufferSamples(0);
2552
Lingfeng Yang69066602016-04-12 09:29:11 -07002553 ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
2554 width, height);
2555}
2556
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002557void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
2558 GLenum target, GLenum attachment,
2559 GLenum renderbuffertarget, GLuint renderbuffer) {
2560 GL2Encoder* ctx = (GL2Encoder*)self;
2561 GLClientState* state = ctx->m_state;
2562
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002563 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2564 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2565 state->attachRbo(target, attachment, renderbuffer);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002566
2567 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
2568}
2569
2570void GL2Encoder::s_glGenFramebuffers(void* self,
2571 GLsizei n, GLuint* framebuffers) {
2572 GL2Encoder* ctx = (GL2Encoder*)self;
2573 GLClientState* state = ctx->m_state;
2574
2575 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2576
2577 ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
2578 state->addFramebuffers(n, framebuffers);
2579}
2580
2581void GL2Encoder::s_glDeleteFramebuffers(void* self,
2582 GLsizei n, const GLuint* framebuffers) {
2583 GL2Encoder* ctx = (GL2Encoder*)self;
2584 GLClientState* state = ctx->m_state;
2585
2586 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2587
2588 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
2589 state->removeFramebuffers(n, framebuffers);
2590}
2591
2592void GL2Encoder::s_glBindFramebuffer(void* self,
2593 GLenum target, GLuint framebuffer) {
2594 GL2Encoder* ctx = (GL2Encoder*)self;
2595 GLClientState* state = ctx->m_state;
2596
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002597 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002598
2599 state->bindFramebuffer(target, framebuffer);
2600
2601 ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
2602}
2603
2604void GL2Encoder::s_glFramebufferTexture2D(void* self,
2605 GLenum target, GLenum attachment,
2606 GLenum textarget, GLuint texture, GLint level) {
2607 GL2Encoder* ctx = (GL2Encoder*)self;
2608 GLClientState* state = ctx->m_state;
2609
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002610 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2611 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
2612 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002613
2614 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
2615}
2616
2617void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
2618 GLenum target, GLenum attachment,
2619 GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
2620 GL2Encoder* ctx = (GL2Encoder*)self;
2621 GLClientState* state = ctx->m_state;
2622
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002623 state->attachTextureObject(target, attachment, texture);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002624
2625 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
2626}
2627
2628void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
2629 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
2630 GL2Encoder* ctx = (GL2Encoder*)self;
2631 const GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002632 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
2633 SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2634 pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE &&
2635 !state->attachmentHasObject(target, attachment),
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002636 GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002637 SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL ||
2638 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE ||
2639 pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) &&
2640 (!state->attachmentHasObject(target, attachment) ||
2641 state->getBoundFramebufferAttachmentType(target, attachment) !=
2642 FBO_ATTACHMENT_TEXTURE),
2643 !state->attachmentHasObject(target, attachment) ?
2644 GL_INVALID_OPERATION : GL_INVALID_ENUM);
2645 SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2646 pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
2647 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
2648 state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
2649 GL_INVALID_OPERATION);
2650 SET_ERROR_IF(state->boundFramebuffer(target) &&
2651 (attachment == GL_BACK ||
2652 attachment == GL_FRONT),
2653 GL_INVALID_OPERATION);
Lingfeng Yang57cb41b2016-04-08 14:42:34 -07002654 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
2655}
Lingfeng Yang69066602016-04-12 09:29:11 -07002656
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002657bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state,
Lingfeng Yang69066602016-04-12 09:29:11 -07002658 GLenum attachment) const {
2659 FboFormatInfo fbo_format_info;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002660 state->getBoundFramebufferFormat(target, attachment, &fbo_format_info);
Lingfeng Yang69066602016-04-12 09:29:11 -07002661
2662 bool res;
2663 switch (fbo_format_info.type) {
2664 case FBO_ATTACHMENT_RENDERBUFFER:
2665 switch (fbo_format_info.rb_format) {
2666 case GL_R16F:
2667 case GL_RG16F:
Lingfeng Yang69066602016-04-12 09:29:11 -07002668 case GL_RGBA16F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002669 case GL_R32F:
2670 case GL_RG32F:
2671 case GL_RGBA32F:
2672 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002673 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002674 break;
2675 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002676 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang69066602016-04-12 09:29:11 -07002677 break;
2678 case GL_STENCIL_INDEX8:
2679 if (attachment == GL_STENCIL_ATTACHMENT) {
2680 res = true;
2681 } else {
2682 res = false;
2683 }
2684 break;
2685 default:
2686 res = true;
2687 }
2688 break;
2689 case FBO_ATTACHMENT_TEXTURE:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002690 switch (fbo_format_info.tex_internalformat) {
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002691 case GL_R16F:
2692 case GL_RG16F:
2693 case GL_RGBA16F:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002694 case GL_R32F:
2695 case GL_RG32F:
2696 case GL_RGBA32F:
Lingfeng Yang931817b2017-01-27 06:50:56 -08002697 case GL_R11F_G11F_B10F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002698 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002699 break;
2700 case GL_RGB16F:
Lingfeng Yangc92685e2017-01-30 20:06:39 -08002701 res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float");
Lingfeng Yang931817b2017-01-27 06:50:56 -08002702 break;
2703 case GL_RED:
2704 case GL_RG:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002705 case GL_SRGB8:
2706 case GL_RGB32UI:
2707 case GL_RGB16UI:
2708 case GL_RGB8UI:
2709 case GL_RGB32I:
2710 case GL_RGB16I:
2711 case GL_RGB8I:
2712 case GL_R8_SNORM:
2713 case GL_RG8_SNORM:
2714 case GL_RGB8_SNORM:
2715 case GL_RGBA8_SNORM:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002716 res = false;
2717 break;
Lingfeng Yang69066602016-04-12 09:29:11 -07002718 // No float/half-float formats allowed for RGB(A)
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002719 case GL_RGB:
2720 case GL_RGBA:
Lingfeng Yang69066602016-04-12 09:29:11 -07002721 switch (fbo_format_info.tex_type) {
2722 case GL_FLOAT:
2723 case GL_HALF_FLOAT_OES:
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002724 case GL_UNSIGNED_INT_10F_11F_11F_REV:
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002725 case GL_UNSIGNED_INT_2_10_10_10_REV:
Lingfeng Yang69066602016-04-12 09:29:11 -07002726 res = false;
2727 break;
2728 default:
2729 res = true;
2730 }
Yahan Zhou68bfd8c2016-05-11 15:06:34 -07002731 break;
2732 default:
Lingfeng Yang69066602016-04-12 09:29:11 -07002733 res = true;
2734 }
2735 break;
2736 case FBO_ATTACHMENT_NONE:
2737 res = true;
2738 break;
2739 default:
2740 res = true;
2741 }
2742 return res;
2743}
2744
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002745bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const {
2746 bool res = true;
2747
2748 for (int i = 0; i < state->getMaxColorAttachments(); i++) {
2749 res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i));
2750 }
2751
2752 res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT);
2753 res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT);
2754
2755 return res;
2756}
2757
Lingfeng Yang69066602016-04-12 09:29:11 -07002758GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
2759 GL2Encoder* ctx = (GL2Encoder*)self;
2760 GLClientState* state = ctx->m_state;
2761
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002762 bool fboCompleteByCodec =
2763 ctx->checkFramebufferCompleteness(target, state);
2764
2765 if (!fboCompleteByCodec) {
2766 state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
Lingfeng Yang69066602016-04-12 09:29:11 -07002767 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2768 } else {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002769 // double check with underlying opengl to avoid craziness.
Lingfeng Yang69066602016-04-12 09:29:11 -07002770 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002771 state->setCheckFramebufferStatus(target, host_checkstatus);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08002772 if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE;
Lingfeng Yang69066602016-04-12 09:29:11 -07002773 return host_checkstatus;
2774 }
2775}
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002776
2777void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) {
2778 GL2Encoder* ctx = (GL2Encoder*)self;
2779 GLClientState* state = ctx->m_state;
2780 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2781
2782 ctx->m_glGenVertexArrays_enc(self, n, arrays);
2783 for (int i = 0; i < n; i++) {
2784 ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]);
2785 }
2786 state->addVertexArrayObjects(n, arrays);
2787}
2788
2789void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) {
2790 GL2Encoder* ctx = (GL2Encoder*)self;
2791 GLClientState* state = ctx->m_state;
2792 SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
2793
2794 ctx->m_glDeleteVertexArrays_enc(self, n, arrays);
2795 for (int i = 0; i < n; i++) {
2796 ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]);
2797 }
2798 state->removeVertexArrayObjects(n, arrays);
2799}
2800
2801void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) {
2802 ALOGV("%s: call. array=%u\n", __FUNCTION__, array);
2803 GL2Encoder* ctx = (GL2Encoder*)self;
2804 GLClientState* state = ctx->m_state;
2805 SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION);
2806 ctx->m_glBindVertexArray_enc(self, array);
2807 state->setVertexArrayObject(array);
2808}
2809
Lingfeng Yangfb3d2bb2017-09-07 15:02:04 -07002810void* GL2Encoder::s_glMapBufferOES(void* self, GLenum target, GLenum access) {
2811 GL2Encoder* ctx = (GL2Encoder*)self;
2812
2813 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2814
2815 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2816
2817 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2818
2819 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2820 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2821
2822 return ctx->glMapBufferRange(ctx, target, 0, buf->m_size, access);
2823}
2824
2825GLboolean GL2Encoder::s_glUnmapBufferOES(void* self, GLenum target) {
2826 GL2Encoder* ctx = (GL2Encoder*)self;
2827
2828 return ctx->glUnmapBuffer(ctx, target);
2829}
2830
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07002831void* GL2Encoder::s_glMapBufferRangeAEMUImpl(GL2Encoder* ctx, GLenum target,
2832 GLintptr offset, GLsizeiptr length,
2833 GLbitfield access, BufferData* buf) {
2834 char* bits = (char*)buf->m_fixedBuffer.ptr() + offset;
2835
2836 ctx->glMapBufferRangeAEMU(
2837 ctx, target,
2838 offset, length,
2839 access,
2840 bits);
2841
2842 return bits;
2843}
2844
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002845void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
2846 GL2Encoder* ctx = (GL2Encoder*)self;
2847 GLClientState* state = ctx->m_state;
2848
2849 // begin validation (lots)
2850
2851 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
2852
2853 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2854
2855 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
2856
2857 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2858 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
2859
2860 GLsizeiptr bufferDataSize = buf->m_size;
2861
2862 RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL);
2863 RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL);
2864 RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL);
2865 RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL);
2866
2867 RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL);
2868 RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL);
2869 RET_AND_SET_ERROR_IF(
2870 (access & GL_MAP_READ_BIT) &&
2871 ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
2872 (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
2873 (access & GL_MAP_UNSYNCHRONIZED_BIT) ||
2874 (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL);
2875
2876 // end validation; actually do stuff now
2877
2878 buf->m_mapped = true;
2879 buf->m_mappedAccess = access;
2880 buf->m_mappedOffset = offset;
2881 buf->m_mappedLength = length;
2882
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07002883 if (ctx->hasExtension("ANDROID_EMU_dma_v2")) {
2884 if (buf->dma_buffer.get().size < length) {
2885 goldfish_dma_context region;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002886
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07002887 const int PAGE_BITS = 12;
2888 GLsizeiptr aligned_length = (length + (1 << PAGE_BITS) - 1) & ~((1 << PAGE_BITS) - 1);
2889
2890 if (goldfish_dma_create_region(aligned_length, &region)) {
2891 buf->dma_buffer.reset(NULL);
2892 return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
2893 }
2894
2895 if (!goldfish_dma_map(&region)) {
2896 buf->dma_buffer.reset(NULL);
2897 return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
2898 }
2899
2900 buf->m_guest_paddr = goldfish_dma_guest_paddr(&region);
2901 buf->dma_buffer.reset(&region);
2902 }
2903
2904 ctx->glMapBufferRangeDMA(
2905 ctx, target,
2906 offset, length,
2907 access,
2908 buf->m_guest_paddr);
2909
2910 return reinterpret_cast<void*>(buf->dma_buffer.get().mapped_addr);
Roman Kiryanovdaecd142018-11-14 14:56:27 -08002911 } else if (ctx->hasExtension("ANDROID_EMU_direct_mem")) {
2912 GoldfishAddressSpaceBlock new_shared_block;
2913
2914 if (new_shared_block.allocate(&ctx->m_goldfish_address_block_provider, length)) {
2915 uint64_t gpu_addr =
2916 ctx->glMapBufferRangeDirect(ctx,
2917 target,
2918 offset,
2919 length,
2920 access,
2921 new_shared_block.physAddr());
2922 if (gpu_addr) {
2923 void *user_ptr = new_shared_block.mmap(gpu_addr);
2924 if (user_ptr) {
2925 buf->shared_block.replace(&new_shared_block);
2926 return user_ptr;
2927 } else {
2928 GLboolean host_res = GL_TRUE;
2929
2930 ctx->glUnmapBufferDirect(
2931 ctx, target,
2932 offset,
2933 length,
2934 access,
2935 new_shared_block.physAddr(),
2936 gpu_addr,
2937 &host_res);
2938
2939 return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
2940 }
2941 } else {
2942 return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
2943 }
2944 } else {
2945 return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
2946 }
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07002947 } else {
2948 return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
2949 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002950}
2951
2952GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
2953 GL2Encoder* ctx = (GL2Encoder*)self;
2954 GLClientState* state = ctx->m_state;
2955
2956 RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE);
2957
2958 GLuint boundBuffer = ctx->m_state->getBuffer(target);
2959
2960 RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE);
2961
2962 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
2963 RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE);
2964 RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE);
2965
Lingfeng Yang423129e2017-01-18 09:23:12 -08002966 if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
2967 // invalide index range cache here
2968 if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) {
2969 buf->m_indexRangeCache.invalidateRange(0, buf->m_size);
2970 } else {
2971 buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength);
2972 }
2973 }
2974
Lingfeng Yang46153ab2017-01-09 13:37:22 -08002975 GLboolean host_res = GL_TRUE;
2976
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07002977 if (buf->dma_buffer.get().mapped_addr) {
2978 memcpy(static_cast<char*>(buf->m_fixedBuffer.ptr()) + buf->m_mappedOffset,
2979 reinterpret_cast<void*>(buf->dma_buffer.get().mapped_addr),
2980 buf->m_mappedLength);
2981
2982 ctx->glUnmapBufferDMA(
Roman Kiryanovdaecd142018-11-14 14:56:27 -08002983 ctx, target,
2984 buf->m_mappedOffset,
2985 buf->m_mappedLength,
2986 buf->m_mappedAccess,
2987 goldfish_dma_guest_paddr(&buf->dma_buffer.get()),
2988 &host_res);
2989 } else if (buf->shared_block.guestPtr()) {
2990 GoldfishAddressSpaceBlock *shared_block = &buf->shared_block;
2991
2992 memcpy(static_cast<char*>(buf->m_fixedBuffer.ptr()) + buf->m_mappedOffset,
2993 shared_block->guestPtr(),
2994 buf->m_mappedLength);
2995
2996 ctx->glUnmapBufferDirect(
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07002997 ctx, target,
2998 buf->m_mappedOffset,
2999 buf->m_mappedLength,
3000 buf->m_mappedAccess,
Roman Kiryanovdaecd142018-11-14 14:56:27 -08003001 shared_block->physAddr(),
3002 shared_block->hostAddr(),
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07003003 &host_res);
Roman Kiryanovdaecd142018-11-14 14:56:27 -08003004
3005 shared_block->replace(NULL);
Roman Kiryanovbe1c0c22018-10-02 18:07:14 -07003006 } else {
3007 ctx->glUnmapBufferAEMU(
3008 ctx, target,
3009 buf->m_mappedOffset,
3010 buf->m_mappedLength,
3011 buf->m_mappedAccess,
3012 (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
3013 &host_res);
3014 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003015
3016 buf->m_mapped = false;
3017 buf->m_mappedAccess = 0;
3018 buf->m_mappedOffset = 0;
3019 buf->m_mappedLength = 0;
3020
3021 return host_res;
3022}
3023
3024void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) {
3025 GL2Encoder* ctx = (GL2Encoder*)self;
3026 GLClientState* state = ctx->m_state;
3027
3028 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3029
3030 GLuint boundBuffer = ctx->m_state->getBuffer(target);
3031 SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION);
3032
3033 BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
3034 SET_ERROR_IF(!buf, GL_INVALID_VALUE);
3035 SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION);
3036 SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION);
3037
3038 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
3039 SET_ERROR_IF(length < 0, GL_INVALID_VALUE);
3040 SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE);
3041
3042 GLintptr totalOffset = buf->m_mappedOffset + offset;
Lingfeng Yang423129e2017-01-18 09:23:12 -08003043
3044 buf->m_indexRangeCache.invalidateRange(totalOffset, length);
3045
Roman Kiryanovdaecd142018-11-14 14:56:27 -08003046 if (buf->shared_block.guestPtr()) {
3047 ctx->glFlushMappedBufferRangeDirect(
3048 ctx, target,
3049 totalOffset,
3050 length,
3051 buf->m_mappedAccess);
3052 } else {
3053 ctx->glFlushMappedBufferRangeAEMU(
3054 ctx, target,
3055 totalOffset,
3056 length,
3057 buf->m_mappedAccess,
3058 (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
3059 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003060}
3061
3062void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
3063 GL2Encoder* ctx = (GL2Encoder*)self;
3064 GLClientState* state = ctx->m_state;
3065
3066 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3067 // Filter compressed formats support.
3068 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3069 // Verify level <= log2(GL_MAX_TEXTURE_SIZE).
3070 GLint max_texture_size;
3071 GLint max_cube_map_texture_size;
3072 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3073 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
3074 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3075 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3076 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
3077 SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE);
3078 SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE);
3079 SET_ERROR_IF(border, GL_INVALID_VALUE);
3080 // If unpack buffer is nonzero, verify unmapped state.
3081 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3082 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
3083 // If unpack buffer is nonzero, verify buffer data fits.
3084 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3085 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3086 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3087 GL_INVALID_OPERATION);
3088 // TODO: Fix:
3089 // If |imageSize| is inconsistent with compressed dimensions.
3090 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE);
3091
3092 GLenum stateTarget = target;
3093 if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
3094 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
3095 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
3096 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
3097 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
3098 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
3099 stateTarget = GL_TEXTURE_CUBE_MAP;
3100 state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
3101 state->setBoundTextureDims(stateTarget, level, width, height, 1);
3102
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003103 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
3104 ctx->override2DTextureTarget(target);
3105 }
3106
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003107 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3108 ctx->glCompressedTexImage2DOffsetAEMU(
3109 ctx, target, level, internalformat,
3110 width, height, border,
3111 imageSize, (uintptr_t)data);
3112 } else {
3113 ctx->m_glCompressedTexImage2D_enc(
3114 ctx, target, level, internalformat,
3115 width, height, border,
3116 imageSize, data);
3117 }
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003118
3119 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
3120 ctx->restore2DTextureTarget(target);
3121 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003122}
3123
3124void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
3125 GL2Encoder* ctx = (GL2Encoder*)self;
3126 GLClientState* state = ctx->m_state;
3127
3128 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3129 // If unpack buffer is nonzero, verify unmapped state.
3130 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3131 GLint max_texture_size;
3132 GLint max_cube_map_texture_size;
3133 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3134 ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
3135 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3136 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3137 SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE);
3138 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
3139 // If unpack buffer is nonzero, verify buffer data fits.
3140 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3141 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3142 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3143 GL_INVALID_OPERATION);
3144 SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
3145
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003146 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
3147 ctx->override2DTextureTarget(target);
3148 }
3149
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003150 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3151 ctx->glCompressedTexSubImage2DOffsetAEMU(
3152 ctx, target, level,
3153 xoffset, yoffset,
3154 width, height, format,
3155 imageSize, (uintptr_t)data);
3156 } else {
3157 ctx->m_glCompressedTexSubImage2D_enc(
3158 ctx, target, level,
3159 xoffset, yoffset,
3160 width, height, format,
3161 imageSize, data);
3162 }
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003163
3164 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
3165 ctx->restore2DTextureTarget(target);
3166 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003167}
3168
3169void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
3170 GL2Encoder* ctx = (GL2Encoder*)self;
3171 GLClientState* state = ctx->m_state;
3172
3173 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3174
3175 // Only works with certain targets
3176 SET_ERROR_IF(
3177 !(target == GL_ATOMIC_COUNTER_BUFFER ||
3178 target == GL_SHADER_STORAGE_BUFFER ||
3179 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
3180 target == GL_UNIFORM_BUFFER),
3181 GL_INVALID_ENUM);
3182
3183 // Can't exceed range
3184 SET_ERROR_IF(index < 0 ||
3185 index >= state->getMaxIndexedBufferBindings(target),
3186 GL_INVALID_VALUE);
3187 SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE);
3188 SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER ||
3189 target == GL_TRANSFORM_FEEDBACK_BUFFER) &&
3190 (size % 4 || offset % 4),
3191 GL_INVALID_VALUE);
3192
3193 GLint ssbo_offset_align, ubo_offset_align;
3194 ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align);
3195 ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align);
3196 SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER &&
3197 offset % ssbo_offset_align,
3198 GL_INVALID_VALUE);
3199 SET_ERROR_IF(target == GL_UNIFORM_BUFFER &&
3200 offset % ubo_offset_align,
3201 GL_INVALID_VALUE);
3202
3203 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003204 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003205 state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0);
3206 ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size);
3207}
3208
3209void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) {
3210 GL2Encoder* ctx = (GL2Encoder*)self;
3211 GLClientState* state = ctx->m_state;
3212
3213 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3214
3215 // Only works with certain targets
3216 SET_ERROR_IF(
3217 !(target == GL_ATOMIC_COUNTER_BUFFER ||
3218 target == GL_SHADER_STORAGE_BUFFER ||
3219 target == GL_TRANSFORM_FEEDBACK_BUFFER ||
3220 target == GL_UNIFORM_BUFFER),
3221 GL_INVALID_ENUM);
3222 // Can't exceed range
3223 SET_ERROR_IF(index < 0 ||
3224 index >= state->getMaxIndexedBufferBindings(target),
3225 GL_INVALID_VALUE);
3226
3227 state->bindBuffer(target, buffer);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003228 ctx->m_state->addBuffer(buffer);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003229 BufferData* buf = ctx->getBufferDataById(buffer);
3230 state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0);
3231 ctx->m_glBindBufferBase_enc(self, target, index, buffer);
3232}
3233
3234void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
3235 GL2Encoder* ctx = (GL2Encoder*)self;
3236 GLClientState* state = ctx->m_state;
3237
3238 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM);
3239 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM);
3240 SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER ||
3241 readtarget == GL_DISPATCH_INDIRECT_BUFFER ||
3242 readtarget == GL_DRAW_INDIRECT_BUFFER ||
3243 readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
3244 SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER ||
3245 writetarget == GL_DISPATCH_INDIRECT_BUFFER ||
3246 writetarget == GL_DRAW_INDIRECT_BUFFER ||
3247 writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM);
3248 SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION);
3249 SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION);
3250 SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION);
3251 SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION);
3252 SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE);
3253 SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE);
3254 SET_ERROR_IF(size < 0, GL_INVALID_VALUE);
3255 SET_ERROR_IF(
3256 ctx->getBufferData(readtarget) &&
3257 (readoffset + size > ctx->getBufferData(readtarget)->m_size),
3258 GL_INVALID_VALUE);
3259 SET_ERROR_IF(
3260 ctx->getBufferData(writetarget) &&
3261 (writeoffset + size > ctx->getBufferData(writetarget)->m_size),
3262 GL_INVALID_VALUE);
3263 SET_ERROR_IF(readtarget == writetarget &&
3264 !((writeoffset >= readoffset + size) ||
3265 (readoffset >= writeoffset + size)),
3266 GL_INVALID_VALUE);
3267
3268 ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size);
3269}
3270
3271void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) {
3272 GL2Encoder* ctx = (GL2Encoder*)self;
3273
3274 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3275 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003276 target != GL_ARRAY_BUFFER &&
3277 target != GL_ELEMENT_ARRAY_BUFFER &&
3278 target != GL_COPY_READ_BUFFER &&
3279 target != GL_COPY_WRITE_BUFFER &&
3280 target != GL_PIXEL_PACK_BUFFER &&
3281 target != GL_PIXEL_UNPACK_BUFFER &&
3282 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
3283 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003284 GL_INVALID_ENUM);
3285 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
3286 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003287 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
3288 pname != GL_BUFFER_MAPPED &&
3289 pname != GL_BUFFER_SIZE &&
3290 pname != GL_BUFFER_USAGE &&
3291 pname != GL_BUFFER_MAP_LENGTH &&
3292 pname != GL_BUFFER_MAP_OFFSET,
3293 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003294
3295 if (!params) return;
3296
3297 BufferData* buf = ctx->getBufferData(target);
3298
3299 switch (pname) {
3300 case GL_BUFFER_ACCESS_FLAGS:
3301 *params = buf ? buf->m_mappedAccess : 0;
3302 break;
3303 case GL_BUFFER_MAPPED:
3304 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3305 break;
3306 case GL_BUFFER_SIZE:
3307 *params = buf ? buf->m_size : 0;
3308 break;
3309 case GL_BUFFER_USAGE:
3310 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3311 break;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003312 case GL_BUFFER_MAP_LENGTH:
3313 *params = buf ? buf->m_mappedLength : 0;
3314 break;
3315 case GL_BUFFER_MAP_OFFSET:
3316 *params = buf ? buf->m_mappedOffset : 0;
3317 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003318 default:
3319 break;
3320 }
3321}
3322
3323void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) {
3324 GL2Encoder* ctx = (GL2Encoder*)self;
3325
3326 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3327 SET_ERROR_IF(
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003328 target != GL_ARRAY_BUFFER &&
3329 target != GL_ELEMENT_ARRAY_BUFFER &&
3330 target != GL_COPY_READ_BUFFER &&
3331 target != GL_COPY_WRITE_BUFFER &&
3332 target != GL_PIXEL_PACK_BUFFER &&
3333 target != GL_PIXEL_UNPACK_BUFFER &&
3334 target != GL_TRANSFORM_FEEDBACK_BUFFER &&
3335 target != GL_UNIFORM_BUFFER,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003336 GL_INVALID_ENUM);
3337 SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM);
3338 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003339 SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS &&
3340 pname != GL_BUFFER_MAPPED &&
3341 pname != GL_BUFFER_SIZE &&
3342 pname != GL_BUFFER_USAGE &&
3343 pname != GL_BUFFER_MAP_LENGTH &&
3344 pname != GL_BUFFER_MAP_OFFSET,
3345 GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003346
3347 if (!params) return;
3348
3349 BufferData* buf = ctx->getBufferData(target);
3350
3351 switch (pname) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003352 case GL_BUFFER_ACCESS_FLAGS:
3353 *params = buf ? buf->m_mappedAccess : 0;
3354 break;
3355 case GL_BUFFER_MAPPED:
3356 *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE;
3357 break;
3358 case GL_BUFFER_SIZE:
3359 *params = buf ? buf->m_size : 0;
3360 break;
3361 case GL_BUFFER_USAGE:
3362 *params = buf ? buf->m_usage : GL_STATIC_DRAW;
3363 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003364 case GL_BUFFER_MAP_LENGTH:
3365 *params = buf ? buf->m_mappedLength : 0;
3366 break;
3367 case GL_BUFFER_MAP_OFFSET:
3368 *params = buf ? buf->m_mappedOffset : 0;
3369 break;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003370 default:
3371 break;
3372 }
3373}
3374
3375void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) {
3376 GL2Encoder* ctx = (GL2Encoder*)self;
3377 SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM);
3378 SET_ERROR_IF(
3379 target == GL_ATOMIC_COUNTER_BUFFER ||
3380 target == GL_DISPATCH_INDIRECT_BUFFER ||
3381 target == GL_DRAW_INDIRECT_BUFFER ||
3382 target == GL_SHADER_STORAGE_BUFFER,
3383 GL_INVALID_ENUM);
3384 SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM);
3385 SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION);
3386 if (!params) return;
3387
3388 BufferData* buf = ctx->getBufferData(target);
3389
3390 if (!buf || !buf->m_mapped) { *params = NULL; return; }
3391
3392 *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
3393}
3394
3395static const char* const kNameDelimiter = ";";
3396
3397static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) {
3398
3399#define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \
3400
3401 std::string packed;
3402 // validate the array of char[]'s
3403 const char* currName;
3404 for (GLsizei i = 0; i < count; i++) {
3405 currName = names[i];
3406 VALIDATE(!currName, GL_INVALID_OPERATION);
3407 // check if has reasonable size
3408 size_t len = strlen(currName);
3409 VALIDATE(!len, GL_INVALID_OPERATION);
3410 // check for our delimiter, which if present
3411 // in the name, means an invalid name anyway.
3412 VALIDATE(strstr(currName, kNameDelimiter),
3413 GL_INVALID_OPERATION);
3414 packed += currName;
3415 packed += ";";
3416 }
3417
3418 *err_out = GL_NO_ERROR;
3419 return packed;
3420}
3421
3422void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) {
3423 GL2Encoder* ctx = (GL2Encoder*)self;
3424
3425 if (!uniformCount) return;
3426
3427 GLint err = GL_NO_ERROR;
3428 std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err);
3429 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3430
3431 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
3432 std::vector<int> arrIndices;
3433 for (size_t i = 0; i < uniformCount; i++) {
3434 int err;
3435 arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err));
3436 if (err) {
3437 ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]);
3438 return;
3439 }
3440 }
3441
3442 ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices);
3443
3444 for (int i = 0; i < uniformCount; i++) {
3445 if (uniformIndices[i] >= 0 && needLocationWAR) {
3446 uniformIndices[i] =
3447 ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]);
3448 }
3449 }
3450}
3451
3452void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) {
3453 GL2Encoder *ctx = (GL2Encoder*)self;
3454 GLClientState* state = ctx->m_state;
3455 GLSharedGroupPtr shared = ctx->m_shared;
3456
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003457 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003458 ctx->m_glUniform1ui_enc(self, hostLoc, v0);
3459
3460 GLenum target;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003461 if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003462 GLenum origActiveTexture = state->getActiveTextureUnit();
3463 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
3464 ctx->m_glActiveTexture_enc(self, origActiveTexture);
3465 }
3466 state->setActiveTextureUnit(origActiveTexture);
3467 }
3468}
3469
3470void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) {
3471 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003472 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003473 ctx->m_glUniform2ui_enc(self, hostLoc, v0, v1);
3474}
3475
3476void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) {
3477 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003478 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003479 ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2);
3480}
3481
3482void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) {
3483 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003484 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003485 ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3);
3486}
3487
3488void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3489 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003490 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003491 ctx->m_glUniform1uiv_enc(self, hostLoc, count, value);
3492}
3493
3494void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3495 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003496 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003497 ctx->m_glUniform2uiv_enc(self, hostLoc, count, value);
3498}
3499
3500void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3501 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003502 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003503 ctx->m_glUniform3uiv_enc(self, hostLoc, count, value);
3504}
3505
3506void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) {
3507 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003508 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003509 ctx->m_glUniform4uiv_enc(self, hostLoc, count, value);
3510}
3511
3512void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3513 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003514 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003515 ctx->m_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value);
3516}
3517
3518void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3519 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003520 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003521 ctx->m_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value);
3522}
3523
3524void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3525 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003526 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003527 ctx->m_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value);
3528}
3529
3530void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3531 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003532 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003533 ctx->m_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value);
3534}
3535
3536void GL2Encoder::s_glUniformMatrix3x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3537 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003538 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003539 ctx->m_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value);
3540}
3541
3542void GL2Encoder::s_glUniformMatrix4x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
3543 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08003544 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003545 ctx->m_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value);
3546}
3547
3548void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) {
3549 GL2Encoder *ctx = (GL2Encoder*)self;
3550 SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
3551 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
3552 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
3553 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
3554 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
3555 ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params);
3556}
3557
3558void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
3559 GL2Encoder* ctx = (GL2Encoder*)self;
3560 GLClientState* state = ctx->m_state;
3561
3562 // refresh client state's # active uniforms in this block
3563 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
3564 // TODO if worth it: cache uniform count and other params,
3565 // invalidate on program relinking.
3566 GLint numActiveUniforms;
3567 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3568 program, uniformBlockIndex,
3569 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
3570 &numActiveUniforms);
3571 ctx->m_state->setNumActiveUniformsInUniformBlock(
3572 program, uniformBlockIndex, numActiveUniforms);
3573 }
3574
3575 ctx->m_glGetActiveUniformBlockiv_enc(ctx,
3576 program, uniformBlockIndex,
3577 pname, params);
3578}
3579
3580void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) {
3581 GL2Encoder *ctx = (GL2Encoder *)self;
3582 assert(ctx->m_state);
3583 GLint maxIndex;
3584 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3585 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3586
3587 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
3588 ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params);
3589 }
3590}
3591
3592void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) {
3593 GL2Encoder *ctx = (GL2Encoder *)self;
3594 assert(ctx->m_state);
3595 GLint maxIndex;
3596 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
3597 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
3598
3599 if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) {
3600 ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params);
3601 }
3602}
3603
3604void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
3605 GL2Encoder *ctx = (GL2Encoder *)self;
3606 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003607 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003608 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
3609 SET_ERROR_IF(
3610 !(type == GL_BYTE ||
3611 type == GL_UNSIGNED_BYTE ||
3612 type == GL_SHORT ||
3613 type == GL_UNSIGNED_SHORT ||
3614 type == GL_INT ||
3615 type == GL_UNSIGNED_INT),
3616 GL_INVALID_ENUM);
3617 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
3618
3619 ctx->m_state->setVertexAttribBinding(index, index);
3620 ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true);
3621 GLsizei effectiveStride = stride;
3622 if (stride == 0) {
3623 effectiveStride = glSizeof(type) * size;
3624 }
3625 ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride);
3626
3627 if (ctx->m_state->currentArrayVbo() != 0) {
3628 ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer);
3629 } else {
3630 SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION);
3631 // wait for client-array handler
3632 }
3633}
3634
3635void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) {
3636 GL2Encoder *ctx = (GL2Encoder *)self;
3637 assert(ctx->m_state != NULL);
Lingfeng Yang07289902017-01-27 12:26:19 -08003638 VALIDATE_VERTEX_ATTRIB_INDEX(index);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003639 ctx->m_state->setVertexAttribBinding(index, index);
3640 ctx->m_state->setVertexBindingDivisor(index, divisor);
3641 ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor);
3642}
3643
3644void GL2Encoder::s_glRenderbufferStorageMultisample(void* self,
3645 GLenum target, GLsizei samples, GLenum internalformat,
3646 GLsizei width, GLsizei height) {
3647 GL2Encoder *ctx = (GL2Encoder *)self;
3648 GLClientState* state = ctx->m_state;
3649
3650 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
3651 SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM);
3652
3653 GLint max_samples;
3654 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
3655 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
3656
3657 state->setBoundRenderbufferFormat(internalformat);
3658 state->setBoundRenderbufferSamples(samples);
3659 ctx->m_glRenderbufferStorageMultisample_enc(
3660 self, target, samples, internalformat, width, height);
3661}
3662
3663void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) {
3664 GL2Encoder* ctx = (GL2Encoder*)self;
3665 SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION);
3666 SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE);
3667 for (int i = 0; i < n; i++) {
3668 SET_ERROR_IF(
3669 bufs[i] != GL_NONE &&
3670 bufs[i] != GL_BACK &&
3671 glUtilsColorAttachmentIndex(bufs[i]) == -1,
3672 GL_INVALID_ENUM);
3673 SET_ERROR_IF(
3674 !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3675 glUtilsColorAttachmentIndex(bufs[i]) != -1,
3676 GL_INVALID_OPERATION);
3677 SET_ERROR_IF(
3678 ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
3679 ((glUtilsColorAttachmentIndex(bufs[i]) != -1 &&
3680 glUtilsColorAttachmentIndex(bufs[i]) != i) ||
3681 (glUtilsColorAttachmentIndex(bufs[i]) == -1 &&
3682 bufs[i] != GL_NONE)),
3683 GL_INVALID_OPERATION);
3684 }
3685
3686 ctx->m_glDrawBuffers_enc(ctx, n, bufs);
3687}
3688
3689void GL2Encoder::s_glReadBuffer(void* self, GLenum src) {
3690 GL2Encoder* ctx = (GL2Encoder*)self;
3691
3692 SET_ERROR_IF(
3693 glUtilsColorAttachmentIndex(src) != -1 &&
3694 (glUtilsColorAttachmentIndex(src) >=
3695 ctx->m_state->getMaxColorAttachments()),
3696 GL_INVALID_OPERATION);
3697 SET_ERROR_IF(
3698 src != GL_NONE &&
3699 src != GL_BACK &&
3700 src > GL_COLOR_ATTACHMENT0 &&
3701 src < GL_DEPTH_ATTACHMENT &&
3702 (src - GL_COLOR_ATTACHMENT0) >
3703 ctx->m_state->getMaxColorAttachments(),
3704 GL_INVALID_OPERATION);
3705 SET_ERROR_IF(
3706 src != GL_NONE &&
3707 src != GL_BACK &&
3708 glUtilsColorAttachmentIndex(src) == -1,
3709 GL_INVALID_ENUM);
3710 SET_ERROR_IF(
3711 !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3712 src != GL_NONE &&
3713 src != GL_BACK,
3714 GL_INVALID_OPERATION);
3715 SET_ERROR_IF(
3716 ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
3717 src != GL_NONE &&
3718 glUtilsColorAttachmentIndex(src) == -1,
3719 GL_INVALID_OPERATION);
3720
3721 ctx->m_glReadBuffer_enc(ctx, src);
3722}
3723
3724void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
3725 GL2Encoder* ctx = (GL2Encoder*)self;
3726 GLClientState* state = ctx->m_state;
3727
3728 SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM);
3729 SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM);
3730 GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture);
3731 SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY &&
3732 lastBoundTarget != GL_TEXTURE_3D,
3733 GL_INVALID_OPERATION);
3734 state->attachTextureObject(target, attachment, texture);
3735
3736 GLint max3DTextureSize;
3737 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
3738 SET_ERROR_IF(
3739 layer >= max3DTextureSize,
3740 GL_INVALID_VALUE);
3741
3742 ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer);
3743}
3744
3745void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
3746 GL2Encoder* ctx = (GL2Encoder*)self;
3747 GLClientState* state = ctx->m_state;
3748
3749 SET_ERROR_IF(
3750 target != GL_TEXTURE_2D &&
3751 target != GL_TEXTURE_CUBE_MAP,
3752 GL_INVALID_ENUM);
3753 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
3754 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
3755 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
3756 SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1,
3757 GL_INVALID_OPERATION);
3758 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3759
3760 state->setBoundTextureInternalFormat(target, internalformat);
3761 state->setBoundTextureDims(target, -1, width, height, 1);
3762 state->setBoundTextureImmutableFormat(target);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003763
3764 if (target == GL_TEXTURE_2D) {
3765 ctx->override2DTextureTarget(target);
3766 }
3767
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003768 ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08003769
3770 if (target == GL_TEXTURE_2D) {
3771 ctx->restore2DTextureTarget(target);
3772 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08003773}
3774
3775void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
3776 GL2Encoder* ctx = (GL2Encoder*)self;
3777
3778 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
3779
3780 GLint maxCount = 0;
3781 ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);
3782
3783 SET_ERROR_IF(
3784 bufferMode == GL_SEPARATE_ATTRIBS &&
3785 maxCount < count,
3786 GL_INVALID_VALUE);
3787 SET_ERROR_IF(
3788 bufferMode != GL_INTERLEAVED_ATTRIBS &&
3789 bufferMode != GL_SEPARATE_ATTRIBS,
3790 GL_INVALID_ENUM);
3791
3792 if (!count) return;
3793
3794 GLint err = GL_NO_ERROR;
3795 std::string packed = packVarNames(count, varyings, &err);
3796 SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION);
3797
3798 ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode);
3799}
3800
3801void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) {
3802 GL2Encoder* ctx = (GL2Encoder*)self;
3803 GLClientState* state = ctx->m_state;
3804 ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode);
3805 state->setTransformFeedbackActiveUnpaused(true);
3806}
3807
3808void GL2Encoder::s_glEndTransformFeedback(void* self) {
3809 GL2Encoder* ctx = (GL2Encoder*)self;
3810 GLClientState* state = ctx->m_state;
3811 ctx->m_glEndTransformFeedback_enc(ctx);
3812 state->setTransformFeedbackActiveUnpaused(false);
3813}
3814
3815void GL2Encoder::s_glPauseTransformFeedback(void* self) {
3816 GL2Encoder* ctx = (GL2Encoder*)self;
3817 GLClientState* state = ctx->m_state;
3818 ctx->m_glPauseTransformFeedback_enc(ctx);
3819 state->setTransformFeedbackActiveUnpaused(false);
3820}
3821
3822void GL2Encoder::s_glResumeTransformFeedback(void* self) {
3823 GL2Encoder* ctx = (GL2Encoder*)self;
3824 GLClientState* state = ctx->m_state;
3825 ctx->m_glResumeTransformFeedback_enc(ctx);
3826 state->setTransformFeedbackActiveUnpaused(true);
3827}
3828
3829void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat,
3830 GLsizei width, GLsizei height, GLsizei depth,
3831 GLint border, GLenum format, GLenum type, const GLvoid* data) {
3832 GL2Encoder* ctx = (GL2Encoder*)self;
3833 GLClientState* state = ctx->m_state;
3834
3835 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3836 target != GL_TEXTURE_2D_ARRAY,
3837 GL_INVALID_ENUM);
3838 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3839 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3840
3841 // If unpack buffer is nonzero, verify unmapped state.
3842 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3843
3844 GLint max_texture_size;
3845 GLint max_3d_texture_size;
3846 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3847 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3848 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3849 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3850 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3851
3852 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3853 SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3854 SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3855 SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
3856 SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3857 SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3858 SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE);
3859 SET_ERROR_IF(border != 0, GL_INVALID_VALUE);
3860 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3861 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3862 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3863 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3864 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3865 GL_INVALID_OPERATION);
3866 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3867 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3868 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3869 glSizeof(type)),
3870 GL_INVALID_OPERATION);
3871 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
3872
3873 state->setBoundTextureInternalFormat(target, internalFormat);
3874 state->setBoundTextureFormat(target, format);
3875 state->setBoundTextureType(target, type);
3876 state->setBoundTextureDims(target, level, width, height, depth);
3877
3878 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3879 ctx->glTexImage3DOffsetAEMU(
3880 ctx, target, level, internalFormat,
3881 width, height, depth,
3882 border, format, type, (uintptr_t)data);
3883 } else {
3884 ctx->m_glTexImage3D_enc(ctx,
3885 target, level, internalFormat,
3886 width, height, depth,
3887 border, format, type, data);
3888 }
3889}
3890
3891void 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) {
3892 GL2Encoder* ctx = (GL2Encoder*)self;
3893 GLClientState* state = ctx->m_state;
3894
3895 SET_ERROR_IF(target != GL_TEXTURE_3D &&
3896 target != GL_TEXTURE_2D_ARRAY,
3897 GL_INVALID_ENUM);
3898 SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM);
3899 SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM);
3900 // If unpack buffer is nonzero, verify unmapped state.
3901 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3902 GLint max_texture_size;
3903 GLint max_3d_texture_size;
3904 ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size);
3905 ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size);
3906 SET_ERROR_IF(level < 0, GL_INVALID_VALUE);
3907 SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE);
3908 SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE);
3909 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3910 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3911 GLuint tex = state->getBoundTexture(target);
3912 GLsizei neededWidth = xoffset + width;
3913 GLsizei neededHeight = yoffset + height;
3914 GLsizei neededDepth = zoffset + depth;
3915
3916 SET_ERROR_IF(tex &&
3917 (neededWidth > state->queryTexWidth(level, tex) ||
3918 neededHeight > state->queryTexHeight(level, tex) ||
3919 neededDepth > state->queryTexDepth(level, tex)),
3920 GL_INVALID_VALUE);
3921 // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
3922 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3923 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3924 (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) >
3925 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3926 GL_INVALID_OPERATION);
3927 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3928 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3929 (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size %
3930 glSizeof(type)),
3931 GL_INVALID_OPERATION);
3932 SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION);
3933 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3934
3935 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3936 ctx->glTexSubImage3DOffsetAEMU(ctx,
3937 target, level,
3938 xoffset, yoffset, zoffset,
3939 width, height, depth,
3940 format, type, (uintptr_t)data);
3941 } else {
3942 ctx->m_glTexSubImage3D_enc(ctx,
3943 target, level,
3944 xoffset, yoffset, zoffset,
3945 width, height, depth,
3946 format, type, data);
3947 }
3948}
3949
3950void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
3951 GL2Encoder* ctx = (GL2Encoder*)self;
3952 GLClientState* state = ctx->m_state;
3953
3954 // Filter compressed formats support.
3955 SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM);
3956 // If unpack buffer is nonzero, verify unmapped state.
3957 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3958 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3959 SET_ERROR_IF(border, GL_INVALID_VALUE);
3960 // If unpack buffer is nonzero, verify buffer data fits.
3961 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3962 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3963 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3964 GL_INVALID_OPERATION);
3965 // TODO: Fix:
3966 // If |imageSize| is too small for compressed dimensions.
3967 // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE);
3968 state->setBoundTextureInternalFormat(target, (GLint)internalformat);
3969 state->setBoundTextureDims(target, level, width, height, depth);
3970
3971 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
3972 ctx->glCompressedTexImage3DOffsetAEMU(
3973 ctx, target, level, internalformat,
3974 width, height, depth, border,
3975 imageSize, (uintptr_t)data);
3976 } else {
3977 ctx->m_glCompressedTexImage3D_enc(
3978 ctx, target, level, internalformat,
3979 width, height, depth, border,
3980 imageSize, data);
3981 }
3982}
3983
3984void 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) {
3985 GL2Encoder* ctx = (GL2Encoder*)self;
3986 GLClientState* state = ctx->m_state;
3987
3988 SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM);
3989 // If unpack buffer is nonzero, verify unmapped state.
3990 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION);
3991 SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE);
3992 // If unpack buffer is nonzero, verify buffer data fits.
3993 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
3994 ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
3995 (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
3996 GL_INVALID_OPERATION);
3997 SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE);
3998
3999 if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
4000 ctx->glCompressedTexSubImage3DOffsetAEMU(
4001 ctx, target, level,
4002 xoffset, yoffset, zoffset,
4003 width, height, depth,
4004 format, imageSize, (uintptr_t)data);
4005 } else {
4006 ctx->m_glCompressedTexSubImage3D_enc(
4007 ctx, target, level,
4008 xoffset, yoffset, zoffset,
4009 width, height, depth,
4010 format, imageSize, data);
4011
4012 }
4013}
4014
4015void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
4016 GL2Encoder* ctx = (GL2Encoder*)self;
4017 GLClientState* state = ctx->m_state;
4018 SET_ERROR_IF(target != GL_TEXTURE_3D &&
4019 target != GL_TEXTURE_2D_ARRAY,
4020 GL_INVALID_ENUM);
4021 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
4022 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
4023 SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE);
4024 SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1),
4025 GL_INVALID_OPERATION);
4026 SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1),
4027 GL_INVALID_OPERATION);
4028 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
4029
4030 state->setBoundTextureInternalFormat(target, internalformat);
4031 state->setBoundTextureDims(target, -1, width, height, depth);
4032 state->setBoundTextureImmutableFormat(target);
4033 ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth);
4034 state->setBoundTextureImmutableFormat(target);
4035}
4036
4037void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
4038 GL2Encoder *ctx = (GL2Encoder *)self;
4039 assert(ctx->m_state != NULL);
4040 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
4041 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
4042
4043 bool has_client_vertex_arrays = false;
4044 bool has_indirect_arrays = false;
4045 ctx->getVBOUsage(&has_client_vertex_arrays,
4046 &has_indirect_arrays);
4047
4048 if (has_client_vertex_arrays ||
4049 (!has_client_vertex_arrays &&
4050 !has_indirect_arrays)) {
4051 ctx->sendVertexAttributes(first, count, true, primcount);
4052 ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount);
4053 } else {
4054 ctx->sendVertexAttributes(0, count, false, primcount);
4055 ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount);
4056 }
4057 ctx->m_stream->flush();
4058}
4059
4060void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount)
4061{
4062
4063 GL2Encoder *ctx = (GL2Encoder *)self;
4064 assert(ctx->m_state != NULL);
4065 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
4066 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
4067 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
4068 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
4069
4070 bool has_client_vertex_arrays = false;
4071 bool has_indirect_arrays = false;
4072 int nLocations = ctx->m_state->nLocations();
4073 GLintptr offset = 0;
4074
4075 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
4076
4077 if (!has_client_vertex_arrays && !has_indirect_arrays) {
4078 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
4079 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
4080 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
4081 }
4082
4083 BufferData* buf = NULL;
4084 int minIndex = 0, maxIndex = 0;
4085
4086 // For validation/immediate index array purposes,
4087 // we need the min/max vertex index of the index array.
4088 // If the VBO != 0, this may not be the first time we have
4089 // used this particular index buffer. getBufferIndexRange
4090 // can more quickly get min/max vertex index by
4091 // caching previous results.
4092 if (ctx->m_state->currentIndexVbo() != 0) {
4093 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
4094 offset = (GLintptr)indices;
4095 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
4096 ctx->getBufferIndexRange(buf,
4097 indices,
4098 type,
4099 (size_t)count,
4100 (size_t)offset,
4101 &minIndex, &maxIndex);
4102 } else {
4103 // In this case, the |indices| field holds a real
4104 // array, so calculate the indices now. They will
4105 // also be needed to know how much data to
4106 // transfer to host.
4107 ctx->calcIndexRange(indices,
4108 type,
4109 count,
4110 &minIndex,
4111 &maxIndex);
4112 }
4113
Lingfeng Yang26e629a2018-10-13 20:00:12 -07004114 if (count == 0) return;
4115
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004116 bool adjustIndices = true;
4117 if (ctx->m_state->currentIndexVbo() != 0) {
4118 if (!has_client_vertex_arrays) {
4119 ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount);
4120 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
4121 ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount);
4122 ctx->flushDrawCall();
4123 adjustIndices = false;
4124 } else {
4125 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
4126 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
4127 }
4128 }
4129 if (adjustIndices) {
4130 void *adjustedIndices =
4131 ctx->recenterIndices(indices,
4132 type,
4133 count,
4134 minIndex);
4135
4136 if (has_indirect_arrays || 1) {
4137 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount);
4138 ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type));
4139 ctx->m_stream->flush();
4140 // XXX - OPTIMIZATION (see the other else branch) should be implemented
4141 if(!has_indirect_arrays) {
4142 //ALOGD("unoptimized drawelements !!!\n");
4143 }
4144 } else {
4145 // we are all direct arrays and immidate mode index array -
4146 // rebuild the arrays and the index array;
4147 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
4148 }
4149 }
4150}
4151
4152void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
4153{
4154
4155 GL2Encoder *ctx = (GL2Encoder *)self;
4156 assert(ctx->m_state != NULL);
4157 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
4158 SET_ERROR_IF(end < start, GL_INVALID_VALUE);
4159 SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
4160 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
4161 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
4162
4163 bool has_client_vertex_arrays = false;
4164 bool has_indirect_arrays = false;
4165 int nLocations = ctx->m_state->nLocations();
4166 GLintptr offset = 0;
4167
4168 ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays);
4169
4170 if (!has_client_vertex_arrays && !has_indirect_arrays) {
4171 // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n");
4172 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
4173 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
4174 }
4175
4176 BufferData* buf = NULL;
4177 int minIndex = 0, maxIndex = 0;
4178
4179 // For validation/immediate index array purposes,
4180 // we need the min/max vertex index of the index array.
4181 // If the VBO != 0, this may not be the first time we have
4182 // used this particular index buffer. getBufferIndexRange
4183 // can more quickly get min/max vertex index by
4184 // caching previous results.
4185 if (ctx->m_state->currentIndexVbo() != 0) {
4186 buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
4187 offset = (GLintptr)indices;
4188 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
4189 ctx->getBufferIndexRange(buf,
4190 indices,
4191 type,
4192 (size_t)count,
4193 (size_t)offset,
4194 &minIndex, &maxIndex);
4195 } else {
4196 // In this case, the |indices| field holds a real
4197 // array, so calculate the indices now. They will
4198 // also be needed to know how much data to
4199 // transfer to host.
4200 ctx->calcIndexRange(indices,
4201 type,
4202 count,
4203 &minIndex,
4204 &maxIndex);
4205 }
4206
Lingfeng Yang26e629a2018-10-13 20:00:12 -07004207 if (count == 0) return;
4208
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004209 bool adjustIndices = true;
4210 if (ctx->m_state->currentIndexVbo() != 0) {
4211 if (!has_client_vertex_arrays) {
4212 ctx->sendVertexAttributes(0, maxIndex + 1, false);
4213 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
4214 ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
4215 ctx->flushDrawCall();
4216 adjustIndices = false;
4217 } else {
4218 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
4219 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
4220 }
4221 }
4222 if (adjustIndices) {
4223 void *adjustedIndices =
4224 ctx->recenterIndices(indices,
4225 type,
4226 count,
4227 minIndex);
4228
4229 if (has_indirect_arrays || 1) {
4230 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true);
4231 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type));
4232 ctx->m_stream->flush();
4233 // XXX - OPTIMIZATION (see the other else branch) should be implemented
4234 if(!has_indirect_arrays) {
4235 //ALOGD("unoptimized drawelements !!!\n");
4236 }
4237 } else {
4238 // we are all direct arrays and immidate mode index array -
4239 // rebuild the arrays and the index array;
4240 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
4241 }
4242 }
4243}
4244
4245// struct GLStringKey {
4246// GLenum name;
4247// GLuint index;
4248// };
4249//
4250// struct GLStringKeyCompare {
4251// bool operator() (const GLStringKey& a,
4252// const GLStringKey& b) const {
4253// if (a.name != b.name) return a.name < b.name;
4254// if (a.index != b.index) return a.index < b.index;
4255// return false;
4256// }
4257// };
4258//
4259// typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore;
4260//
4261// static GLStringStore sGLStringStore;
4262// bool sGLStringStoreInitialized = false;
4263
4264const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
4265 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004266 const GLubyte *retval = (GLubyte *) "";
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004267
4268 RET_AND_SET_ERROR_IF(
4269 name != GL_VENDOR &&
4270 name != GL_RENDERER &&
4271 name != GL_VERSION &&
4272 name != GL_EXTENSIONS,
4273 GL_INVALID_ENUM,
4274 retval);
4275
4276 RET_AND_SET_ERROR_IF(
Lingfeng Yang44209df2018-09-21 10:04:17 -07004277 (name == GL_VENDOR ||
4278 name == GL_RENDERER ||
4279 name == GL_VERSION) &&
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004280 index != 0,
4281 GL_INVALID_VALUE,
4282 retval);
4283
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004284 RET_AND_SET_ERROR_IF(
4285 name == GL_EXTENSIONS &&
4286 index >= ctx->m_currExtensionsArray.size(),
4287 GL_INVALID_VALUE,
4288 retval);
4289
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004290 switch (name) {
4291 case GL_VENDOR:
4292 retval = gVendorString;
4293 break;
4294 case GL_RENDERER:
4295 retval = gRendererString;
4296 break;
4297 case GL_VERSION:
4298 retval = gVersionString;
4299 break;
4300 case GL_EXTENSIONS:
Lingfeng Yanga16eb2e2018-02-23 11:26:53 -08004301 retval = (const GLubyte*)(ctx->m_currExtensionsArray[index].c_str());
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004302 break;
4303 }
4304
4305 return retval;
4306}
4307
4308void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) {
4309 GL2Encoder *ctx = (GL2Encoder *)self;
4310
4311 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
4312
4313 GLint linkStatus = 0;
4314 ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
4315 GLint properLength = 0;
4316 ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength);
4317
4318 SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION);
4319 SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION);
4320
4321 ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary);
4322}
4323
4324void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
4325 GL2Encoder *ctx = (GL2Encoder *)self;
4326
4327 SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM);
4328 SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM);
4329 SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
4330 SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION);
4331 SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) &&
4332 ctx->getBufferData(GL_PIXEL_PACK_BUFFER) &&
4333 (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) >
4334 ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size),
4335 GL_INVALID_OPERATION);
4336 /*
4337GL_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.
4338
4339GL_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.
4340
4341GL_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.
4342
4343GL_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.
4344*/
4345
4346 FboFormatInfo fbo_format_info;
4347 ctx->m_state->getBoundFramebufferFormat(
4348 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info);
4349 SET_ERROR_IF(
4350 fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4351 !GLESv2Validation::readPixelsFboFormatMatch(
4352 format, type, fbo_format_info.tex_type),
4353 GL_INVALID_OPERATION);
4354
4355 if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) {
4356 ctx->glReadPixelsOffsetAEMU(
4357 ctx, x, y, width, height,
4358 format, type, (uintptr_t)pixels);
4359 } else {
4360 ctx->m_glReadPixels_enc(
4361 ctx, x, y, width, height,
4362 format, type, pixels);
4363 }
4364}
4365
4366// Track enabled state for some things like:
4367// - Primitive restart
4368void GL2Encoder::s_glEnable(void* self, GLenum what) {
4369 GL2Encoder *ctx = (GL2Encoder *)self;
4370
4371 switch (what) {
4372 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4373 ctx->m_primitiveRestartEnabled = true;
4374 break;
4375 }
4376
4377 ctx->m_glEnable_enc(ctx, what);
4378}
4379
4380void GL2Encoder::s_glDisable(void* self, GLenum what) {
4381 GL2Encoder *ctx = (GL2Encoder *)self;
4382
4383 switch (what) {
4384 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4385 ctx->m_primitiveRestartEnabled = false;
4386 break;
4387 }
4388
4389 ctx->m_glDisable_enc(ctx, what);
4390}
4391
4392void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) {
4393 GL2Encoder *ctx = (GL2Encoder *)self;
4394
4395 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4396
4397 ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value);
4398}
4399
4400void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) {
4401 GL2Encoder *ctx = (GL2Encoder *)self;
4402
4403 SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4404
4405 ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value);
4406}
4407
4408void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) {
4409 GL2Encoder *ctx = (GL2Encoder *)self;
4410
4411 SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM);
4412
4413 ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value);
4414}
4415
4416void 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) {
4417 GL2Encoder *ctx = (GL2Encoder *)self;
4418 GLClientState* state = ctx->m_state;
4419
4420 bool validateColor = mask | GL_COLOR_BUFFER_BIT;
4421 bool validateDepth = mask | GL_DEPTH_BUFFER_BIT;
4422 bool validateStencil = mask | GL_STENCIL_BUFFER_BIT;
4423
4424 FboFormatInfo read_fbo_format_info;
4425 FboFormatInfo draw_fbo_format_info;
4426 if (validateColor) {
4427 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4428 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4429
4430 if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4431 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) {
4432 SET_ERROR_IF(
4433 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4434 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4435 !GLESv2Validation::blitFramebufferFormat(
4436 read_fbo_format_info.tex_type,
4437 draw_fbo_format_info.tex_type),
4438 GL_INVALID_OPERATION);
4439 }
4440 }
4441
4442 if (validateDepth) {
4443 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info);
4444 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info);
4445
4446 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4447 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4448 SET_ERROR_IF(
4449 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4450 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4451 !GLESv2Validation::blitFramebufferFormat(
4452 read_fbo_format_info.rb_format,
4453 draw_fbo_format_info.rb_format),
4454 GL_INVALID_OPERATION);
4455 }
4456 }
4457
4458 if (validateStencil) {
4459 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info);
4460 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info);
4461
4462 if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4463 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) {
4464 SET_ERROR_IF(
4465 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4466 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4467 !GLESv2Validation::blitFramebufferFormat(
4468 read_fbo_format_info.rb_format,
4469 draw_fbo_format_info.rb_format),
4470 GL_INVALID_OPERATION);
4471 }
4472 }
4473
4474 state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info);
4475 SET_ERROR_IF(
4476 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4477 draw_fbo_format_info.rb_multisamples > 0,
4478 GL_INVALID_OPERATION);
4479 SET_ERROR_IF(
4480 draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE &&
4481 draw_fbo_format_info.tex_multisamples > 0,
4482 GL_INVALID_OPERATION);
4483
4484 state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info);
4485 SET_ERROR_IF(
4486 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4487 read_fbo_format_info.rb_multisamples > 0 &&
4488 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4489 state->boundFramebuffer(GL_READ_FRAMEBUFFER) &&
4490 state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) &&
4491 (read_fbo_format_info.rb_format !=
4492 draw_fbo_format_info.rb_format),
4493 GL_INVALID_OPERATION);
4494 SET_ERROR_IF(
4495 read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4496 read_fbo_format_info.rb_multisamples > 0 &&
4497 draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER &&
4498 (srcX0 != dstX0 || srcY0 != dstY0 ||
4499 srcX1 != dstX1 || srcY1 != dstY1),
4500 GL_INVALID_OPERATION);
4501
4502 ctx->m_glBlitFramebuffer_enc(ctx,
4503 srcX0, srcY0, srcX1, srcY1,
4504 dstX0, dstY0, dstX1, dstY1,
4505 mask, filter);
4506}
4507
4508void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
4509 GL2Encoder *ctx = (GL2Encoder *)self;
4510
4511 SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS &&
4512 pname != GL_SAMPLES,
4513 GL_INVALID_ENUM);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004514 SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004515 SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004516 !GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4517 !GLESv2Validation::depthRenderableFormat(ctx, internalformat) &&
4518 !GLESv2Validation::stencilRenderableFormat(ctx, internalformat),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004519 GL_INVALID_ENUM);
4520 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4521
4522 if (bufSize < 1) return;
4523
4524 // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64).
4525 // Limit to 4 (spec minimum) to keep dEQP tests from timing out.
4526 switch (pname) {
4527 case GL_NUM_SAMPLE_COUNTS:
4528 *params = 3;
4529 break;
4530 case GL_SAMPLES:
4531 params[0] = 4;
4532 if (bufSize > 1) params[1] = 2;
4533 if (bufSize > 2) params[2] = 1;
4534 break;
4535 default:
4536 break;
4537 }
4538}
4539
4540void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) {
4541 GL2Encoder *ctx = (GL2Encoder *)self;
4542 GLClientState* state = ctx->m_state;
4543
4544 SET_ERROR_IF(target != GL_TEXTURE_2D &&
4545 target != GL_TEXTURE_3D &&
Yahan Zhou53c64582018-04-16 15:46:17 -07004546 target != GL_TEXTURE_CUBE_MAP &&
4547 target != GL_TEXTURE_2D_ARRAY,
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004548 GL_INVALID_ENUM);
4549
4550 GLuint tex = state->getBoundTexture(target);
4551 GLenum internalformat = state->queryTexInternalFormat(tex);
4552 GLenum format = state->queryTexFormat(tex);
4553
4554 SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat),
4555 GL_INVALID_OPERATION);
4556 SET_ERROR_IF(tex &&
4557 !GLESv2Validation::unsizedFormat(internalformat) &&
Lingfeng Yang931817b2017-01-27 06:50:56 -08004558 !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
4559 GLESv2Validation::filterableTexFormat(ctx, internalformat)),
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004560 GL_INVALID_OPERATION);
4561
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08004562 if (target == GL_TEXTURE_2D) {
4563 ctx->override2DTextureTarget(target);
4564 }
4565
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004566 ctx->m_glGenerateMipmap_enc(ctx, target);
Lingfeng Yanga9fff6a2018-03-02 13:42:51 -08004567
4568 if (target == GL_TEXTURE_2D) {
4569 ctx->restore2DTextureTarget(target);
4570 }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004571}
4572
4573void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
4574 GL2Encoder *ctx = (GL2Encoder *)self;
4575 GLint maxCombinedUnits;
4576 ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits);
4577 SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE);
4578
4579 ctx->m_glBindSampler_enc(ctx, unit, sampler);
4580}
4581
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004582GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) {
4583 GL2Encoder *ctx = (GL2Encoder *)self;
4584 uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags);
4585 return (GLsync)(uintptr_t)syncHandle;
4586}
4587
4588GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4589 GL2Encoder *ctx = (GL2Encoder *)self;
4590 return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4591}
4592
4593void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) {
4594 GL2Encoder *ctx = (GL2Encoder *)self;
4595 ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout);
4596}
4597
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004598void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) {
4599 GL2Encoder *ctx = (GL2Encoder *)self;
4600
4601 if (!sync) return;
4602
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004603 ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4604}
4605
4606GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) {
4607 GL2Encoder *ctx = (GL2Encoder *)self;
4608 return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync);
4609}
4610
4611void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
4612 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004613
4614 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
4615
Lingfeng Yangf000ab42017-01-11 18:31:38 -08004616 return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004617}
4618
4619#define LIMIT_CASE(target, lim) \
4620 case target: \
4621 ctx->glGetIntegerv(ctx, lim, &limit); \
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004622 SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004623 break; \
4624
4625void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) {
4626 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004627 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004628
4629 GLint limit;
4630
4631 switch (target) {
4632 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4633 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4634 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4635 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4636 default:
4637 break;
4638 }
4639
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004640 const GLClientState::VertexAttribBindingVector& currBindings =
4641 state->currentVertexBufferBindings();
4642
4643 switch (target) {
4644 case GL_VERTEX_BINDING_DIVISOR:
4645 case GL_VERTEX_BINDING_OFFSET:
4646 case GL_VERTEX_BINDING_STRIDE:
4647 case GL_VERTEX_BINDING_BUFFER:
4648 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4649 break;
4650 default:
4651 break;
4652 }
4653
4654 switch (target) {
4655 case GL_VERTEX_BINDING_DIVISOR:
4656 *params = currBindings[index].divisor;
4657 return;
4658 case GL_VERTEX_BINDING_OFFSET:
4659 *params = currBindings[index].offset;
4660 return;
4661 case GL_VERTEX_BINDING_STRIDE:
4662 *params = currBindings[index].effectiveStride;
4663 return;
4664 case GL_VERTEX_BINDING_BUFFER:
4665 *params = currBindings[index].buffer;
4666 return;
4667 default:
4668 break;
4669 }
4670
Lingfeng Yang80a36332017-07-09 10:58:07 -07004671 ctx->safe_glGetIntegeri_v(target, index, params);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004672}
4673
4674void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
4675 GL2Encoder *ctx = (GL2Encoder *)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004676 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004677
4678 GLint limit;
4679
4680 switch (target) {
4681 LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
4682 LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS)
4683 LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS)
4684 LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
4685 default:
4686 break;
4687 }
4688
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004689 const GLClientState::VertexAttribBindingVector& currBindings =
4690 state->currentVertexBufferBindings();
4691
4692 switch (target) {
4693 case GL_VERTEX_BINDING_DIVISOR:
4694 case GL_VERTEX_BINDING_OFFSET:
4695 case GL_VERTEX_BINDING_STRIDE:
4696 case GL_VERTEX_BINDING_BUFFER:
4697 SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE);
4698 break;
4699 default:
4700 break;
4701 }
4702
4703 switch (target) {
4704 case GL_VERTEX_BINDING_DIVISOR:
4705 *params = currBindings[index].divisor;
4706 return;
4707 case GL_VERTEX_BINDING_OFFSET:
4708 *params = currBindings[index].offset;
4709 return;
4710 case GL_VERTEX_BINDING_STRIDE:
4711 *params = currBindings[index].effectiveStride;
4712 return;
4713 case GL_VERTEX_BINDING_BUFFER:
4714 *params = currBindings[index].buffer;
4715 return;
4716 default:
4717 break;
4718 }
4719
Lingfeng Yang80a36332017-07-09 10:58:07 -07004720 ctx->safe_glGetInteger64i_v(target, index, params);
4721}
4722
4723void GL2Encoder::s_glGetInteger64v(void* self, GLenum param, GLint64* val) {
4724 GL2Encoder *ctx = (GL2Encoder *)self;
4725 ctx->safe_glGetInteger64v(param, val);
4726}
4727
4728void GL2Encoder::s_glGetBooleani_v(void* self, GLenum param, GLuint index, GLboolean* val) {
4729 GL2Encoder *ctx = (GL2Encoder *)self;
4730 ctx->safe_glGetBooleani_v(param, index, val);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004731}
4732
4733void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
4734 GL2Encoder *ctx = (GL2Encoder *)self;
4735 ctx->m_glGetShaderiv_enc(self, shader, pname, params);
4736 if (pname == GL_SHADER_SOURCE_LENGTH) {
4737 ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
4738 if (shaderData) {
4739 int totalLen = 0;
4740 for (int i = 0; i < shaderData->sources.size(); i++) {
4741 totalLen += shaderData->sources[i].size();
4742 }
4743 if (totalLen != 0) {
4744 *params = totalLen + 1; // account for null terminator
4745 }
4746 }
4747 }
4748}
4749
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004750void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) {
4751 GL2Encoder *ctx = (GL2Encoder*)self;
4752 GLClientState* state = ctx->m_state;
4753 GLSharedGroupPtr shared = ctx->m_shared;
4754
4755 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
4756 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
4757 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
4758
4759 ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program);
4760 if (!state->currentProgram()) {
4761 state->setCurrentShaderProgram(program);
4762 }
4763}
4764
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004765GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) {
4766
4767 GLint* length = NULL;
4768 GL2Encoder* ctx = (GL2Encoder*)self;
4769
4770 int len = glUtilsCalcShaderSourceLen((char**)strings, length, count);
4771 char *str = new char[len + 1];
4772 glUtilsPackStrings(str, (char**)strings, (GLint*)length, count);
4773
4774 // Do GLSharedGroup and location WorkARound-specific initialization
4775 // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D()
4776 uint32_t spDataId = ctx->m_shared->addNewShaderProgramData();
4777 ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004778
Lingfeng Yang44209df2018-09-21 10:04:17 -07004779 if (!replaceSamplerExternalWith2D(str, &spData->shaderData)) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004780 delete [] str;
4781 ctx->setError(GL_OUT_OF_MEMORY);
4782 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4783 return -1;
4784 }
4785
4786 GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1);
4787 delete [] str;
4788
4789 // Phase 2: do glLinkProgram-related initialization for locationWorkARound
4790 GLint linkStatus = 0;
4791 ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus);
4792 if (!linkStatus) {
4793 ctx->m_shared->deleteShaderProgramDataById(spDataId);
4794 return -1;
4795 }
4796
4797 ctx->m_shared->associateGLShaderProgram(res, spDataId);
4798
4799 GLint numUniforms = 0;
Lingfeng Yang80a36332017-07-09 10:58:07 -07004800 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORMS, &numUniforms);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004801 ctx->m_shared->initShaderProgramData(res, numUniforms);
4802
4803 GLint maxLength=0;
4804 ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
4805
4806 GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1];
4807
4808 for (GLint i = 0; i < numUniforms; ++i) {
4809 ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name);
4810 GLint location = ctx->m_glGetUniformLocation_enc(self, res, name);
4811 ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name);
4812 }
4813
4814 ctx->m_shared->setupShaderProgramLocationShiftWAR(res);
4815
4816 delete [] name;
4817
4818 return res;
4819}
4820
4821void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0)
4822{
4823 GL2Encoder *ctx = (GL2Encoder*)self;
4824 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4825 ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0);
4826}
4827
4828void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4829{
4830 GL2Encoder *ctx = (GL2Encoder*)self;
4831 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4832 ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value);
4833}
4834
4835void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0)
4836{
4837 GL2Encoder *ctx = (GL2Encoder*)self;
4838 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08004839 ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08004840
4841 GLClientState* state = ctx->m_state;
4842 GLSharedGroupPtr shared = ctx->m_shared;
4843 GLenum target;
4844
4845 if (shared->setSamplerUniform(program, location, v0, &target)) {
4846 GLenum origActiveTexture = state->getActiveTextureUnit();
4847 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4848 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4849 }
4850 state->setActiveTextureUnit(origActiveTexture);
4851 }
4852}
4853
4854void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4855{
4856 GL2Encoder *ctx = (GL2Encoder*)self;
4857 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4858 ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value);
4859}
4860
4861void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0)
4862{
4863 GL2Encoder *ctx = (GL2Encoder*)self;
4864 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4865 ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0);
4866
4867 GLClientState* state = ctx->m_state;
4868 GLSharedGroupPtr shared = ctx->m_shared;
4869 GLenum target;
4870
4871 if (shared->setSamplerUniform(program, location, v0, &target)) {
4872 GLenum origActiveTexture = state->getActiveTextureUnit();
4873 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) {
4874 ctx->m_glActiveTexture_enc(self, origActiveTexture);
4875 }
4876 state->setActiveTextureUnit(origActiveTexture);
4877 }
4878}
4879
4880void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4881{
4882 GL2Encoder *ctx = (GL2Encoder*)self;
4883 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4884 ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value);
4885}
4886
4887void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1)
4888{
4889 GL2Encoder *ctx = (GL2Encoder*)self;
4890 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4891 ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1);
4892}
4893
4894void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4895{
4896 GL2Encoder *ctx = (GL2Encoder*)self;
4897 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4898 ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value);
4899}
4900
4901void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1)
4902{
4903 GL2Encoder *ctx = (GL2Encoder*)self;
4904 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4905 ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1);
4906}
4907
4908void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4909{
4910 GL2Encoder *ctx = (GL2Encoder*)self;
4911 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4912 ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value);
4913}
4914
4915void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1)
4916{
4917 GL2Encoder *ctx = (GL2Encoder*)self;
4918 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4919 ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1);
4920}
4921
4922void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4923{
4924 GL2Encoder *ctx = (GL2Encoder*)self;
4925 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4926 ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value);
4927}
4928
4929void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
4930{
4931 GL2Encoder *ctx = (GL2Encoder*)self;
4932 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4933 ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2);
4934}
4935
4936void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4937{
4938 GL2Encoder *ctx = (GL2Encoder*)self;
4939 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4940 ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value);
4941}
4942
4943void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
4944{
4945 GL2Encoder *ctx = (GL2Encoder*)self;
4946 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4947 ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2);
4948}
4949
4950void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4951{
4952 GL2Encoder *ctx = (GL2Encoder*)self;
4953 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4954 ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value);
4955}
4956
4957void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
4958{
4959 GL2Encoder *ctx = (GL2Encoder*)self;
4960 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4961 ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2);
4962}
4963
4964void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
4965{
4966 GL2Encoder *ctx = (GL2Encoder*)self;
4967 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4968 ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value);
4969}
4970
4971void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
4972{
4973 GL2Encoder *ctx = (GL2Encoder*)self;
4974 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4975 ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3);
4976}
4977
4978void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value)
4979{
4980 GL2Encoder *ctx = (GL2Encoder*)self;
4981 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4982 ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value);
4983}
4984
4985void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
4986{
4987 GL2Encoder *ctx = (GL2Encoder*)self;
4988 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4989 ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3);
4990}
4991
4992void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value)
4993{
4994 GL2Encoder *ctx = (GL2Encoder*)self;
4995 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
4996 ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value);
4997}
4998
4999void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
5000{
5001 GL2Encoder *ctx = (GL2Encoder*)self;
5002 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5003 ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3);
5004}
5005
5006void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value)
5007{
5008 GL2Encoder *ctx = (GL2Encoder*)self;
5009 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5010 ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value);
5011}
5012
5013void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5014{
5015 GL2Encoder *ctx = (GL2Encoder*)self;
5016 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5017 ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value);
5018}
5019
5020void GL2Encoder::s_glProgramUniformMatrix2x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5021{
5022 GL2Encoder *ctx = (GL2Encoder*)self;
5023 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5024 ctx->m_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value);
5025}
5026
5027void GL2Encoder::s_glProgramUniformMatrix2x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5028{
5029 GL2Encoder *ctx = (GL2Encoder*)self;
5030 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5031 ctx->m_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value);
5032}
5033
5034void GL2Encoder::s_glProgramUniformMatrix3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5035{
5036 GL2Encoder *ctx = (GL2Encoder*)self;
5037 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5038 ctx->m_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value);
5039}
5040
5041void GL2Encoder::s_glProgramUniformMatrix3x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5042{
5043 GL2Encoder *ctx = (GL2Encoder*)self;
5044 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5045 ctx->m_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value);
5046}
5047
5048void GL2Encoder::s_glProgramUniformMatrix3x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5049{
5050 GL2Encoder *ctx = (GL2Encoder*)self;
5051 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5052 ctx->m_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value);
5053}
5054
5055void GL2Encoder::s_glProgramUniformMatrix4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5056{
5057 GL2Encoder *ctx = (GL2Encoder*)self;
5058 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5059 ctx->m_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value);
5060}
5061
5062void GL2Encoder::s_glProgramUniformMatrix4x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5063{
5064 GL2Encoder *ctx = (GL2Encoder*)self;
5065 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5066 ctx->m_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value);
5067}
5068
5069void GL2Encoder::s_glProgramUniformMatrix4x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
5070{
5071 GL2Encoder *ctx = (GL2Encoder*)self;
5072 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
5073 ctx->m_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value);
5074}
5075
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005076void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) {
5077 GL2Encoder* ctx = (GL2Encoder*)self;
5078 ctx->m_glProgramParameteri_enc(self, program, pname, value);
5079}
5080
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005081void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program)
5082{
5083 GL2Encoder *ctx = (GL2Encoder*)self;
5084 GLClientState* state = ctx->m_state;
5085 GLSharedGroupPtr shared = ctx->m_shared;
5086
5087 SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION);
5088 SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE);
5089 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
5090
5091 ctx->m_glUseProgramStages_enc(self, pipeline, stages, program);
5092 state->associateProgramWithPipeline(program, pipeline);
5093
5094 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
5095 if (state->currentProgram()) {
5096 return;
5097 }
5098
5099 // Otherwise, update host texture 2D bindings.
5100 ctx->updateHostTexture2DBindingsFromProgramData(program);
5101}
5102
5103void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline)
5104{
5105 GL2Encoder *ctx = (GL2Encoder*)self;
5106 GLClientState* state = ctx->m_state;
5107
5108 ctx->m_glBindProgramPipeline_enc(self, pipeline);
5109
5110 // There is an active non-separable shader program in effect; no need to update external/2D bindings.
5111 if (!pipeline || state->currentProgram()) {
5112 return;
5113 }
5114
5115 GLClientState::ProgramPipelineIterator it = state->programPipelineBegin();
5116 for (; it != state->programPipelineEnd(); ++it) {
5117 if (it->second == pipeline) {
5118 ctx->updateHostTexture2DBindingsFromProgramData(it->first);
5119 }
5120 }
5121}
5122
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005123void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
5124 GL2Encoder *ctx = (GL2Encoder*)self;
5125 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
5126 if (bufSize == 0) {
5127 if (length) *length = 0;
5128 return;
5129 }
5130
5131 // Avoid modifying |name| if |*length| < bufSize.
5132 GLint* intermediate = new GLint[bufSize];
5133 GLsizei* myLength = length ? length : new GLsizei;
5134 bool needFreeLength = length == NULL;
5135
5136 ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate);
5137 GLsizei writtenInts = *myLength;
5138 memcpy(params, intermediate, writtenInts * sizeof(GLint));
5139
5140 delete [] intermediate;
5141 if (needFreeLength)
5142 delete myLength;
5143}
5144
5145GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) {
5146 GL2Encoder *ctx = (GL2Encoder*)self;
5147 return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name);
5148}
5149
5150GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) {
5151 GL2Encoder *ctx = (GL2Encoder*)self;
5152 return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name);
5153}
5154
5155void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) {
5156 GL2Encoder *ctx = (GL2Encoder*)self;
5157 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
5158 if (bufSize == 0) {
5159 if (length) *length = 0;
5160 return;
5161 }
5162
5163 // Avoid modifying |name| if |*length| < bufSize.
5164 char* intermediate = new char[bufSize];
5165 GLsizei* myLength = length ? length : new GLsizei;
5166 bool needFreeLength = length == NULL;
5167
5168 ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate);
5169 GLsizei writtenStrLen = *myLength;
5170 memcpy(name, intermediate, writtenStrLen + 1);
5171
5172 delete [] intermediate;
5173 if (needFreeLength)
5174 delete myLength;
5175}
5176
5177void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
5178 GL2Encoder *ctx = (GL2Encoder*)self;
5179 SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
5180 if (bufSize == 0) {
5181 if (length) *length = 0;
5182 return;
5183 }
5184
5185 // Avoid modifying |infoLog| if |*length| < bufSize.
5186 GLchar* intermediate = new GLchar[bufSize];
5187 GLsizei* myLength = length ? length : new GLsizei;
5188 bool needFreeLength = length == NULL;
5189
5190 ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate);
5191 GLsizei writtenStrLen = *myLength;
5192 memcpy(infoLog, intermediate, writtenStrLen + 1);
5193
5194 delete [] intermediate;
5195 if (needFreeLength)
5196 delete myLength;
5197}
5198
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005199void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
5200 GL2Encoder *ctx = (GL2Encoder*)self;
5201 GLClientState* state = ctx->m_state;
5202
Lingfeng Yang07289902017-01-27 12:26:19 -08005203 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005204 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5205
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005206 state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false);
5207 ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset);
5208}
5209
5210void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
5211 GL2Encoder *ctx = (GL2Encoder*)self;
5212 GLClientState* state = ctx->m_state;
5213
Lingfeng Yang07289902017-01-27 12:26:19 -08005214 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005215 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5216
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005217 state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true);
5218 ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset);
5219}
5220
5221void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) {
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005222 GL2Encoder *ctx = (GL2Encoder*)self;
5223 GLClientState* state = ctx->m_state;
5224
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005225 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5226
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005227 state->setVertexBindingDivisor(bindingindex, divisor);
5228 ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor);
5229}
5230
5231void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) {
5232 GL2Encoder *ctx = (GL2Encoder*)self;
5233 GLClientState* state = ctx->m_state;
Lingfeng Yang07289902017-01-27 12:26:19 -08005234 VALIDATE_VERTEX_ATTRIB_INDEX(attribindex);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005235 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005236
5237 state->setVertexAttribBinding(attribindex, bindingindex);
5238 ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex);
5239}
5240
5241void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) {
5242 GL2Encoder *ctx = (GL2Encoder*)self;
5243 GLClientState* state = ctx->m_state;
5244
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005245 SET_ERROR_IF(offset < 0, GL_INVALID_VALUE);
5246
5247 GLint maxStride;
5248 ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
5249 SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE);
5250
5251 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5252
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005253 state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride);
5254 ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride);
5255}
5256
5257void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) {
5258 GL2Encoder *ctx = (GL2Encoder*)self;
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005259 GLClientState* state = ctx->m_state;
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005260
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005261 bool hasClientArrays = false;
5262 ctx->getVBOUsage(&hasClientArrays, NULL);
5263
5264 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
5265 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5266 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
5267
5268 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005269 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005270 // BufferData* buf = ctx->getBufferData(target);
5271 // if (buf) {
5272 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
5273 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005274 ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect);
5275 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005276 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
5277 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005278 ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize);
5279 }
5280}
5281
5282void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) {
5283 GL2Encoder *ctx = (GL2Encoder*)self;
5284
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005285 GLClientState* state = ctx->m_state;
5286
5287 bool hasClientArrays = false;
5288 ctx->getVBOUsage(&hasClientArrays, NULL);
5289
5290 SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION);
5291 SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION);
5292 SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION);
5293
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005294 SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005295
5296 GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005297 if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005298 // BufferData* buf = ctx->getBufferData(target);
5299 // if (buf) {
5300 // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE);
5301 // }
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005302 ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect);
5303 } else {
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005304 // Client command structs are technically allowed in desktop OpenGL, but not in ES.
5305 // This is purely for debug/dev purposes.
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005306 ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize);
5307 }
5308
5309}
5310
5311void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
5312 GL2Encoder *ctx = (GL2Encoder*)self;
5313 GLClientState* state = ctx->m_state;
5314
5315 SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM);
5316 SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM);
5317 SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION);
5318 SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE);
5319 SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION);
Lingfeng Yangd3ae1062017-01-18 11:42:04 -08005320 GLint max_samples;
5321 ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples);
5322 SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION);
Lingfeng Yang46153ab2017-01-09 13:37:22 -08005323
5324 state->setBoundTextureInternalFormat(target, internalformat);
5325 state->setBoundTextureDims(target, 0, width, height, 1);
5326 state->setBoundTextureImmutableFormat(target);
5327 state->setBoundTextureSamples(target, samples);
5328
5329 ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
5330}
5331
Yahan Zhou72944ba2019-01-02 15:43:46 -08005332GLenum GL2Encoder::s_glGetGraphicsResetStatusEXT(void* self) {
5333 (void)self;
5334 return GL_NO_ERROR;
5335}
5336
5337void GL2Encoder::s_glReadnPixelsEXT(void* self, GLint x, GLint y, GLsizei width,
5338 GLsizei height, GLenum format, GLenum type, GLsizei bufSize,
5339 GLvoid* pixels) {
5340 GL2Encoder *ctx = (GL2Encoder*)self;
5341 SET_ERROR_IF(bufSize < glesv2_enc::pixelDataSize(self, width, height, format,
5342 type, 1), GL_INVALID_OPERATION);
5343 s_glReadPixels(self, x, y, width, height, format, type, pixels);
5344}
5345
5346void GL2Encoder::s_glGetnUniformfvEXT(void *self, GLuint program, GLint location,
5347 GLsizei bufSize, GLfloat* params) {
5348 GL2Encoder *ctx = (GL2Encoder*)self;
5349 SET_ERROR_IF(bufSize < glSizeof(glesv2_enc::uniformType(self, program,
5350 location)), GL_INVALID_OPERATION);
5351 s_glGetUniformfv(self, program, location, params);
5352}
5353
5354void GL2Encoder::s_glGetnUniformivEXT(void *self, GLuint program, GLint location,
5355 GLsizei bufSize, GLint* params) {
5356 GL2Encoder *ctx = (GL2Encoder*)self;
5357 SET_ERROR_IF(bufSize < glSizeof(glesv2_enc::uniformType(self, program,
5358 location)), GL_INVALID_OPERATION);
5359 s_glGetUniformiv(self, program, location, params);
5360}