blob: 1c5a05500250206e67ed214ea0e585999f85ca0d [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
15
Nicolas Capens0bac2852016-05-07 06:09:58 -040016#include "Buffer.h"
Nicolas Capens45be1bc2021-04-07 12:34:21 -040017#include "Common/Version.h"
Nicolas Capens0bac2852016-05-07 06:09:58 -040018#include "Context.h"
19#include "Fence.h"
20#include "Framebuffer.h"
21#include "Program.h"
Nicolas Capens45be1bc2021-04-07 12:34:21 -040022#include "Query.h"
Nicolas Capens0bac2852016-05-07 06:09:58 -040023#include "Renderbuffer.h"
24#include "Shader.h"
25#include "Texture.h"
Nicolas Capens0bac2852016-05-07 06:09:58 -040026#include "TransformFeedback.h"
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -050027#include "VertexArray.h"
Nicolas Capens0bac2852016-05-07 06:09:58 -040028#include "common/debug.h"
Nicolas Capens45be1bc2021-04-07 12:34:21 -040029#include "main.h"
30#include "mathutil.h"
31#include "utilities.h"
Nicolas Capens0bac2852016-05-07 06:09:58 -040032
33#include <GLES2/gl2.h>
34#include <GLES2/gl2ext.h>
35#include <GLES3/gl3.h>
36
Krzysztof Kosińskif919b862018-01-03 23:17:52 +010037#include <algorithm>
Nicolas Capens0bac2852016-05-07 06:09:58 -040038#include <limits>
39
Nicolas Capens0bac2852016-05-07 06:09:58 -040040namespace es2
41{
42
43static bool validImageSize(GLint level, GLsizei width, GLsizei height)
44{
Nicolas Capens805d7612018-08-02 13:56:32 -040045 if(level < 0 || level >= IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -040046 {
47 return false;
48 }
49
50 return true;
51}
52
Nicolas Capens805d7612018-08-02 13:56:32 -040053}
54
55namespace gl
56{
57
58using namespace es2;
59
Nicolas Capens38a9b3c2019-09-10 16:35:24 -040060void GL_APIENTRY ActiveTexture(GLenum texture)
Nicolas Capens0bac2852016-05-07 06:09:58 -040061{
62 TRACE("(GLenum texture = 0x%X)", texture);
63
Chris Forbes108f3e12018-08-30 19:41:59 -070064 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -040065
66 if(context)
67 {
68 if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
69 {
70 return error(GL_INVALID_ENUM);
71 }
72
73 context->setActiveSampler(texture - GL_TEXTURE0);
74 }
75}
76
Nicolas Capens38a9b3c2019-09-10 16:35:24 -040077void GL_APIENTRY AttachShader(GLuint program, GLuint shader)
Nicolas Capens0bac2852016-05-07 06:09:58 -040078{
79 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
80
Chris Forbes108f3e12018-08-30 19:41:59 -070081 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -040082
83 if(context)
84 {
85 es2::Program *programObject = context->getProgram(program);
86 es2::Shader *shaderObject = context->getShader(shader);
87
88 if(!programObject)
89 {
90 if(context->getShader(program))
91 {
92 return error(GL_INVALID_OPERATION);
93 }
94 else
95 {
96 return error(GL_INVALID_VALUE);
97 }
98 }
99
100 if(!shaderObject)
101 {
102 if(context->getProgram(shader))
103 {
104 return error(GL_INVALID_OPERATION);
105 }
106 else
107 {
108 return error(GL_INVALID_VALUE);
109 }
110 }
111
112 if(!programObject->attachShader(shaderObject))
113 {
114 return error(GL_INVALID_OPERATION);
115 }
116 }
117}
118
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400119void GL_APIENTRY BeginQueryEXT(GLenum target, GLuint name)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400120{
121 TRACE("(GLenum target = 0x%X, GLuint name = %d)", target, name);
122
123 switch(target)
124 {
125 case GL_ANY_SAMPLES_PASSED_EXT:
126 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
127 break;
128 default:
129 return error(GL_INVALID_ENUM);
130 }
131
132 if(name == 0)
133 {
134 return error(GL_INVALID_OPERATION);
135 }
136
Chris Forbes108f3e12018-08-30 19:41:59 -0700137 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400138
139 if(context)
140 {
141 context->beginQuery(target, name);
142 }
143}
144
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400145void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar* name)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400146{
147 TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = %s)", program, index, name);
148
149 if(index >= es2::MAX_VERTEX_ATTRIBS)
150 {
151 return error(GL_INVALID_VALUE);
152 }
153
Chris Forbes108f3e12018-08-30 19:41:59 -0700154 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400155
156 if(context)
157 {
158 es2::Program *programObject = context->getProgram(program);
159
160 if(!programObject)
161 {
162 if(context->getShader(program))
163 {
164 return error(GL_INVALID_OPERATION);
165 }
166 else
167 {
168 return error(GL_INVALID_VALUE);
169 }
170 }
171
172 if(strncmp(name, "gl_", 3) == 0)
173 {
174 return error(GL_INVALID_OPERATION);
175 }
176
177 programObject->bindAttributeLocation(index, name);
178 }
179}
180
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400181void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400182{
183 TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
184
Chris Forbes108f3e12018-08-30 19:41:59 -0700185 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400186
187 if(context)
188 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400189 switch(target)
190 {
191 case GL_ARRAY_BUFFER:
192 context->bindArrayBuffer(buffer);
193 return;
194 case GL_ELEMENT_ARRAY_BUFFER:
195 context->bindElementArrayBuffer(buffer);
196 return;
197 case GL_COPY_READ_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400198 context->bindCopyReadBuffer(buffer);
199 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400200 case GL_COPY_WRITE_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400201 context->bindCopyWriteBuffer(buffer);
202 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400203 case GL_PIXEL_PACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400204 context->bindPixelPackBuffer(buffer);
205 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400206 case GL_PIXEL_UNPACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400207 context->bindPixelUnpackBuffer(buffer);
208 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400209 case GL_TRANSFORM_FEEDBACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400210 context->bindTransformFeedbackBuffer(buffer);
211 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400212 case GL_UNIFORM_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400213 context->bindGenericUniformBuffer(buffer);
214 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400215 default:
216 return error(GL_INVALID_ENUM);
217 }
218 }
219}
220
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400221void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400222{
223 TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
224
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000225 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400226 {
227 return error(GL_INVALID_ENUM);
228 }
229
Chris Forbes108f3e12018-08-30 19:41:59 -0700230 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400231
232 if(context)
233 {
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000234 if(target == GL_READ_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400235 {
236 context->bindReadFramebuffer(framebuffer);
237 }
238
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000239 if(target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400240 {
241 context->bindDrawFramebuffer(framebuffer);
242 }
243 }
244}
245
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400246void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400247{
248 TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
249
250 if(target != GL_RENDERBUFFER)
251 {
252 return error(GL_INVALID_ENUM);
253 }
254
Chris Forbes108f3e12018-08-30 19:41:59 -0700255 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400256
257 if(context)
258 {
259 // [OpenGL ES 2.0.25] Section 4.4.3 page 110
260 // [OpenGL ES 3.0.4] Section 4.4.2 page 204
261 // If renderbuffer is not zero, then the resulting renderbuffer object
262 // is a new state vector, initialized with a zero-sized memory buffer.
263 context->bindRenderbuffer(renderbuffer);
264 }
265}
266
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400267void GL_APIENTRY BindTexture(GLenum target, GLuint texture)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400268{
269 TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
270
Chris Forbes108f3e12018-08-30 19:41:59 -0700271 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400272
273 if(context)
274 {
275 es2::Texture *textureObject = context->getTexture(texture);
276
277 if(textureObject && textureObject->getTarget() != target && texture != 0)
278 {
279 return error(GL_INVALID_OPERATION);
280 }
281
Nicolas Capens0bac2852016-05-07 06:09:58 -0400282 switch(target)
283 {
284 case GL_TEXTURE_2D:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500285 context->bindTexture(TEXTURE_2D, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400286 break;
287 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500288 context->bindTexture(TEXTURE_CUBE, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400289 break;
290 case GL_TEXTURE_EXTERNAL_OES:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500291 context->bindTexture(TEXTURE_EXTERNAL, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400292 break;
293 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500294 context->bindTexture(TEXTURE_2D_ARRAY, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400295 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -0500296 case GL_TEXTURE_3D:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500297 context->bindTexture(TEXTURE_3D, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400298 break;
Alexis Hetu46768622018-01-16 22:09:28 -0500299 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500300 context->bindTexture(TEXTURE_2D_RECT, texture);
Alexis Hetu46768622018-01-16 22:09:28 -0500301 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400302 default:
303 return error(GL_INVALID_ENUM);
304 }
305 }
306}
307
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400308void GL_APIENTRY BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400309{
310 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
311 red, green, blue, alpha);
312
Chris Forbes108f3e12018-08-30 19:41:59 -0700313 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400314
315 if(context)
316 {
317 context->setBlendColor(es2::clamp01(red), es2::clamp01(green), es2::clamp01(blue), es2::clamp01(alpha));
318 }
319}
320
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400321void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400322{
323 TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
324
325 switch(modeRGB)
326 {
327 case GL_FUNC_ADD:
328 case GL_FUNC_SUBTRACT:
329 case GL_FUNC_REVERSE_SUBTRACT:
330 case GL_MIN_EXT:
331 case GL_MAX_EXT:
332 break;
333 default:
334 return error(GL_INVALID_ENUM);
335 }
336
337 switch(modeAlpha)
338 {
339 case GL_FUNC_ADD:
340 case GL_FUNC_SUBTRACT:
341 case GL_FUNC_REVERSE_SUBTRACT:
342 case GL_MIN_EXT:
343 case GL_MAX_EXT:
344 break;
345 default:
346 return error(GL_INVALID_ENUM);
347 }
348
Chris Forbes108f3e12018-08-30 19:41:59 -0700349 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400350
351 if(context)
352 {
353 context->setBlendEquation(modeRGB, modeAlpha);
354 }
355}
356
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400357void GL_APIENTRY BlendEquation(GLenum mode)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400358{
Nicolas Capens805d7612018-08-02 13:56:32 -0400359 BlendEquationSeparate(mode, mode);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400360}
361
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400362void GL_APIENTRY BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400363{
364 TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
365 srcRGB, dstRGB, srcAlpha, dstAlpha);
366
Nicolas Capens0bac2852016-05-07 06:09:58 -0400367 switch(srcRGB)
368 {
369 case GL_ZERO:
370 case GL_ONE:
371 case GL_SRC_COLOR:
372 case GL_ONE_MINUS_SRC_COLOR:
373 case GL_DST_COLOR:
374 case GL_ONE_MINUS_DST_COLOR:
375 case GL_SRC_ALPHA:
376 case GL_ONE_MINUS_SRC_ALPHA:
377 case GL_DST_ALPHA:
378 case GL_ONE_MINUS_DST_ALPHA:
379 case GL_CONSTANT_COLOR:
380 case GL_ONE_MINUS_CONSTANT_COLOR:
381 case GL_CONSTANT_ALPHA:
382 case GL_ONE_MINUS_CONSTANT_ALPHA:
383 case GL_SRC_ALPHA_SATURATE:
384 break;
385 default:
386 return error(GL_INVALID_ENUM);
387 }
388
389 switch(dstRGB)
390 {
391 case GL_ZERO:
392 case GL_ONE:
393 case GL_SRC_COLOR:
394 case GL_ONE_MINUS_SRC_COLOR:
395 case GL_DST_COLOR:
396 case GL_ONE_MINUS_DST_COLOR:
397 case GL_SRC_ALPHA:
398 case GL_ONE_MINUS_SRC_ALPHA:
399 case GL_DST_ALPHA:
400 case GL_ONE_MINUS_DST_ALPHA:
401 case GL_CONSTANT_COLOR:
402 case GL_ONE_MINUS_CONSTANT_COLOR:
403 case GL_CONSTANT_ALPHA:
404 case GL_ONE_MINUS_CONSTANT_ALPHA:
405 break;
406 case GL_SRC_ALPHA_SATURATE:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400407 break;
408 default:
409 return error(GL_INVALID_ENUM);
410 }
411
412 switch(srcAlpha)
413 {
414 case GL_ZERO:
415 case GL_ONE:
416 case GL_SRC_COLOR:
417 case GL_ONE_MINUS_SRC_COLOR:
418 case GL_DST_COLOR:
419 case GL_ONE_MINUS_DST_COLOR:
420 case GL_SRC_ALPHA:
421 case GL_ONE_MINUS_SRC_ALPHA:
422 case GL_DST_ALPHA:
423 case GL_ONE_MINUS_DST_ALPHA:
424 case GL_CONSTANT_COLOR:
425 case GL_ONE_MINUS_CONSTANT_COLOR:
426 case GL_CONSTANT_ALPHA:
427 case GL_ONE_MINUS_CONSTANT_ALPHA:
428 case GL_SRC_ALPHA_SATURATE:
429 break;
430 default:
431 return error(GL_INVALID_ENUM);
432 }
433
434 switch(dstAlpha)
435 {
436 case GL_ZERO:
437 case GL_ONE:
438 case GL_SRC_COLOR:
439 case GL_ONE_MINUS_SRC_COLOR:
440 case GL_DST_COLOR:
441 case GL_ONE_MINUS_DST_COLOR:
442 case GL_SRC_ALPHA:
443 case GL_ONE_MINUS_SRC_ALPHA:
444 case GL_DST_ALPHA:
445 case GL_ONE_MINUS_DST_ALPHA:
446 case GL_CONSTANT_COLOR:
447 case GL_ONE_MINUS_CONSTANT_COLOR:
448 case GL_CONSTANT_ALPHA:
449 case GL_ONE_MINUS_CONSTANT_ALPHA:
450 break;
451 case GL_SRC_ALPHA_SATURATE:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400452 break;
453 default:
454 return error(GL_INVALID_ENUM);
455 }
456
Chris Forbes108f3e12018-08-30 19:41:59 -0700457 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400458
459 if(context)
460 {
461 context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
462 }
463}
464
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400465void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor)
Nicolas Capens805d7612018-08-02 13:56:32 -0400466{
467 BlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
468}
469
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400470void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400471{
472 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
473
474 TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = %p, GLenum usage = %d)",
475 target, size, data, usage);
476
477 if(size < 0)
478 {
479 return error(GL_INVALID_VALUE);
480 }
481
Nicolas Capens0bac2852016-05-07 06:09:58 -0400482 switch(usage)
483 {
484 case GL_STREAM_DRAW:
485 case GL_STATIC_DRAW:
486 case GL_DYNAMIC_DRAW:
487 break;
488 case GL_STREAM_READ:
489 case GL_STREAM_COPY:
490 case GL_STATIC_READ:
491 case GL_STATIC_COPY:
492 case GL_DYNAMIC_READ:
493 case GL_DYNAMIC_COPY:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400494 break;
495 default:
496 return error(GL_INVALID_ENUM);
497 }
498
Chris Forbes108f3e12018-08-30 19:41:59 -0700499 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400500
501 if(context)
502 {
503 es2::Buffer *buffer = nullptr;
504 if(!context->getBuffer(target, &buffer))
505 {
506 return error(GL_INVALID_ENUM);
507 }
508
509 if(!buffer)
510 {
511 // A null buffer means that "0" is bound to the requested buffer target
512 return error(GL_INVALID_OPERATION);
513 }
514
515 buffer->bufferData(data, size, usage);
516 }
517}
518
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400519void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400520{
521 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
522 offset = static_cast<GLint>(offset);
523
524 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = %p)",
525 target, offset, size, data);
526
527 if(size < 0 || offset < 0)
528 {
529 return error(GL_INVALID_VALUE);
530 }
531
Chris Forbes108f3e12018-08-30 19:41:59 -0700532 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400533
534 if(context)
535 {
536 es2::Buffer *buffer = nullptr;
537 if(!context->getBuffer(target, &buffer))
538 {
539 return error(GL_INVALID_ENUM);
540 }
541
542 if(!buffer)
543 {
544 // A null buffer means that "0" is bound to the requested buffer target
545 return error(GL_INVALID_OPERATION);
546 }
547
Alexis Hetu6e864492017-11-14 15:27:00 -0500548 if(buffer->isMapped())
549 {
550 // It is an invalid operation to update an already mapped buffer
551 return error(GL_INVALID_OPERATION);
552 }
553
Nicolas Capens0bac2852016-05-07 06:09:58 -0400554 if((size_t)size + offset > buffer->size())
555 {
556 return error(GL_INVALID_VALUE);
557 }
558
559 buffer->bufferSubData(data, size, offset);
560 }
561}
562
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400563GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400564{
565 TRACE("(GLenum target = 0x%X)", target);
566
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000567 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400568 {
569 return error(GL_INVALID_ENUM, 0);
570 }
571
Chris Forbes108f3e12018-08-30 19:41:59 -0700572 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400573
574 if(context)
575 {
576 es2::Framebuffer *framebuffer = nullptr;
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000577 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400578 {
579 framebuffer = context->getReadFramebuffer();
580 }
581 else
582 {
583 framebuffer = context->getDrawFramebuffer();
584 }
585
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400586 if(!framebuffer)
587 {
588 return GL_FRAMEBUFFER_UNDEFINED_OES;
589 }
590
Nicolas Capens0bac2852016-05-07 06:09:58 -0400591 return framebuffer->completeness();
592 }
593
594 return 0;
595}
596
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400597void GL_APIENTRY Clear(GLbitfield mask)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400598{
599 TRACE("(GLbitfield mask = %X)", mask);
600
601 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
602 {
603 return error(GL_INVALID_VALUE);
604 }
605
Chris Forbes108f3e12018-08-30 19:41:59 -0700606 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400607
608 if(context)
609 {
610 context->clear(mask);
611 }
612}
613
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400614void GL_APIENTRY ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400615{
616 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
617 red, green, blue, alpha);
618
Chris Forbes108f3e12018-08-30 19:41:59 -0700619 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400620
621 if(context)
622 {
623 context->setClearColor(red, green, blue, alpha);
624 }
625}
626
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400627void GL_APIENTRY ClearDepthf(GLclampf depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400628{
629 TRACE("(GLclampf depth = %f)", depth);
630
Chris Forbes108f3e12018-08-30 19:41:59 -0700631 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400632
633 if(context)
634 {
635 context->setClearDepth(depth);
636 }
637}
638
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400639void GL_APIENTRY ClearStencil(GLint s)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400640{
641 TRACE("(GLint s = %d)", s);
642
Chris Forbes108f3e12018-08-30 19:41:59 -0700643 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400644
645 if(context)
646 {
647 context->setClearStencil(s);
648 }
649}
650
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400651void GL_APIENTRY ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400652{
653 TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
654 red, green, blue, alpha);
655
Chris Forbes108f3e12018-08-30 19:41:59 -0700656 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400657
658 if(context)
659 {
Nicolas Capens51814272018-10-15 13:01:22 -0400660 context->setColorMask(red != GL_FALSE, green != GL_FALSE, blue != GL_FALSE, alpha != GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400661 }
662}
663
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400664void GL_APIENTRY CompileShader(GLuint shader)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400665{
666 TRACE("(GLuint shader = %d)", shader);
667
Chris Forbes108f3e12018-08-30 19:41:59 -0700668 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400669
670 if(context)
671 {
672 es2::Shader *shaderObject = context->getShader(shader);
673
674 if(!shaderObject)
675 {
676 if(context->getProgram(shader))
677 {
678 return error(GL_INVALID_OPERATION);
679 }
680 else
681 {
682 return error(GL_INVALID_VALUE);
683 }
684 }
685
686 shaderObject->compile();
687 }
688}
689
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400690void GL_APIENTRY CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
691 GLint border, GLsizei imageSize, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400692{
693 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
694 "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
695 target, level, internalformat, width, height, border, imageSize, data);
696
697 if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)
698 {
699 return error(GL_INVALID_VALUE);
700 }
701
Nicolas Capens83463112018-06-12 23:55:16 -0400702 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400703 {
Nicolas Capens03589982018-02-01 17:28:32 -0500704 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400705 }
706
707 if(border != 0)
708 {
709 return error(GL_INVALID_VALUE);
710 }
711
Chris Forbes108f3e12018-08-30 19:41:59 -0700712 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400713
714 if(context)
715 {
716 if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
717 {
718 return error(GL_INVALID_VALUE);
719 }
720
721 switch(target)
722 {
723 case GL_TEXTURE_2D:
724 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
725 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
726 {
727 return error(GL_INVALID_VALUE);
728 }
729 break;
730 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
731 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
732 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
733 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
734 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
735 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
736 if(width != height)
737 {
738 return error(GL_INVALID_VALUE);
739 }
740
741 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
742 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
743 {
744 return error(GL_INVALID_VALUE);
745 }
746 break;
Alexis Hetu0988fb82018-02-02 17:23:48 -0500747 case GL_TEXTURE_RECTANGLE_ARB: // Rectangle textures cannot be compressed
Nicolas Capens0bac2852016-05-07 06:09:58 -0400748 default:
749 return error(GL_INVALID_ENUM);
750 }
751
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500752 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400753 {
754 return error(GL_INVALID_VALUE);
755 }
756
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500757 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500758 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500759 {
760 return error(validationError);
761 }
762
Alexis Hetu46768622018-01-16 22:09:28 -0500763 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400764 {
Alexis Hetu46768622018-01-16 22:09:28 -0500765 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400766
767 if(!texture)
768 {
769 return error(GL_INVALID_OPERATION);
770 }
771
772 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
773 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500774 else if(es2::IsCubemapTextureTarget(target))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400775 {
776 es2::TextureCubeMap *texture = context->getTextureCubeMap();
777
778 if(!texture)
779 {
780 return error(GL_INVALID_OPERATION);
781 }
782
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500783 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400784 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500785 else UNREACHABLE(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400786 }
787}
788
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400789void GL_APIENTRY CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
790 GLenum format, GLsizei imageSize, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400791{
792 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
793 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
794 "GLsizei imageSize = %d, const GLvoid* data = %p)",
795 target, level, xoffset, yoffset, width, height, format, imageSize, data);
796
Antonio Maioranod1fff582019-04-16 10:08:39 -0400797 if(!es2::IsTexImageTarget(target))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400798 {
799 return error(GL_INVALID_ENUM);
800 }
801
802 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
803 {
804 return error(GL_INVALID_VALUE);
805 }
806
807 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
808 {
809 return error(GL_INVALID_VALUE);
810 }
811
Merck Hung9b768842018-10-16 14:28:26 +0900812 if(!IsCompressed(format))
813 {
814 return error(GL_INVALID_ENUM);
815 }
816
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500817 if(imageSize != gl::ComputeCompressedSize(width, height, format))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400818 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500819 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400820 }
821
Chris Forbes108f3e12018-08-30 19:41:59 -0700822 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400823
824 if(context)
825 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400826 if(xoffset % 4 != 0 || yoffset % 4 != 0)
827 {
828 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
829 return error(GL_INVALID_OPERATION);
830 }
831
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500832 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500833 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500834 {
835 return error(validationError);
836 }
837
Alexis Hetu46768622018-01-16 22:09:28 -0500838 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400839 {
Alexis Hetu46768622018-01-16 22:09:28 -0500840 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400841
Nicolas Capens83463112018-06-12 23:55:16 -0400842 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -0500843 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400844 {
845 return error(validationError);
846 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500847
Nicolas Capenseab70762018-02-06 16:49:36 -0500848 texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400849 }
850 else if(es2::IsCubemapTextureTarget(target))
851 {
852 es2::TextureCubeMap *texture = context->getTextureCubeMap();
853
Nicolas Capens83463112018-06-12 23:55:16 -0400854 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -0500855 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400856 {
857 return error(validationError);
858 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500859
Nicolas Capenseab70762018-02-06 16:49:36 -0500860 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400861 }
862 else UNREACHABLE(target);
863 }
864}
865
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400866void GL_APIENTRY CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400867{
868 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
869 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
870 target, level, internalformat, x, y, width, height, border);
871
872 if(!validImageSize(level, width, height))
873 {
874 return error(GL_INVALID_VALUE);
875 }
876
877 if(border != 0)
878 {
879 return error(GL_INVALID_VALUE);
880 }
881
Chris Forbes108f3e12018-08-30 19:41:59 -0700882 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400883
884 if(context)
885 {
886 switch(target)
887 {
Alexis Hetu46768622018-01-16 22:09:28 -0500888 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -0500889 if(level != 0)
890 {
891 return error(GL_INVALID_VALUE);
892 }
Nicolas Capens894858a2018-03-22 00:55:23 -0400893 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -0500894 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400895 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
896 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
897 {
898 return error(GL_INVALID_VALUE);
899 }
900 break;
901 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
902 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
903 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
904 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
905 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
906 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
907 if(width != height)
908 {
909 return error(GL_INVALID_VALUE);
910 }
911
912 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
913 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
914 {
915 return error(GL_INVALID_VALUE);
916 }
917 break;
918 default:
919 return error(GL_INVALID_ENUM);
920 }
921
922 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
923
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400924 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400925 {
926 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
927 }
928
929 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
930
931 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
932 {
933 return error(GL_INVALID_OPERATION);
934 }
935
936 GLenum colorbufferFormat = source->getFormat();
937
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500938 // Determine the sized internal format.
939 if(gl::IsUnsizedInternalFormat(internalformat))
940 {
Nicolas Capense1fa9ea2018-07-05 12:13:56 -0400941 if(colorbufferFormat == GL_RGB10_A2)
942 {
943 // Not supported with unsized internalformat.
944 // https://www.khronos.org/members/login/bugzilla/show_bug.cgi?id=9807#c56
945 return error(GL_INVALID_OPERATION);
946 }
947
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500948 if(gl::GetBaseInternalFormat(colorbufferFormat) == internalformat)
949 {
950 internalformat = colorbufferFormat;
951 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400952 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_NORMALIZED && GetRedSize(colorbufferFormat) <= 8)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500953 {
Nicolas Capens667ab102018-03-22 13:22:20 -0400954 // TODO: Convert to the smallest format that fits all components.
955 // e.g. Copying RGBA4 to RGB should result in RGB565, not RGB8.
956
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500957 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_BYTE);
958 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400959 else if(GetColorComponentType(colorbufferFormat) == GL_INT)
960 {
961 internalformat = gl::GetSizedInternalFormat(internalformat, GL_INT);
962 }
963 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_INT)
964 {
965 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_INT);
966 }
967 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 16) // GL_EXT_color_buffer_half_float
968 {
969 internalformat = gl::GetSizedInternalFormat(internalformat, GL_HALF_FLOAT_OES);
970 }
Nicolas Capens659d89e2018-06-22 13:57:37 -0400971 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 32) // GL_EXT_color_buffer_float
972 {
973 internalformat = gl::GetSizedInternalFormat(internalformat, GL_FLOAT);
974 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500975 else
976 {
Nicolas Capensa5dfd972018-09-28 15:27:08 -0400977 UNIMPLEMENTED("internalformat = %x, colorbufferFormat = %X", internalformat, colorbufferFormat);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500978
979 return error(GL_INVALID_OPERATION);
980 }
981 }
982
Nicolas Capens8f215a42018-02-02 13:25:53 -0500983 if(!ValidateCopyFormats(internalformat, colorbufferFormat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400984 {
985 return;
986 }
987
Alexis Hetu46768622018-01-16 22:09:28 -0500988 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400989 {
Alexis Hetu46768622018-01-16 22:09:28 -0500990 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400991
992 if(!texture)
993 {
994 return error(GL_INVALID_OPERATION);
995 }
996
Nicolas Capens1529c2c2018-02-06 14:44:47 -0500997 texture->copyImage(level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400998 }
999 else if(es2::IsCubemapTextureTarget(target))
1000 {
1001 es2::TextureCubeMap *texture = context->getTextureCubeMap();
1002
1003 if(!texture)
1004 {
1005 return error(GL_INVALID_OPERATION);
1006 }
1007
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001008 texture->copyImage(target, level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001009 }
1010 else UNREACHABLE(target);
1011 }
1012}
1013
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001014void GL_APIENTRY CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001015{
1016 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1017 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1018 target, level, xoffset, yoffset, x, y, width, height);
1019
Antonio Maioranod1fff582019-04-16 10:08:39 -04001020 if(!es2::IsTexImageTarget(target))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001021 {
1022 return error(GL_INVALID_ENUM);
1023 }
1024
1025 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1026 {
1027 return error(GL_INVALID_VALUE);
1028 }
1029
1030 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1031 {
1032 return error(GL_INVALID_VALUE);
1033 }
1034
1035 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1036 {
1037 return error(GL_INVALID_VALUE);
1038 }
1039
Chris Forbes108f3e12018-08-30 19:41:59 -07001040 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001041
1042 if(context)
1043 {
1044 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1045
Alexis Hetu5cd502b2018-03-22 08:29:31 -04001046 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001047 {
1048 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1049 }
1050
1051 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1052
1053 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1054 {
1055 return error(GL_INVALID_OPERATION);
1056 }
1057
1058 es2::Texture *texture = nullptr;
1059
Alexis Hetu46768622018-01-16 22:09:28 -05001060 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001061 {
Alexis Hetu46768622018-01-16 22:09:28 -05001062 texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001063 }
1064 else if(es2::IsCubemapTextureTarget(target))
1065 {
1066 texture = context->getTextureCubeMap();
1067 }
1068 else UNREACHABLE(target);
1069
Nicolas Capens83463112018-06-12 23:55:16 -04001070 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05001071 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001072 {
1073 return error(validationError);
1074 }
1075
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001076 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001077 }
1078}
1079
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001080GLuint GL_APIENTRY CreateProgram(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001081{
1082 TRACE("()");
1083
Chris Forbes108f3e12018-08-30 19:41:59 -07001084 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001085
1086 if(context)
1087 {
1088 return context->createProgram();
1089 }
1090
1091 return 0;
1092}
1093
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001094GLuint GL_APIENTRY CreateShader(GLenum type)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001095{
1096 TRACE("(GLenum type = 0x%X)", type);
1097
Chris Forbes108f3e12018-08-30 19:41:59 -07001098 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001099
1100 if(context)
1101 {
1102 switch(type)
1103 {
1104 case GL_FRAGMENT_SHADER:
1105 case GL_VERTEX_SHADER:
1106 return context->createShader(type);
1107 default:
1108 return error(GL_INVALID_ENUM, 0);
1109 }
1110 }
1111
1112 return 0;
1113}
1114
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001115void GL_APIENTRY CullFace(GLenum mode)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001116{
1117 TRACE("(GLenum mode = 0x%X)", mode);
1118
1119 switch(mode)
1120 {
1121 case GL_FRONT:
1122 case GL_BACK:
1123 case GL_FRONT_AND_BACK:
1124 {
Chris Forbes108f3e12018-08-30 19:41:59 -07001125 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001126
1127 if(context)
1128 {
1129 context->setCullMode(mode);
1130 }
1131 }
1132 break;
1133 default:
1134 return error(GL_INVALID_ENUM);
1135 }
1136}
1137
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001138void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint* buffers)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001139{
1140 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1141
1142 if(n < 0)
1143 {
1144 return error(GL_INVALID_VALUE);
1145 }
1146
Chris Forbes108f3e12018-08-30 19:41:59 -07001147 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001148
1149 if(context)
1150 {
1151 for(int i = 0; i < n; i++)
1152 {
1153 context->deleteBuffer(buffers[i]);
1154 }
1155 }
1156}
1157
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001158void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint* fences)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001159{
1160 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1161
1162 if(n < 0)
1163 {
1164 return error(GL_INVALID_VALUE);
1165 }
1166
Chris Forbes108f3e12018-08-30 19:41:59 -07001167 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001168
1169 if(context)
1170 {
1171 for(int i = 0; i < n; i++)
1172 {
1173 context->deleteFence(fences[i]);
1174 }
1175 }
1176}
1177
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001178void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001179{
1180 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1181
1182 if(n < 0)
1183 {
1184 return error(GL_INVALID_VALUE);
1185 }
1186
Chris Forbes108f3e12018-08-30 19:41:59 -07001187 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001188
1189 if(context)
1190 {
1191 for(int i = 0; i < n; i++)
1192 {
Nicolas Capens56eacf02018-09-27 13:54:27 -04001193 if(framebuffers[i] != 0) // Attempts to delete default framebuffer silently ignored.
Nicolas Capens0bac2852016-05-07 06:09:58 -04001194 {
1195 context->deleteFramebuffer(framebuffers[i]);
1196 }
1197 }
1198 }
1199}
1200
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001201void GL_APIENTRY DeleteProgram(GLuint program)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001202{
1203 TRACE("(GLuint program = %d)", program);
1204
1205 if(program == 0)
1206 {
1207 return;
1208 }
1209
Chris Forbes108f3e12018-08-30 19:41:59 -07001210 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001211
1212 if(context)
1213 {
1214 if(!context->getProgram(program))
1215 {
1216 if(context->getShader(program))
1217 {
1218 return error(GL_INVALID_OPERATION);
1219 }
1220 else
1221 {
1222 return error(GL_INVALID_VALUE);
1223 }
1224 }
1225
1226 context->deleteProgram(program);
1227 }
1228}
1229
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001230void GL_APIENTRY DeleteQueriesEXT(GLsizei n, const GLuint *ids)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001231{
1232 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1233
1234 if(n < 0)
1235 {
1236 return error(GL_INVALID_VALUE);
1237 }
1238
Chris Forbes108f3e12018-08-30 19:41:59 -07001239 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001240
1241 if(context)
1242 {
1243 for(int i = 0; i < n; i++)
1244 {
1245 context->deleteQuery(ids[i]);
1246 }
1247 }
1248}
1249
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001250void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001251{
1252 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1253
1254 if(n < 0)
1255 {
1256 return error(GL_INVALID_VALUE);
1257 }
1258
Chris Forbes108f3e12018-08-30 19:41:59 -07001259 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001260
1261 if(context)
1262 {
1263 for(int i = 0; i < n; i++)
1264 {
1265 context->deleteRenderbuffer(renderbuffers[i]);
1266 }
1267 }
1268}
1269
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001270void GL_APIENTRY DeleteShader(GLuint shader)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001271{
1272 TRACE("(GLuint shader = %d)", shader);
1273
1274 if(shader == 0)
1275 {
1276 return;
1277 }
1278
Chris Forbes108f3e12018-08-30 19:41:59 -07001279 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001280
1281 if(context)
1282 {
1283 if(!context->getShader(shader))
1284 {
1285 if(context->getProgram(shader))
1286 {
1287 return error(GL_INVALID_OPERATION);
1288 }
1289 else
1290 {
1291 return error(GL_INVALID_VALUE);
1292 }
1293 }
1294
1295 context->deleteShader(shader);
1296 }
1297}
1298
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001299void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint* textures)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001300{
1301 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1302
1303 if(n < 0)
1304 {
1305 return error(GL_INVALID_VALUE);
1306 }
1307
Chris Forbes108f3e12018-08-30 19:41:59 -07001308 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001309
1310 if(context)
1311 {
1312 for(int i = 0; i < n; i++)
1313 {
Nicolas Capens56eacf02018-09-27 13:54:27 -04001314 if(textures[i] != 0) // Attempts to delete default texture silently ignored.
Nicolas Capens0bac2852016-05-07 06:09:58 -04001315 {
1316 context->deleteTexture(textures[i]);
1317 }
1318 }
1319 }
1320}
1321
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001322void GL_APIENTRY DepthFunc(GLenum func)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001323{
1324 TRACE("(GLenum func = 0x%X)", func);
1325
1326 switch(func)
1327 {
1328 case GL_NEVER:
1329 case GL_ALWAYS:
1330 case GL_LESS:
1331 case GL_LEQUAL:
1332 case GL_EQUAL:
1333 case GL_GREATER:
1334 case GL_GEQUAL:
1335 case GL_NOTEQUAL:
1336 break;
1337 default:
1338 return error(GL_INVALID_ENUM);
1339 }
1340
Chris Forbes108f3e12018-08-30 19:41:59 -07001341 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001342
1343 if(context)
1344 {
1345 context->setDepthFunc(func);
1346 }
1347}
1348
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001349void GL_APIENTRY DepthMask(GLboolean flag)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001350{
1351 TRACE("(GLboolean flag = %d)", flag);
1352
Chris Forbes108f3e12018-08-30 19:41:59 -07001353 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001354
1355 if(context)
1356 {
1357 context->setDepthMask(flag != GL_FALSE);
1358 }
1359}
1360
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001361void GL_APIENTRY DepthRangef(GLclampf zNear, GLclampf zFar)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001362{
1363 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1364
Chris Forbes108f3e12018-08-30 19:41:59 -07001365 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001366
1367 if(context)
1368 {
1369 context->setDepthRange(zNear, zFar);
1370 }
1371}
1372
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001373void GL_APIENTRY DetachShader(GLuint program, GLuint shader)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001374{
1375 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1376
Chris Forbes108f3e12018-08-30 19:41:59 -07001377 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001378
1379 if(context)
1380 {
1381
1382 es2::Program *programObject = context->getProgram(program);
1383 es2::Shader *shaderObject = context->getShader(shader);
1384
1385 if(!programObject)
1386 {
1387 es2::Shader *shaderByProgramHandle;
1388 shaderByProgramHandle = context->getShader(program);
1389 if(!shaderByProgramHandle)
1390 {
1391 return error(GL_INVALID_VALUE);
1392 }
1393 else
1394 {
1395 return error(GL_INVALID_OPERATION);
1396 }
1397 }
1398
1399 if(!shaderObject)
1400 {
1401 es2::Program *programByShaderHandle = context->getProgram(shader);
1402 if(!programByShaderHandle)
1403 {
1404 return error(GL_INVALID_VALUE);
1405 }
1406 else
1407 {
1408 return error(GL_INVALID_OPERATION);
1409 }
1410 }
1411
1412 if(!programObject->detachShader(shaderObject))
1413 {
1414 return error(GL_INVALID_OPERATION);
1415 }
1416 }
1417}
1418
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001419void GL_APIENTRY Disable(GLenum cap)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001420{
1421 TRACE("(GLenum cap = 0x%X)", cap);
1422
Chris Forbes108f3e12018-08-30 19:41:59 -07001423 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001424
1425 if(context)
1426 {
1427 switch(cap)
1428 {
1429 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1430 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1431 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1432 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1433 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1434 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1435 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1436 case GL_BLEND: context->setBlendEnabled(false); break;
1437 case GL_DITHER: context->setDitherEnabled(false); break;
1438 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1439 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1440 default:
1441 return error(GL_INVALID_ENUM);
1442 }
1443 }
1444}
1445
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001446void GL_APIENTRY DisableVertexAttribArray(GLuint index)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001447{
1448 TRACE("(GLuint index = %d)", index);
1449
1450 if(index >= es2::MAX_VERTEX_ATTRIBS)
1451 {
1452 return error(GL_INVALID_VALUE);
1453 }
1454
Chris Forbes108f3e12018-08-30 19:41:59 -07001455 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001456
1457 if(context)
1458 {
1459 context->setVertexAttribArrayEnabled(index, false);
1460 }
1461}
1462
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001463void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001464{
1465 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1466
1467 switch(mode)
1468 {
1469 case GL_POINTS:
1470 case GL_LINES:
1471 case GL_LINE_LOOP:
1472 case GL_LINE_STRIP:
1473 case GL_TRIANGLES:
1474 case GL_TRIANGLE_FAN:
1475 case GL_TRIANGLE_STRIP:
1476 break;
1477 default:
1478 return error(GL_INVALID_ENUM);
1479 }
1480
1481 if(count < 0 || first < 0)
1482 {
1483 return error(GL_INVALID_VALUE);
1484 }
1485
Chris Forbes108f3e12018-08-30 19:41:59 -07001486 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001487
1488 if(context)
1489 {
1490 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1491 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1492 {
1493 return error(GL_INVALID_OPERATION);
1494 }
1495
1496 context->drawArrays(mode, first, count);
1497 }
1498}
1499
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001500void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001501{
1502 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1503 mode, count, type, indices);
1504
1505 switch(mode)
1506 {
1507 case GL_POINTS:
1508 case GL_LINES:
1509 case GL_LINE_LOOP:
1510 case GL_LINE_STRIP:
1511 case GL_TRIANGLES:
1512 case GL_TRIANGLE_FAN:
1513 case GL_TRIANGLE_STRIP:
1514 break;
1515 default:
1516 return error(GL_INVALID_ENUM);
1517 }
1518
1519 if(count < 0)
1520 {
1521 return error(GL_INVALID_VALUE);
1522 }
1523
Chris Forbes108f3e12018-08-30 19:41:59 -07001524 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001525
1526 if(context)
1527 {
1528 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1529 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1530 {
1531 return error(GL_INVALID_OPERATION);
1532 }
1533
1534 switch(type)
1535 {
1536 case GL_UNSIGNED_BYTE:
1537 case GL_UNSIGNED_SHORT:
1538 case GL_UNSIGNED_INT:
1539 break;
1540 default:
1541 return error(GL_INVALID_ENUM);
1542 }
1543
1544 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1545 }
1546}
1547
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001548void GL_APIENTRY DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001549{
1550 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1551 mode, first, count, instanceCount);
1552
1553 switch(mode)
1554 {
1555 case GL_POINTS:
1556 case GL_LINES:
1557 case GL_LINE_LOOP:
1558 case GL_LINE_STRIP:
1559 case GL_TRIANGLES:
1560 case GL_TRIANGLE_FAN:
1561 case GL_TRIANGLE_STRIP:
1562 break;
1563 default:
1564 return error(GL_INVALID_ENUM);
1565 }
1566
1567 if(count < 0 || instanceCount < 0)
1568 {
1569 return error(GL_INVALID_VALUE);
1570 }
1571
Chris Forbes108f3e12018-08-30 19:41:59 -07001572 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001573
1574 if(context)
1575 {
1576 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1577 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1578 {
1579 return error(GL_INVALID_OPERATION);
1580 }
1581
1582 context->drawArrays(mode, first, count, instanceCount);
1583 }
1584}
1585
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001586void GL_APIENTRY DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001587{
1588 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1589 mode, count, type, indices, instanceCount);
1590
1591 switch(mode)
1592 {
1593 case GL_POINTS:
1594 case GL_LINES:
1595 case GL_LINE_LOOP:
1596 case GL_LINE_STRIP:
1597 case GL_TRIANGLES:
1598 case GL_TRIANGLE_FAN:
1599 case GL_TRIANGLE_STRIP:
1600 break;
1601 default:
1602 return error(GL_INVALID_ENUM);
1603 }
1604
1605 switch(type)
1606 {
1607 case GL_UNSIGNED_BYTE:
1608 case GL_UNSIGNED_SHORT:
1609 case GL_UNSIGNED_INT:
1610 break;
1611 default:
1612 return error(GL_INVALID_ENUM);
1613 }
1614
1615 if(count < 0 || instanceCount < 0)
1616 {
1617 return error(GL_INVALID_VALUE);
1618 }
1619
Chris Forbes108f3e12018-08-30 19:41:59 -07001620 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001621
1622 if(context)
1623 {
1624 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1625 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1626 {
1627 return error(GL_INVALID_OPERATION);
1628 }
1629
1630 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1631 }
1632}
1633
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001634void GL_APIENTRY VertexAttribDivisorEXT(GLuint index, GLuint divisor)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001635{
1636 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1637
Chris Forbes108f3e12018-08-30 19:41:59 -07001638 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001639
1640 if(context)
1641 {
1642 if(index >= es2::MAX_VERTEX_ATTRIBS)
1643 {
1644 return error(GL_INVALID_VALUE);
1645 }
1646
1647 context->setVertexAttribDivisor(index, divisor);
1648 }
1649}
1650
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001651void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001652{
1653 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1654 mode, first, count, instanceCount);
1655
1656 switch(mode)
1657 {
1658 case GL_POINTS:
1659 case GL_LINES:
1660 case GL_LINE_LOOP:
1661 case GL_LINE_STRIP:
1662 case GL_TRIANGLES:
1663 case GL_TRIANGLE_FAN:
1664 case GL_TRIANGLE_STRIP:
1665 break;
1666 default:
1667 return error(GL_INVALID_ENUM);
1668 }
1669
1670 if(count < 0 || instanceCount < 0)
1671 {
1672 return error(GL_INVALID_VALUE);
1673 }
1674
Chris Forbes108f3e12018-08-30 19:41:59 -07001675 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001676
1677 if(context)
1678 {
1679 if(!context->hasZeroDivisor())
1680 {
1681 return error(GL_INVALID_OPERATION);
1682 }
1683
1684 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1685 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1686 {
1687 return error(GL_INVALID_OPERATION);
1688 }
1689
1690 context->drawArrays(mode, first, count, instanceCount);
1691 }
1692}
1693
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001694void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001695{
1696 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1697 mode, count, type, indices, instanceCount);
1698
1699 switch(mode)
1700 {
1701 case GL_POINTS:
1702 case GL_LINES:
1703 case GL_LINE_LOOP:
1704 case GL_LINE_STRIP:
1705 case GL_TRIANGLES:
1706 case GL_TRIANGLE_FAN:
1707 case GL_TRIANGLE_STRIP:
1708 break;
1709 default:
1710 return error(GL_INVALID_ENUM);
1711 }
1712
1713 switch(type)
1714 {
1715 case GL_UNSIGNED_BYTE:
1716 case GL_UNSIGNED_SHORT:
1717 case GL_UNSIGNED_INT:
1718 break;
1719 default:
1720 return error(GL_INVALID_ENUM);
1721 }
1722
1723 if(count < 0 || instanceCount < 0)
1724 {
1725 return error(GL_INVALID_VALUE);
1726 }
1727
Chris Forbes108f3e12018-08-30 19:41:59 -07001728 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001729
1730 if(context)
1731 {
1732 if(!context->hasZeroDivisor())
1733 {
1734 return error(GL_INVALID_OPERATION);
1735 }
1736
1737 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1738 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1739 {
1740 return error(GL_INVALID_OPERATION);
1741 }
1742
1743 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1744 }
1745}
1746
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001747void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001748{
1749 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1750
Chris Forbes108f3e12018-08-30 19:41:59 -07001751 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001752
1753 if(context)
1754 {
1755 if(index >= MAX_VERTEX_ATTRIBS)
1756 {
1757 return error(GL_INVALID_VALUE);
1758 }
1759
1760 context->setVertexAttribDivisor(index, divisor);
1761 }
1762}
1763
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001764void GL_APIENTRY Enable(GLenum cap)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001765{
1766 TRACE("(GLenum cap = 0x%X)", cap);
1767
Chris Forbes108f3e12018-08-30 19:41:59 -07001768 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001769
1770 if(context)
1771 {
1772 switch(cap)
1773 {
1774 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1775 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1776 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1777 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1778 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1779 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1780 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1781 case GL_BLEND: context->setBlendEnabled(true); break;
1782 case GL_DITHER: context->setDitherEnabled(true); break;
1783 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1784 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1785 default:
1786 return error(GL_INVALID_ENUM);
1787 }
1788 }
1789}
1790
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001791void GL_APIENTRY EnableVertexAttribArray(GLuint index)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001792{
1793 TRACE("(GLuint index = %d)", index);
1794
1795 if(index >= es2::MAX_VERTEX_ATTRIBS)
1796 {
1797 return error(GL_INVALID_VALUE);
1798 }
1799
Chris Forbes108f3e12018-08-30 19:41:59 -07001800 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001801
1802 if(context)
1803 {
1804 context->setVertexAttribArrayEnabled(index, true);
1805 }
1806}
1807
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001808void GL_APIENTRY EndQueryEXT(GLenum target)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001809{
1810 TRACE("GLenum target = 0x%X)", target);
1811
1812 switch(target)
1813 {
1814 case GL_ANY_SAMPLES_PASSED_EXT:
1815 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1816 break;
1817 default:
1818 return error(GL_INVALID_ENUM);
1819 }
1820
Chris Forbes108f3e12018-08-30 19:41:59 -07001821 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001822
1823 if(context)
1824 {
1825 context->endQuery(target);
1826 }
1827}
1828
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001829void GL_APIENTRY FinishFenceNV(GLuint fence)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001830{
1831 TRACE("(GLuint fence = %d)", fence);
1832
Chris Forbes108f3e12018-08-30 19:41:59 -07001833 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001834
1835 if(context)
1836 {
1837 es2::Fence *fenceObject = context->getFence(fence);
1838
1839 if(!fenceObject)
1840 {
1841 return error(GL_INVALID_OPERATION);
1842 }
1843
1844 fenceObject->finishFence();
1845 }
1846}
1847
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001848void GL_APIENTRY Finish(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001849{
1850 TRACE("()");
1851
Chris Forbes108f3e12018-08-30 19:41:59 -07001852 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001853
1854 if(context)
1855 {
1856 context->finish();
1857 }
1858}
1859
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001860void GL_APIENTRY Flush(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001861{
1862 TRACE("()");
1863
Chris Forbes108f3e12018-08-30 19:41:59 -07001864 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001865
1866 if(context)
1867 {
1868 context->flush();
1869 }
1870}
1871
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001872void GL_APIENTRY FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001873{
1874 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1875 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1876
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001877 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -04001878 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1879 {
1880 return error(GL_INVALID_ENUM);
1881 }
1882
Chris Forbes108f3e12018-08-30 19:41:59 -07001883 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001884
1885 if(context)
1886 {
1887 es2::Framebuffer *framebuffer = nullptr;
1888 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001889 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001890 {
1891 framebuffer = context->getReadFramebuffer();
1892 framebufferName = context->getReadFramebufferName();
1893 }
1894 else
1895 {
1896 framebuffer = context->getDrawFramebuffer();
1897 framebufferName = context->getDrawFramebufferName();
1898 }
1899
1900 if(!framebuffer || framebufferName == 0)
1901 {
1902 return error(GL_INVALID_OPERATION);
1903 }
1904
1905 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1906 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1907 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1908 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1909 if(renderbuffer != 0)
1910 {
1911 if(!context->getRenderbuffer(renderbuffer))
1912 {
1913 return error(GL_INVALID_OPERATION);
1914 }
1915 }
1916
Nicolas Capens0bac2852016-05-07 06:09:58 -04001917 switch(attachment)
1918 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001919 case GL_DEPTH_ATTACHMENT:
1920 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1921 break;
1922 case GL_STENCIL_ATTACHMENT:
1923 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1924 break;
1925 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capens83463112018-06-12 23:55:16 -04001926 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1927 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1928 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001929 default:
Nicolas Capens4e344192018-10-24 21:01:17 -04001930 if(attachment < GL_COLOR_ATTACHMENT0 || attachment > GL_COLOR_ATTACHMENT31)
Nicolas Capens83463112018-06-12 23:55:16 -04001931 {
1932 return error(GL_INVALID_ENUM);
1933 }
Nicolas Capens4e344192018-10-24 21:01:17 -04001934
1935 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
1936 {
1937 return error(GL_INVALID_OPERATION);
1938 }
1939
Nicolas Capens83463112018-06-12 23:55:16 -04001940 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
1941 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001942 }
1943 }
1944}
1945
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001946void GL_APIENTRY FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001947{
1948 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1949 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1950
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001951 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001952 {
1953 return error(GL_INVALID_ENUM);
1954 }
1955
Chris Forbes108f3e12018-08-30 19:41:59 -07001956 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001957
1958 if(context)
1959 {
1960 if(texture == 0)
1961 {
1962 textarget = GL_NONE;
1963 }
1964 else
1965 {
1966 es2::Texture *tex = context->getTexture(texture);
1967
1968 if(!tex)
1969 {
1970 return error(GL_INVALID_OPERATION);
1971 }
1972
1973 switch(textarget)
1974 {
1975 case GL_TEXTURE_2D:
1976 if(tex->getTarget() != GL_TEXTURE_2D)
1977 {
1978 return error(GL_INVALID_OPERATION);
1979 }
1980 break;
Alexis Hetu46768622018-01-16 22:09:28 -05001981 case GL_TEXTURE_RECTANGLE_ARB:
1982 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
1983 {
1984 return error(GL_INVALID_OPERATION);
1985 }
1986 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001987 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1988 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1989 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1990 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1991 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1992 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1993 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
1994 {
1995 return error(GL_INVALID_OPERATION);
1996 }
1997 break;
1998 default:
1999 return error(GL_INVALID_ENUM);
2000 }
2001
Nicolas Capens83463112018-06-12 23:55:16 -04002002 if((textarget == GL_TEXTURE_RECTANGLE_ARB) && (level != 0))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002003 {
2004 return error(GL_INVALID_VALUE);
2005 }
2006
2007 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
2008 {
2009 return error(GL_INVALID_VALUE);
2010 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04002011
2012 if(tex->isCompressed(textarget, level))
2013 {
2014 return error(GL_INVALID_OPERATION);
2015 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002016 }
2017
2018 es2::Framebuffer *framebuffer = nullptr;
2019 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002020 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002021 {
2022 framebuffer = context->getReadFramebuffer();
2023 framebufferName = context->getReadFramebufferName();
2024 }
2025 else
2026 {
2027 framebuffer = context->getDrawFramebuffer();
2028 framebufferName = context->getDrawFramebufferName();
2029 }
2030
2031 if(framebufferName == 0 || !framebuffer)
2032 {
2033 return error(GL_INVALID_OPERATION);
2034 }
2035
2036 switch(attachment)
2037 {
Nicolas Capens83463112018-06-12 23:55:16 -04002038 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2039 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
2040 case GL_DEPTH_STENCIL_ATTACHMENT:
2041 framebuffer->setDepthbuffer(textarget, texture, level);
2042 framebuffer->setStencilbuffer(textarget, texture, level);
2043 break;
2044 default:
Nicolas Capens4e344192018-10-24 21:01:17 -04002045 if(attachment < GL_COLOR_ATTACHMENT0 || attachment > GL_COLOR_ATTACHMENT31)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002046 {
2047 return error(GL_INVALID_ENUM);
2048 }
Nicolas Capens4e344192018-10-24 21:01:17 -04002049
2050 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2051 {
2052 return error(GL_INVALID_OPERATION);
2053 }
2054
Nicolas Capens0bac2852016-05-07 06:09:58 -04002055 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2056 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002057 }
2058 }
2059}
2060
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002061void GL_APIENTRY FrontFace(GLenum mode)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002062{
2063 TRACE("(GLenum mode = 0x%X)", mode);
2064
2065 switch(mode)
2066 {
2067 case GL_CW:
2068 case GL_CCW:
2069 {
Chris Forbes108f3e12018-08-30 19:41:59 -07002070 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002071
2072 if(context)
2073 {
2074 context->setFrontFace(mode);
2075 }
2076 }
2077 break;
2078 default:
2079 return error(GL_INVALID_ENUM);
2080 }
2081}
2082
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002083void GL_APIENTRY GenBuffers(GLsizei n, GLuint* buffers)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002084{
2085 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2086
2087 if(n < 0)
2088 {
2089 return error(GL_INVALID_VALUE);
2090 }
2091
Chris Forbes108f3e12018-08-30 19:41:59 -07002092 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002093
2094 if(context)
2095 {
2096 for(int i = 0; i < n; i++)
2097 {
2098 buffers[i] = context->createBuffer();
2099 }
2100 }
2101}
2102
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002103void GL_APIENTRY GenerateMipmap(GLenum target)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002104{
2105 TRACE("(GLenum target = 0x%X)", target);
2106
Chris Forbes108f3e12018-08-30 19:41:59 -07002107 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002108
2109 if(context)
2110 {
Nicolas Capens24cb99d2019-03-18 12:42:22 -04002111 es2::Texture *texture = context->getTargetTexture(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002112
Nicolas Capens24cb99d2019-03-18 12:42:22 -04002113 if(!texture)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002114 {
Nicolas Capens24cb99d2019-03-18 12:42:22 -04002115 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002116 }
2117
Nicolas Capens83463112018-06-12 23:55:16 -04002118 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel())))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002119 {
2120 return error(GL_INVALID_OPERATION);
2121 }
2122
Nicolas Capens24cb99d2019-03-18 12:42:22 -04002123 if(target == GL_TEXTURE_CUBE_MAP)
2124 {
2125 TextureCubeMap *cube = context->getTextureCubeMap();
2126
2127 if(!cube->isCubeComplete())
2128 {
2129 return error(GL_INVALID_OPERATION);
2130 }
2131 }
2132
2133 // [OpenGL ES 3.2]: "Otherwise, if levelbase is not defined, or if any dimension
2134 // is zero, all mipmap levels are left unchanged. This is not an error."
2135 if(!texture->isBaseLevelDefined())
2136 {
2137 return;
2138 }
2139
Nicolas Capens0bac2852016-05-07 06:09:58 -04002140 texture->generateMipmaps();
2141 }
2142}
2143
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002144void GL_APIENTRY GenFencesNV(GLsizei n, GLuint* fences)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002145{
2146 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2147
2148 if(n < 0)
2149 {
2150 return error(GL_INVALID_VALUE);
2151 }
2152
Chris Forbes108f3e12018-08-30 19:41:59 -07002153 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002154
2155 if(context)
2156 {
2157 for(int i = 0; i < n; i++)
2158 {
2159 fences[i] = context->createFence();
2160 }
2161 }
2162}
2163
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002164void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint* framebuffers)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002165{
2166 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2167
2168 if(n < 0)
2169 {
2170 return error(GL_INVALID_VALUE);
2171 }
2172
Chris Forbes108f3e12018-08-30 19:41:59 -07002173 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002174
2175 if(context)
2176 {
2177 for(int i = 0; i < n; i++)
2178 {
2179 framebuffers[i] = context->createFramebuffer();
2180 }
2181 }
2182}
2183
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002184void GL_APIENTRY GenQueriesEXT(GLsizei n, GLuint* ids)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002185{
2186 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2187
2188 if(n < 0)
2189 {
2190 return error(GL_INVALID_VALUE);
2191 }
2192
Chris Forbes108f3e12018-08-30 19:41:59 -07002193 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002194
2195 if(context)
2196 {
2197 for(int i = 0; i < n; i++)
2198 {
2199 ids[i] = context->createQuery();
2200 }
2201 }
2202}
2203
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002204void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002205{
2206 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2207
2208 if(n < 0)
2209 {
2210 return error(GL_INVALID_VALUE);
2211 }
2212
Chris Forbes108f3e12018-08-30 19:41:59 -07002213 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002214
2215 if(context)
2216 {
2217 for(int i = 0; i < n; i++)
2218 {
2219 renderbuffers[i] = context->createRenderbuffer();
2220 }
2221 }
2222}
2223
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002224void GL_APIENTRY GenTextures(GLsizei n, GLuint* textures)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002225{
2226 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2227
2228 if(n < 0)
2229 {
2230 return error(GL_INVALID_VALUE);
2231 }
2232
Chris Forbes108f3e12018-08-30 19:41:59 -07002233 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002234
2235 if(context)
2236 {
2237 for(int i = 0; i < n; i++)
2238 {
2239 textures[i] = context->createTexture();
2240 }
2241 }
2242}
2243
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002244void GL_APIENTRY GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002245{
2246 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2247 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2248 program, index, bufsize, length, size, type, name);
2249
2250 if(bufsize < 0)
2251 {
2252 return error(GL_INVALID_VALUE);
2253 }
2254
Chris Forbes108f3e12018-08-30 19:41:59 -07002255 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002256
2257 if(context)
2258 {
2259 es2::Program *programObject = context->getProgram(program);
2260
2261 if(!programObject)
2262 {
2263 if(context->getShader(program))
2264 {
2265 return error(GL_INVALID_OPERATION);
2266 }
2267 else
2268 {
2269 return error(GL_INVALID_VALUE);
2270 }
2271 }
2272
2273 if(index >= programObject->getActiveAttributeCount())
2274 {
2275 return error(GL_INVALID_VALUE);
2276 }
2277
2278 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2279 }
2280}
2281
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002282void GL_APIENTRY GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002283{
2284 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2285 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2286 program, index, bufsize, length, size, type, name);
2287
2288 if(bufsize < 0)
2289 {
2290 return error(GL_INVALID_VALUE);
2291 }
2292
Chris Forbes108f3e12018-08-30 19:41:59 -07002293 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002294
2295 if(context)
2296 {
2297 es2::Program *programObject = context->getProgram(program);
2298
2299 if(!programObject)
2300 {
2301 if(context->getShader(program))
2302 {
2303 return error(GL_INVALID_OPERATION);
2304 }
2305 else
2306 {
2307 return error(GL_INVALID_VALUE);
2308 }
2309 }
2310
2311 if(index >= programObject->getActiveUniformCount())
2312 {
2313 return error(GL_INVALID_VALUE);
2314 }
2315
2316 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2317 }
2318}
2319
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002320void GL_APIENTRY GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002321{
2322 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2323 program, maxcount, count, shaders);
2324
2325 if(maxcount < 0)
2326 {
2327 return error(GL_INVALID_VALUE);
2328 }
2329
Chris Forbes108f3e12018-08-30 19:41:59 -07002330 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002331
2332 if(context)
2333 {
2334 es2::Program *programObject = context->getProgram(program);
2335
2336 if(!programObject)
2337 {
2338 if(context->getShader(program))
2339 {
2340 return error(GL_INVALID_OPERATION);
2341 }
2342 else
2343 {
2344 return error(GL_INVALID_VALUE);
2345 }
2346 }
2347
2348 return programObject->getAttachedShaders(maxcount, count, shaders);
2349 }
2350}
2351
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002352int GL_APIENTRY GetAttribLocation(GLuint program, const GLchar* name)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002353{
2354 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2355
Chris Forbes108f3e12018-08-30 19:41:59 -07002356 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002357
2358 if(context)
2359 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04002360 es2::Program *programObject = context->getProgram(program);
2361
2362 if(!programObject)
2363 {
2364 if(context->getShader(program))
2365 {
2366 return error(GL_INVALID_OPERATION, -1);
2367 }
2368 else
2369 {
2370 return error(GL_INVALID_VALUE, -1);
2371 }
2372 }
2373
2374 if(!programObject->isLinked())
2375 {
2376 return error(GL_INVALID_OPERATION, -1);
2377 }
2378
2379 return programObject->getAttributeLocation(name);
2380 }
2381
2382 return -1;
2383}
2384
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002385void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002386{
2387 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2388
Chris Forbes108f3e12018-08-30 19:41:59 -07002389 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002390
2391 if(context)
2392 {
2393 if(!(context->getBooleanv(pname, params)))
2394 {
2395 GLenum nativeType;
2396 unsigned int numParams = 0;
2397 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2398 return error(GL_INVALID_ENUM);
2399
2400 if(numParams == 0)
2401 return; // it is known that the pname is valid, but there are no parameters to return
2402
2403 if(nativeType == GL_FLOAT)
2404 {
2405 GLfloat *floatParams = nullptr;
2406 floatParams = new GLfloat[numParams];
2407
2408 context->getFloatv(pname, floatParams);
2409
2410 for(unsigned int i = 0; i < numParams; ++i)
2411 {
2412 if(floatParams[i] == 0.0f)
2413 params[i] = GL_FALSE;
2414 else
2415 params[i] = GL_TRUE;
2416 }
2417
2418 delete [] floatParams;
2419 }
2420 else if(nativeType == GL_INT)
2421 {
2422 GLint *intParams = nullptr;
2423 intParams = new GLint[numParams];
2424
2425 context->getIntegerv(pname, intParams);
2426
2427 for(unsigned int i = 0; i < numParams; ++i)
2428 {
2429 if(intParams[i] == 0)
2430 params[i] = GL_FALSE;
2431 else
2432 params[i] = GL_TRUE;
2433 }
2434
2435 delete [] intParams;
2436 }
2437 }
2438 }
2439}
2440
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002441void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002442{
2443 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2444
Chris Forbes108f3e12018-08-30 19:41:59 -07002445 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002446
2447 if(context)
2448 {
2449 es2::Buffer *buffer;
2450 if(!context->getBuffer(target, &buffer))
2451 {
2452 return error(GL_INVALID_ENUM);
2453 }
2454
2455 if(!buffer)
2456 {
2457 // A null buffer means that "0" is bound to the requested buffer target
2458 return error(GL_INVALID_OPERATION);
2459 }
2460
Nicolas Capens0bac2852016-05-07 06:09:58 -04002461 switch(pname)
2462 {
2463 case GL_BUFFER_USAGE:
2464 *params = buffer->usage();
2465 break;
2466 case GL_BUFFER_SIZE:
2467 *params = (GLint)buffer->size();
2468 break;
2469 case GL_BUFFER_ACCESS_FLAGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002470 *params = buffer->access();
2471 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002472 case GL_BUFFER_MAPPED:
Nicolas Capens83463112018-06-12 23:55:16 -04002473 *params = buffer->isMapped();
2474 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002475 case GL_BUFFER_MAP_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002476 *params = (GLint)buffer->length();
2477 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002478 case GL_BUFFER_MAP_OFFSET:
Nicolas Capens83463112018-06-12 23:55:16 -04002479 *params = (GLint)buffer->offset();
2480 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002481 default:
2482 return error(GL_INVALID_ENUM);
2483 }
2484 }
2485}
2486
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002487GLenum GL_APIENTRY GetError(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002488{
2489 TRACE("()");
2490
Chris Forbes108f3e12018-08-30 19:41:59 -07002491 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002492
2493 if(context)
2494 {
2495 return context->getError();
2496 }
2497
2498 return GL_NO_ERROR;
2499}
2500
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002501void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002502{
2503 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2504
Chris Forbes108f3e12018-08-30 19:41:59 -07002505 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002506
2507 if(context)
2508 {
2509 es2::Fence *fenceObject = context->getFence(fence);
2510
2511 if(!fenceObject)
2512 {
2513 return error(GL_INVALID_OPERATION);
2514 }
2515
2516 fenceObject->getFenceiv(pname, params);
2517 }
2518}
2519
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002520void GL_APIENTRY GetFloatv(GLenum pname, GLfloat* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002521{
2522 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2523
Chris Forbes108f3e12018-08-30 19:41:59 -07002524 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002525
2526 if(context)
2527 {
2528 if(!(context->getFloatv(pname, params)))
2529 {
2530 GLenum nativeType;
2531 unsigned int numParams = 0;
2532 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2533 return error(GL_INVALID_ENUM);
2534
2535 if(numParams == 0)
2536 return; // it is known that the pname is valid, but that there are no parameters to return.
2537
2538 if(nativeType == GL_BOOL)
2539 {
2540 GLboolean *boolParams = nullptr;
2541 boolParams = new GLboolean[numParams];
2542
2543 context->getBooleanv(pname, boolParams);
2544
2545 for(unsigned int i = 0; i < numParams; ++i)
2546 {
2547 if(boolParams[i] == GL_FALSE)
2548 params[i] = 0.0f;
2549 else
2550 params[i] = 1.0f;
2551 }
2552
2553 delete [] boolParams;
2554 }
2555 else if(nativeType == GL_INT)
2556 {
2557 GLint *intParams = nullptr;
2558 intParams = new GLint[numParams];
2559
2560 context->getIntegerv(pname, intParams);
2561
2562 for(unsigned int i = 0; i < numParams; ++i)
2563 {
2564 params[i] = (GLfloat)intParams[i];
2565 }
2566
2567 delete [] intParams;
2568 }
2569 }
2570 }
2571}
2572
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002573void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002574{
2575 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2576 target, attachment, pname, params);
2577
Chris Forbes108f3e12018-08-30 19:41:59 -07002578 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002579
2580 if(context)
2581 {
2582 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2583 {
2584 return error(GL_INVALID_ENUM);
2585 }
2586
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002587 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002588
Nicolas Capens0bac2852016-05-07 06:09:58 -04002589 if(target == GL_READ_FRAMEBUFFER)
2590 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002591 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002592 }
2593 else
2594 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002595 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002596 }
2597
Nicolas Capens0bac2852016-05-07 06:09:58 -04002598 switch(attachment)
2599 {
2600 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002601 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002602 case GL_STENCIL:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002603 if(framebufferName != 0)
2604 {
2605 return error(GL_INVALID_OPERATION);
2606 }
2607 break;
2608 case GL_DEPTH_ATTACHMENT:
2609 case GL_STENCIL_ATTACHMENT:
2610 if(framebufferName == 0)
2611 {
2612 return error(GL_INVALID_OPERATION);
2613 }
2614 break;
2615 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002616 if(framebufferName == 0)
2617 {
2618 return error(GL_INVALID_OPERATION);
2619 }
2620 break;
2621 default:
Nicolas Capens4e344192018-10-24 21:01:17 -04002622 if(framebufferName == 0)
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002623 {
Nicolas Capens4e344192018-10-24 21:01:17 -04002624 return error(GL_INVALID_OPERATION);
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002625 }
Nicolas Capens4e344192018-10-24 21:01:17 -04002626
2627 if(attachment < GL_COLOR_ATTACHMENT0 || attachment > GL_COLOR_ATTACHMENT31)
2628 {
2629 return error(GL_INVALID_ENUM);
2630 }
2631
2632 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2633 {
2634 return error(GL_INVALID_OPERATION);
2635 }
2636 break;
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002637 }
2638
2639 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2640
Alexis Hetu5cd502b2018-03-22 08:29:31 -04002641 if(!framebuffer)
2642 {
2643 return error(GL_INVALID_OPERATION);
2644 }
2645
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002646 GLenum attachmentType;
2647 GLuint attachmentHandle;
2648 GLint attachmentLayer;
2649 Renderbuffer *renderbuffer = nullptr;
2650 switch(attachment)
2651 {
2652 case GL_BACK:
2653 attachmentType = framebuffer->getColorbufferType(0);
2654 attachmentHandle = framebuffer->getColorbufferName(0);
2655 attachmentLayer = framebuffer->getColorbufferLayer(0);
2656 renderbuffer = framebuffer->getColorbuffer(0);
2657 break;
2658 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002659 case GL_DEPTH_ATTACHMENT:
2660 attachmentType = framebuffer->getDepthbufferType();
2661 attachmentHandle = framebuffer->getDepthbufferName();
2662 attachmentLayer = framebuffer->getDepthbufferLayer();
2663 renderbuffer = framebuffer->getDepthbuffer();
2664 break;
2665 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002666 case GL_STENCIL_ATTACHMENT:
2667 attachmentType = framebuffer->getStencilbufferType();
2668 attachmentHandle = framebuffer->getStencilbufferName();
2669 attachmentLayer = framebuffer->getStencilbufferLayer();
2670 renderbuffer = framebuffer->getStencilbuffer();
2671 break;
2672 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002673 attachmentType = framebuffer->getDepthbufferType();
2674 attachmentHandle = framebuffer->getDepthbufferName();
2675 attachmentLayer = framebuffer->getDepthbufferLayer();
2676 renderbuffer = framebuffer->getDepthbuffer();
2677
2678 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002679 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002680 // Different attachments to DEPTH and STENCIL, query fails
2681 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002682 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002683 break;
2684 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002685 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2686 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2687 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2688 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2689 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2690 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002691 }
2692
2693 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002694 if(framebufferName == 0)
2695 {
2696 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2697 }
2698 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002699 {
2700 attachmentObjectType = attachmentType;
2701 }
2702 else if(es2::IsTextureTarget(attachmentType))
2703 {
2704 attachmentObjectType = GL_TEXTURE;
2705 }
2706 else UNREACHABLE(attachmentType);
2707
2708 if(attachmentObjectType != GL_NONE)
2709 {
2710 switch(pname)
2711 {
2712 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2713 *params = attachmentObjectType;
2714 break;
2715 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002716 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002717 {
2718 *params = attachmentHandle;
2719 }
2720 else
2721 {
2722 return error(GL_INVALID_ENUM);
2723 }
2724 break;
2725 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2726 if(attachmentObjectType == GL_TEXTURE)
2727 {
Nicolas Capens83463112018-06-12 23:55:16 -04002728 *params = renderbuffer->getLevel();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002729 }
2730 else
2731 {
2732 return error(GL_INVALID_ENUM);
2733 }
2734 break;
2735 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2736 if(attachmentObjectType == GL_TEXTURE)
2737 {
2738 if(es2::IsCubemapTextureTarget(attachmentType))
2739 {
2740 *params = attachmentType;
2741 }
2742 else
2743 {
2744 *params = 0;
2745 }
2746 }
2747 else
2748 {
2749 return error(GL_INVALID_ENUM);
2750 }
2751 break;
2752 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
Nicolas Capens83463112018-06-12 23:55:16 -04002753 *params = attachmentLayer;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002754 break;
2755 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002756 *params = renderbuffer->getRedSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002757 break;
2758 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002759 *params = renderbuffer->getGreenSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002760 break;
2761 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002762 *params = renderbuffer->getBlueSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002763 break;
2764 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002765 *params = renderbuffer->getAlphaSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002766 break;
2767 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002768 *params = renderbuffer->getDepthSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002769 break;
2770 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002771 *params = renderbuffer->getStencilSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002772 break;
2773 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002774 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2775 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002776 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002777 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002778 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002779
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002780 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002781 break;
2782 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Nicolas Capens83463112018-06-12 23:55:16 -04002783 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002784 break;
2785 default:
2786 return error(GL_INVALID_ENUM);
2787 }
2788 }
2789 else
2790 {
2791 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2792 // is NONE, then querying any other pname will generate INVALID_ENUM.
2793
2794 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2795 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2796 // INVALID_OPERATION for all other pnames
2797
2798 switch(pname)
2799 {
2800 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2801 *params = GL_NONE;
2802 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002803 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002804 *params = 0;
2805 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002806 default:
Nicolas Capens83463112018-06-12 23:55:16 -04002807 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002808 }
2809 }
2810 }
2811}
2812
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002813GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002814{
2815 TRACE("()");
2816
2817 return GL_NO_ERROR;
2818}
2819
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002820void GL_APIENTRY GetIntegerv(GLenum pname, GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002821{
2822 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2823
Chris Forbes108f3e12018-08-30 19:41:59 -07002824 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002825
2826 if(!context)
2827 {
2828 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
Alistair Strachanc28d28a2018-03-24 12:24:00 -07002829 ERR("glGetIntegerv() called without current context.");
Nicolas Capens0bac2852016-05-07 06:09:58 -04002830
2831 // This is not spec compliant! When there is no current GL context, functions should
2832 // have no side effects. Google Maps queries these values before creating a context,
2833 // so we need this as a bug-compatible workaround.
2834 switch(pname)
2835 {
2836 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
2837 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
2838 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
2839 case GL_STENCIL_BITS: *params = 8; return;
2840 case GL_ALIASED_LINE_WIDTH_RANGE:
2841 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
2842 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
2843 return;
2844 }
2845 }
2846
2847 if(context)
2848 {
2849 if(!(context->getIntegerv(pname, params)))
2850 {
2851 GLenum nativeType;
2852 unsigned int numParams = 0;
2853 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2854 return error(GL_INVALID_ENUM);
2855
2856 if(numParams == 0)
2857 return; // it is known that pname is valid, but there are no parameters to return
2858
2859 if(nativeType == GL_BOOL)
2860 {
2861 GLboolean *boolParams = nullptr;
2862 boolParams = new GLboolean[numParams];
2863
2864 context->getBooleanv(pname, boolParams);
2865
2866 for(unsigned int i = 0; i < numParams; ++i)
2867 {
2868 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
2869 }
2870
2871 delete [] boolParams;
2872 }
2873 else if(nativeType == GL_FLOAT)
2874 {
2875 GLfloat *floatParams = nullptr;
2876 floatParams = new GLfloat[numParams];
2877
2878 context->getFloatv(pname, floatParams);
2879
2880 for(unsigned int i = 0; i < numParams; ++i)
2881 {
2882 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
2883 {
Alexis Hetu60e20282017-12-13 07:42:22 -05002884 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002885 }
2886 else
2887 {
2888 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
2889 }
2890 }
2891
2892 delete [] floatParams;
2893 }
2894 }
2895 }
2896}
2897
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002898void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002899{
2900 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
2901
Chris Forbes108f3e12018-08-30 19:41:59 -07002902 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002903
2904 if(context)
2905 {
2906 es2::Program *programObject = context->getProgram(program);
2907
2908 if(!programObject)
2909 {
2910 if(context->getShader(program))
2911 {
2912 return error(GL_INVALID_OPERATION);
2913 }
2914 else
2915 {
2916 return error(GL_INVALID_VALUE);
2917 }
2918 }
2919
Nicolas Capens0bac2852016-05-07 06:09:58 -04002920 switch(pname)
2921 {
2922 case GL_DELETE_STATUS:
2923 *params = programObject->isFlaggedForDeletion();
2924 return;
2925 case GL_LINK_STATUS:
2926 *params = programObject->isLinked();
2927 return;
2928 case GL_VALIDATE_STATUS:
2929 *params = programObject->isValidated();
2930 return;
2931 case GL_INFO_LOG_LENGTH:
2932 *params = (GLint)programObject->getInfoLogLength();
2933 return;
2934 case GL_ATTACHED_SHADERS:
2935 *params = programObject->getAttachedShadersCount();
2936 return;
2937 case GL_ACTIVE_ATTRIBUTES:
2938 *params = (GLint)programObject->getActiveAttributeCount();
2939 return;
2940 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
2941 *params = programObject->getActiveAttributeMaxLength();
2942 return;
2943 case GL_ACTIVE_UNIFORMS:
2944 *params = (GLint)programObject->getActiveUniformCount();
2945 return;
2946 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
2947 *params = programObject->getActiveUniformMaxLength();
2948 return;
2949 case GL_ACTIVE_UNIFORM_BLOCKS:
Nicolas Capens83463112018-06-12 23:55:16 -04002950 *params = (GLint)programObject->getActiveUniformBlockCount();
2951 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002952 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002953 *params = programObject->getActiveUniformBlockMaxLength();
2954 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002955 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04002956 *params = programObject->getTransformFeedbackBufferMode();
2957 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002958 case GL_TRANSFORM_FEEDBACK_VARYINGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002959 *params = programObject->getTransformFeedbackVaryingCount();
2960 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002961 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002962 *params = programObject->getTransformFeedbackVaryingMaxLength();
2963 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002964 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Nicolas Capens83463112018-06-12 23:55:16 -04002965 *params = programObject->getBinaryRetrievableHint();
2966 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002967 case GL_PROGRAM_BINARY_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002968 *params = programObject->getBinaryLength();
2969 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002970 default:
2971 return error(GL_INVALID_ENUM);
2972 }
2973 }
2974}
2975
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04002976void GL_APIENTRY GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002977{
2978 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
2979 program, bufsize, length, infolog);
2980
2981 if(bufsize < 0)
2982 {
2983 return error(GL_INVALID_VALUE);
2984 }
2985
Chris Forbes108f3e12018-08-30 19:41:59 -07002986 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002987
2988 if(context)
2989 {
2990 es2::Program *programObject = context->getProgram(program);
2991
2992 if(!programObject)
2993 {
2994 if(context->getShader(program))
2995 {
2996 return error(GL_INVALID_OPERATION);
2997 }
2998 else
2999 {
3000 return error(GL_INVALID_VALUE);
3001 }
3002 }
3003
3004 programObject->getInfoLog(bufsize, length, infolog);
3005 }
3006}
3007
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003008void GL_APIENTRY GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003009{
3010 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
3011
3012 switch(pname)
3013 {
3014 case GL_CURRENT_QUERY_EXT:
3015 break;
3016 default:
3017 return error(GL_INVALID_ENUM);
3018 }
3019
Chris Forbes108f3e12018-08-30 19:41:59 -07003020 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003021
3022 if(context)
3023 {
3024 params[0] = context->getActiveQuery(target);
3025 }
3026}
3027
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003028void GL_APIENTRY GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003029{
3030 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3031
3032 switch(pname)
3033 {
3034 case GL_QUERY_RESULT_EXT:
3035 case GL_QUERY_RESULT_AVAILABLE_EXT:
3036 break;
3037 default:
3038 return error(GL_INVALID_ENUM);
3039 }
3040
Chris Forbes108f3e12018-08-30 19:41:59 -07003041 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003042
3043 if(context)
3044 {
3045 es2::Query *queryObject = context->getQuery(name);
3046
3047 if(!queryObject)
3048 {
3049 return error(GL_INVALID_OPERATION);
3050 }
3051
3052 if(context->getActiveQuery(queryObject->getType()) == name)
3053 {
3054 return error(GL_INVALID_OPERATION);
3055 }
3056
3057 switch(pname)
3058 {
3059 case GL_QUERY_RESULT_EXT:
3060 params[0] = queryObject->getResult();
3061 break;
3062 case GL_QUERY_RESULT_AVAILABLE_EXT:
3063 params[0] = queryObject->isResultAvailable();
3064 break;
3065 default:
3066 ASSERT(false);
3067 }
3068 }
3069}
3070
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003071void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003072{
3073 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3074
Chris Forbes108f3e12018-08-30 19:41:59 -07003075 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003076
3077 if(context)
3078 {
3079 if(target != GL_RENDERBUFFER)
3080 {
3081 return error(GL_INVALID_ENUM);
3082 }
3083
3084 if(context->getRenderbufferName() == 0)
3085 {
3086 return error(GL_INVALID_OPERATION);
3087 }
3088
3089 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3090
3091 switch(pname)
3092 {
3093 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3094 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003095 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3096 {
3097 GLint internalformat = renderbuffer->getFormat();
3098 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3099 }
3100 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003101 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3102 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3103 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3104 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3105 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3106 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003107 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003108 default:
3109 return error(GL_INVALID_ENUM);
3110 }
3111 }
3112}
3113
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003114void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003115{
3116 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3117
Chris Forbes108f3e12018-08-30 19:41:59 -07003118 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003119
3120 if(context)
3121 {
3122 es2::Shader *shaderObject = context->getShader(shader);
3123
3124 if(!shaderObject)
3125 {
3126 if(context->getProgram(shader))
3127 {
3128 return error(GL_INVALID_OPERATION);
3129 }
3130 else
3131 {
3132 return error(GL_INVALID_VALUE);
3133 }
3134 }
3135
3136 switch(pname)
3137 {
3138 case GL_SHADER_TYPE:
3139 *params = shaderObject->getType();
3140 return;
3141 case GL_DELETE_STATUS:
3142 *params = shaderObject->isFlaggedForDeletion();
3143 return;
3144 case GL_COMPILE_STATUS:
3145 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3146 return;
3147 case GL_INFO_LOG_LENGTH:
3148 *params = (GLint)shaderObject->getInfoLogLength();
3149 return;
3150 case GL_SHADER_SOURCE_LENGTH:
3151 *params = (GLint)shaderObject->getSourceLength();
3152 return;
3153 default:
3154 return error(GL_INVALID_ENUM);
3155 }
3156 }
3157}
3158
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003159void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003160{
3161 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3162 shader, bufsize, length, infolog);
3163
3164 if(bufsize < 0)
3165 {
3166 return error(GL_INVALID_VALUE);
3167 }
3168
Chris Forbes108f3e12018-08-30 19:41:59 -07003169 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003170
3171 if(context)
3172 {
3173 es2::Shader *shaderObject = context->getShader(shader);
3174
3175 if(!shaderObject)
3176 {
3177 if(context->getProgram(shader))
3178 {
3179 return error(GL_INVALID_OPERATION);
3180 }
3181 else
3182 {
3183 return error(GL_INVALID_VALUE);
3184 }
3185 }
3186
3187 shaderObject->getInfoLog(bufsize, length, infolog);
3188 }
3189}
3190
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003191void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003192{
3193 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3194 shadertype, precisiontype, range, precision);
3195
3196 switch(shadertype)
3197 {
3198 case GL_VERTEX_SHADER:
3199 case GL_FRAGMENT_SHADER:
3200 break;
3201 default:
3202 return error(GL_INVALID_ENUM);
3203 }
3204
3205 switch(precisiontype)
3206 {
3207 case GL_LOW_FLOAT:
3208 case GL_MEDIUM_FLOAT:
3209 case GL_HIGH_FLOAT:
3210 // IEEE 754 single-precision
3211 range[0] = 127;
3212 range[1] = 127;
3213 *precision = 23;
3214 break;
3215 case GL_LOW_INT:
3216 case GL_MEDIUM_INT:
3217 case GL_HIGH_INT:
3218 // Full integer precision is supported
3219 range[0] = 31;
3220 range[1] = 30;
3221 *precision = 0;
3222 break;
3223 default:
3224 return error(GL_INVALID_ENUM);
3225 }
3226}
3227
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003228void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003229{
3230 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3231 shader, bufsize, length, source);
3232
3233 if(bufsize < 0)
3234 {
3235 return error(GL_INVALID_VALUE);
3236 }
3237
Chris Forbes108f3e12018-08-30 19:41:59 -07003238 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003239
3240 if(context)
3241 {
3242 es2::Shader *shaderObject = context->getShader(shader);
3243
3244 if(!shaderObject)
3245 {
3246 if(context->getProgram(shader))
3247 {
3248 return error(GL_INVALID_OPERATION);
3249 }
3250 else
3251 {
3252 return error(GL_INVALID_VALUE);
3253 }
3254 }
3255
3256 shaderObject->getSource(bufsize, length, source);
3257 }
3258}
3259
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003260const GLubyte* GL_APIENTRY GetString(GLenum name)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003261{
3262 TRACE("(GLenum name = 0x%X)", name);
3263
3264 switch(name)
3265 {
3266 case GL_VENDOR:
3267 return (GLubyte*)"Google Inc.";
3268 case GL_RENDERER:
3269 return (GLubyte*)"Google SwiftShader";
3270 case GL_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003271 return (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003272 case GL_SHADING_LANGUAGE_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003273 return (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003274 case GL_EXTENSIONS:
Nicolas Capens894858a2018-03-22 00:55:23 -04003275 {
Chris Forbes108f3e12018-08-30 19:41:59 -07003276 auto context = es2::getContext();
Nicolas Capens894858a2018-03-22 00:55:23 -04003277 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3278 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003279 default:
3280 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3281 }
3282}
3283
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003284void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003285{
3286 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3287
Chris Forbes108f3e12018-08-30 19:41:59 -07003288 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003289
3290 if(context)
3291 {
Nicolas Capens24cb99d2019-03-18 12:42:22 -04003292 es2::Texture *texture = context->getTargetTexture(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003293
Nicolas Capens24cb99d2019-03-18 12:42:22 -04003294 if(!texture)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003295 {
Nicolas Capens24cb99d2019-03-18 12:42:22 -04003296 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003297 }
3298
3299 switch(pname)
3300 {
3301 case GL_TEXTURE_MAG_FILTER:
3302 *params = (GLfloat)texture->getMagFilter();
3303 break;
3304 case GL_TEXTURE_MIN_FILTER:
3305 *params = (GLfloat)texture->getMinFilter();
3306 break;
3307 case GL_TEXTURE_WRAP_S:
3308 *params = (GLfloat)texture->getWrapS();
3309 break;
3310 case GL_TEXTURE_WRAP_T:
3311 *params = (GLfloat)texture->getWrapT();
3312 break;
3313 case GL_TEXTURE_WRAP_R_OES:
3314 *params = (GLfloat)texture->getWrapR();
3315 break;
3316 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3317 *params = texture->getMaxAnisotropy();
3318 break;
3319 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3320 *params = (GLfloat)1;
3321 break;
3322 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003323 *params = (GLfloat)texture->getBaseLevel();
3324 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003325 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003326 *params = (GLfloat)texture->getCompareFunc();
3327 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003328 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003329 *params = (GLfloat)texture->getCompareMode();
3330 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003331 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003332 *params = (GLfloat)texture->getImmutableFormat();
3333 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003334 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003335 *params = (GLfloat)texture->getImmutableLevels();
3336 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003337 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003338 *params = (GLfloat)texture->getMaxLevel();
3339 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003340 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003341 *params = texture->getMaxLOD();
3342 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003343 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003344 *params = texture->getMinLOD();
3345 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003346 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003347 *params = (GLfloat)texture->getSwizzleR();
3348 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003349 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003350 *params = (GLfloat)texture->getSwizzleG();
3351 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003352 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003353 *params = (GLfloat)texture->getSwizzleB();
3354 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003355 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003356 *params = (GLfloat)texture->getSwizzleA();
3357 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003358 default:
3359 return error(GL_INVALID_ENUM);
3360 }
3361 }
3362}
3363
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003364void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003365{
3366 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3367
Chris Forbes108f3e12018-08-30 19:41:59 -07003368 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003369
3370 if(context)
3371 {
Nicolas Capens24cb99d2019-03-18 12:42:22 -04003372 es2::Texture *texture = context->getTargetTexture(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003373
Nicolas Capens24cb99d2019-03-18 12:42:22 -04003374 if(!texture)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003375 {
Nicolas Capens24cb99d2019-03-18 12:42:22 -04003376 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003377 }
3378
3379 switch(pname)
3380 {
3381 case GL_TEXTURE_MAG_FILTER:
3382 *params = texture->getMagFilter();
3383 break;
3384 case GL_TEXTURE_MIN_FILTER:
3385 *params = texture->getMinFilter();
3386 break;
3387 case GL_TEXTURE_WRAP_S:
3388 *params = texture->getWrapS();
3389 break;
3390 case GL_TEXTURE_WRAP_T:
3391 *params = texture->getWrapT();
3392 break;
3393 case GL_TEXTURE_WRAP_R_OES:
3394 *params = texture->getWrapR();
3395 break;
3396 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3397 *params = (GLint)texture->getMaxAnisotropy();
3398 break;
3399 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3400 *params = 1;
3401 break;
3402 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003403 *params = texture->getBaseLevel();
3404 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003405 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003406 *params = (GLint)texture->getCompareFunc();
3407 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003408 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003409 *params = (GLint)texture->getCompareMode();
3410 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003411 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003412 *params = (GLint)texture->getImmutableFormat();
3413 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003414 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003415 *params = (GLint)texture->getImmutableLevels();
3416 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003417 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003418 *params = texture->getMaxLevel();
3419 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003420 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003421 *params = (GLint)roundf(texture->getMaxLOD());
3422 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003423 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003424 *params = (GLint)roundf(texture->getMinLOD());
3425 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003426 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003427 *params = (GLint)texture->getSwizzleR();
3428 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003429 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003430 *params = (GLint)texture->getSwizzleG();
3431 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003432 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003433 *params = (GLint)texture->getSwizzleB();
3434 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003435 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003436 *params = (GLint)texture->getSwizzleA();
3437 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003438 default:
3439 return error(GL_INVALID_ENUM);
3440 }
3441 }
3442}
3443
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003444void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003445{
3446 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3447 program, location, bufSize, params);
3448
3449 if(bufSize < 0)
3450 {
3451 return error(GL_INVALID_VALUE);
3452 }
3453
Chris Forbes108f3e12018-08-30 19:41:59 -07003454 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003455
3456 if(context)
3457 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003458 es2::Program *programObject = context->getProgram(program);
3459
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003460 if(!programObject)
3461 {
3462 if(context->getShader(program))
3463 {
3464 return error(GL_INVALID_OPERATION);
3465 }
3466 else
3467 {
3468 return error(GL_INVALID_VALUE);
3469 }
3470 }
3471
3472 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003473 {
3474 return error(GL_INVALID_OPERATION);
3475 }
3476
3477 if(!programObject->getUniformfv(location, &bufSize, params))
3478 {
3479 return error(GL_INVALID_OPERATION);
3480 }
3481 }
3482}
3483
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003484void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003485{
3486 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3487
Chris Forbes108f3e12018-08-30 19:41:59 -07003488 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003489
3490 if(context)
3491 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003492 es2::Program *programObject = context->getProgram(program);
3493
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003494 if(!programObject)
3495 {
3496 if(context->getShader(program))
3497 {
3498 return error(GL_INVALID_OPERATION);
3499 }
3500 else
3501 {
3502 return error(GL_INVALID_VALUE);
3503 }
3504 }
3505
3506 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003507 {
3508 return error(GL_INVALID_OPERATION);
3509 }
3510
3511 if(!programObject->getUniformfv(location, nullptr, params))
3512 {
3513 return error(GL_INVALID_OPERATION);
3514 }
3515 }
3516}
3517
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003518void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003519{
3520 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3521 program, location, bufSize, params);
3522
3523 if(bufSize < 0)
3524 {
3525 return error(GL_INVALID_VALUE);
3526 }
3527
Chris Forbes108f3e12018-08-30 19:41:59 -07003528 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003529
3530 if(context)
3531 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003532 es2::Program *programObject = context->getProgram(program);
3533
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003534 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003535 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003536 if(context->getShader(program))
3537 {
3538 return error(GL_INVALID_OPERATION);
3539 }
3540 else
3541 {
3542 return error(GL_INVALID_VALUE);
3543 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003544 }
3545
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003546 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003547 {
3548 return error(GL_INVALID_OPERATION);
3549 }
3550
3551 if(!programObject->getUniformiv(location, &bufSize, params))
3552 {
3553 return error(GL_INVALID_OPERATION);
3554 }
3555 }
3556}
3557
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003558void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003559{
3560 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3561
Chris Forbes108f3e12018-08-30 19:41:59 -07003562 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003563
3564 if(context)
3565 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003566 es2::Program *programObject = context->getProgram(program);
3567
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003568 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003569 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003570 if(context->getShader(program))
3571 {
3572 return error(GL_INVALID_OPERATION);
3573 }
3574 else
3575 {
3576 return error(GL_INVALID_VALUE);
3577 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003578 }
3579
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003580 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003581 {
3582 return error(GL_INVALID_OPERATION);
3583 }
3584
3585 if(!programObject->getUniformiv(location, nullptr, params))
3586 {
3587 return error(GL_INVALID_OPERATION);
3588 }
3589 }
3590}
3591
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003592int GL_APIENTRY GetUniformLocation(GLuint program, const GLchar* name)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003593{
3594 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3595
Chris Forbes108f3e12018-08-30 19:41:59 -07003596 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003597
3598 if(strstr(name, "gl_") == name)
3599 {
3600 return -1;
3601 }
3602
3603 if(context)
3604 {
3605 es2::Program *programObject = context->getProgram(program);
3606
3607 if(!programObject)
3608 {
3609 if(context->getShader(program))
3610 {
3611 return error(GL_INVALID_OPERATION, -1);
3612 }
3613 else
3614 {
3615 return error(GL_INVALID_VALUE, -1);
3616 }
3617 }
3618
3619 if(!programObject->isLinked())
3620 {
3621 return error(GL_INVALID_OPERATION, -1);
3622 }
3623
3624 return programObject->getUniformLocation(name);
3625 }
3626
3627 return -1;
3628}
3629
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003630void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003631{
3632 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
3633
Chris Forbes108f3e12018-08-30 19:41:59 -07003634 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003635
3636 if(context)
3637 {
3638 if(index >= es2::MAX_VERTEX_ATTRIBS)
3639 {
3640 return error(GL_INVALID_VALUE);
3641 }
3642
3643 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3644
Nicolas Capens0bac2852016-05-07 06:09:58 -04003645 switch(pname)
3646 {
3647 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3648 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3649 break;
3650 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3651 *params = (GLfloat)attribState.mSize;
3652 break;
3653 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3654 *params = (GLfloat)attribState.mStride;
3655 break;
3656 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3657 *params = (GLfloat)attribState.mType;
3658 break;
3659 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3660 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
3661 break;
3662 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3663 *params = (GLfloat)attribState.mBoundBuffer.name();
3664 break;
3665 case GL_CURRENT_VERTEX_ATTRIB:
3666 {
3667 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3668 for(int i = 0; i < 4; ++i)
3669 {
3670 params[i] = attrib.getCurrentValueF(i);
3671 }
3672 }
3673 break;
3674 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003675 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3676 break;
3677 default:
3678 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003679 }
3680 }
3681}
3682
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003683void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003684{
3685 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
3686
Chris Forbes108f3e12018-08-30 19:41:59 -07003687 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003688
3689 if(context)
3690 {
3691 if(index >= es2::MAX_VERTEX_ATTRIBS)
3692 {
3693 return error(GL_INVALID_VALUE);
3694 }
3695
3696 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3697
Nicolas Capens0bac2852016-05-07 06:09:58 -04003698 switch(pname)
3699 {
3700 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3701 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3702 break;
3703 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3704 *params = attribState.mSize;
3705 break;
3706 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3707 *params = attribState.mStride;
3708 break;
3709 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3710 *params = attribState.mType;
3711 break;
3712 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3713 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
3714 break;
3715 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3716 *params = attribState.mBoundBuffer.name();
3717 break;
3718 case GL_CURRENT_VERTEX_ATTRIB:
3719 {
3720 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3721 for(int i = 0; i < 4; ++i)
3722 {
3723 float currentValue = attrib.getCurrentValueF(i);
3724 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
3725 }
3726 }
3727 break;
3728 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003729 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3730 break;
3731 default:
3732 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003733 }
3734 }
3735}
3736
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003737void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003738{
3739 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
3740
Chris Forbes108f3e12018-08-30 19:41:59 -07003741 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003742
3743 if(context)
3744 {
3745 if(index >= es2::MAX_VERTEX_ATTRIBS)
3746 {
3747 return error(GL_INVALID_VALUE);
3748 }
3749
3750 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
3751 {
3752 return error(GL_INVALID_ENUM);
3753 }
3754
3755 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
3756 }
3757}
3758
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003759void GL_APIENTRY Hint(GLenum target, GLenum mode)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003760{
3761 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
3762
3763 switch(mode)
3764 {
3765 case GL_FASTEST:
3766 case GL_NICEST:
3767 case GL_DONT_CARE:
3768 break;
3769 default:
3770 return error(GL_INVALID_ENUM);
3771 }
3772
Chris Forbes108f3e12018-08-30 19:41:59 -07003773 auto context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003774
3775 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003776 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003777 switch(target)
3778 {
3779 case GL_GENERATE_MIPMAP_HINT:
3780 context->setGenerateMipmapHint(mode);
3781 break;
3782 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
3783 context->setFragmentShaderDerivativeHint(mode);
3784 break;
3785 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
3786 context->setTextureFilteringHint(mode);
3787 break;
3788 default:
3789 return error(GL_INVALID_ENUM);
3790 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003791 }
3792}
3793
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003794GLboolean GL_APIENTRY IsBuffer(GLuint buffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003795{
3796 TRACE("(GLuint buffer = %d)", buffer);
3797
Chris Forbes108f3e12018-08-30 19:41:59 -07003798 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003799
3800 if(context && buffer)
3801 {
3802 es2::Buffer *bufferObject = context->getBuffer(buffer);
3803
3804 if(bufferObject)
3805 {
3806 return GL_TRUE;
3807 }
3808 }
3809
3810 return GL_FALSE;
3811}
3812
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003813GLboolean GL_APIENTRY IsEnabled(GLenum cap)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003814{
3815 TRACE("(GLenum cap = 0x%X)", cap);
3816
Chris Forbes108f3e12018-08-30 19:41:59 -07003817 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003818
3819 if(context)
3820 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003821 switch(cap)
3822 {
3823 case GL_CULL_FACE: return context->isCullFaceEnabled();
3824 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
3825 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
3826 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
3827 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
3828 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
3829 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
3830 case GL_BLEND: return context->isBlendEnabled();
3831 case GL_DITHER: return context->isDitherEnabled();
Nicolas Capens83463112018-06-12 23:55:16 -04003832 case GL_PRIMITIVE_RESTART_FIXED_INDEX: return context->isPrimitiveRestartFixedIndexEnabled();
3833 case GL_RASTERIZER_DISCARD: return context->isRasterizerDiscardEnabled();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003834 default:
3835 return error(GL_INVALID_ENUM, false);
3836 }
3837 }
3838
3839 return false;
3840}
3841
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003842GLboolean GL_APIENTRY IsFenceNV(GLuint fence)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003843{
3844 TRACE("(GLuint fence = %d)", fence);
3845
Chris Forbes108f3e12018-08-30 19:41:59 -07003846 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003847
3848 if(context)
3849 {
3850 es2::Fence *fenceObject = context->getFence(fence);
3851
3852 if(!fenceObject)
3853 {
3854 return GL_FALSE;
3855 }
3856
3857 return fenceObject->isFence();
3858 }
3859
3860 return GL_FALSE;
3861}
3862
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003863GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003864{
3865 TRACE("(GLuint framebuffer = %d)", framebuffer);
3866
Chris Forbes108f3e12018-08-30 19:41:59 -07003867 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003868
3869 if(context && framebuffer)
3870 {
3871 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
3872
3873 if(framebufferObject)
3874 {
3875 return GL_TRUE;
3876 }
3877 }
3878
3879 return GL_FALSE;
3880}
3881
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003882GLboolean GL_APIENTRY IsProgram(GLuint program)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003883{
3884 TRACE("(GLuint program = %d)", program);
3885
Chris Forbes108f3e12018-08-30 19:41:59 -07003886 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003887
3888 if(context && program)
3889 {
3890 es2::Program *programObject = context->getProgram(program);
3891
3892 if(programObject)
3893 {
3894 return GL_TRUE;
3895 }
3896 }
3897
3898 return GL_FALSE;
3899}
3900
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003901GLboolean GL_APIENTRY IsQueryEXT(GLuint name)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003902{
3903 TRACE("(GLuint name = %d)", name);
3904
3905 if(name == 0)
3906 {
3907 return GL_FALSE;
3908 }
3909
Chris Forbes108f3e12018-08-30 19:41:59 -07003910 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003911
3912 if(context)
3913 {
3914 es2::Query *queryObject = context->getQuery(name);
3915
3916 if(queryObject)
3917 {
3918 return GL_TRUE;
3919 }
3920 }
3921
3922 return GL_FALSE;
3923}
3924
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003925GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003926{
3927 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
3928
Chris Forbes108f3e12018-08-30 19:41:59 -07003929 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003930
3931 if(context && renderbuffer)
3932 {
3933 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
3934
3935 if(renderbufferObject)
3936 {
3937 return GL_TRUE;
3938 }
3939 }
3940
3941 return GL_FALSE;
3942}
3943
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003944GLboolean GL_APIENTRY IsShader(GLuint shader)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003945{
3946 TRACE("(GLuint shader = %d)", shader);
3947
Chris Forbes108f3e12018-08-30 19:41:59 -07003948 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003949
3950 if(context && shader)
3951 {
3952 es2::Shader *shaderObject = context->getShader(shader);
3953
3954 if(shaderObject)
3955 {
3956 return GL_TRUE;
3957 }
3958 }
3959
3960 return GL_FALSE;
3961}
3962
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003963GLboolean GL_APIENTRY IsTexture(GLuint texture)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003964{
3965 TRACE("(GLuint texture = %d)", texture);
3966
Chris Forbes108f3e12018-08-30 19:41:59 -07003967 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003968
3969 if(context && texture)
3970 {
3971 es2::Texture *textureObject = context->getTexture(texture);
3972
3973 if(textureObject)
3974 {
3975 return GL_TRUE;
3976 }
3977 }
3978
3979 return GL_FALSE;
3980}
3981
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003982void GL_APIENTRY LineWidth(GLfloat width)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003983{
3984 TRACE("(GLfloat width = %f)", width);
3985
3986 if(width <= 0.0f)
3987 {
3988 return error(GL_INVALID_VALUE);
3989 }
3990
Chris Forbes108f3e12018-08-30 19:41:59 -07003991 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003992
3993 if(context)
3994 {
3995 context->setLineWidth(width);
3996 }
3997}
3998
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04003999void GL_APIENTRY LinkProgram(GLuint program)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004000{
4001 TRACE("(GLuint program = %d)", program);
4002
Chris Forbes108f3e12018-08-30 19:41:59 -07004003 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004004
4005 if(context)
4006 {
4007 es2::Program *programObject = context->getProgram(program);
4008
4009 if(!programObject)
4010 {
4011 if(context->getShader(program))
4012 {
4013 return error(GL_INVALID_OPERATION);
4014 }
4015 else
4016 {
4017 return error(GL_INVALID_VALUE);
4018 }
4019 }
4020
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004021 if(programObject == context->getCurrentProgram())
4022 {
4023 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4024 if(transformFeedback && transformFeedback->isActive())
4025 {
4026 return error(GL_INVALID_OPERATION);
4027 }
4028 }
4029
Nicolas Capens0bac2852016-05-07 06:09:58 -04004030 programObject->link();
4031 }
4032}
4033
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004034void GL_APIENTRY PixelStorei(GLenum pname, GLint param)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004035{
4036 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4037
Chris Forbes108f3e12018-08-30 19:41:59 -07004038 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004039
4040 if(context)
4041 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004042 switch(pname)
4043 {
4044 case GL_UNPACK_ALIGNMENT:
4045 if(param != 1 && param != 2 && param != 4 && param != 8)
4046 {
4047 return error(GL_INVALID_VALUE);
4048 }
4049 context->setUnpackAlignment(param);
4050 break;
4051 case GL_PACK_ALIGNMENT:
4052 if(param != 1 && param != 2 && param != 4 && param != 8)
4053 {
4054 return error(GL_INVALID_VALUE);
4055 }
4056 context->setPackAlignment(param);
4057 break;
4058 case GL_PACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004059 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004060 {
Nicolas Capens83463112018-06-12 23:55:16 -04004061 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004062 }
Nicolas Capens83463112018-06-12 23:55:16 -04004063 context->setPackRowLength(param);
4064 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004065 case GL_PACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004066 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004067 {
Nicolas Capens83463112018-06-12 23:55:16 -04004068 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004069 }
Nicolas Capens83463112018-06-12 23:55:16 -04004070 context->setPackSkipPixels(param);
4071 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004072 case GL_PACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004073 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004074 {
Nicolas Capens83463112018-06-12 23:55:16 -04004075 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004076 }
Nicolas Capens83463112018-06-12 23:55:16 -04004077 context->setPackSkipRows(param);
4078 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004079 case GL_UNPACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004080 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004081 {
Nicolas Capens83463112018-06-12 23:55:16 -04004082 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004083 }
Nicolas Capens83463112018-06-12 23:55:16 -04004084 context->setUnpackRowLength(param);
4085 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004086 case GL_UNPACK_IMAGE_HEIGHT:
Nicolas Capens83463112018-06-12 23:55:16 -04004087 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004088 {
Nicolas Capens83463112018-06-12 23:55:16 -04004089 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004090 }
Nicolas Capens83463112018-06-12 23:55:16 -04004091 context->setUnpackImageHeight(param);
4092 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004093 case GL_UNPACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004094 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004095 {
Nicolas Capens83463112018-06-12 23:55:16 -04004096 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004097 }
Nicolas Capens83463112018-06-12 23:55:16 -04004098 context->setUnpackSkipPixels(param);
4099 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004100 case GL_UNPACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004101 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004102 {
Nicolas Capens83463112018-06-12 23:55:16 -04004103 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004104 }
Nicolas Capens83463112018-06-12 23:55:16 -04004105 context->setUnpackSkipRows(param);
4106 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004107 case GL_UNPACK_SKIP_IMAGES:
Nicolas Capens83463112018-06-12 23:55:16 -04004108 if(param < 0)
4109 {
4110 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004111 }
Nicolas Capens83463112018-06-12 23:55:16 -04004112 context->setUnpackSkipImages(param);
4113 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004114 default:
4115 return error(GL_INVALID_ENUM);
4116 }
4117 }
4118}
4119
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004120void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004121{
4122 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4123
Chris Forbes108f3e12018-08-30 19:41:59 -07004124 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004125
4126 if(context)
4127 {
4128 context->setPolygonOffsetParams(factor, units);
4129 }
4130}
4131
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004132void GL_APIENTRY ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4133 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004134{
4135 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4136 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4137 x, y, width, height, format, type, bufSize, data);
4138
4139 if(width < 0 || height < 0 || bufSize < 0)
4140 {
4141 return error(GL_INVALID_VALUE);
4142 }
4143
Chris Forbes108f3e12018-08-30 19:41:59 -07004144 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004145
4146 if(context)
4147 {
4148 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4149 }
4150}
4151
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004152void GL_APIENTRY ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004153{
4154 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4155 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4156 x, y, width, height, format, type, pixels);
4157
4158 if(width < 0 || height < 0)
4159 {
4160 return error(GL_INVALID_VALUE);
4161 }
4162
Chris Forbes108f3e12018-08-30 19:41:59 -07004163 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004164
4165 if(context)
4166 {
4167 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4168 }
4169}
4170
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004171void GL_APIENTRY ReleaseShaderCompiler(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004172{
4173 TRACE("()");
4174
4175 es2::Shader::releaseCompiler();
4176}
4177
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004178void GL_APIENTRY RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004179{
4180 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4181 target, samples, internalformat, width, height);
4182
4183 switch(target)
4184 {
4185 case GL_RENDERBUFFER:
4186 break;
4187 default:
4188 return error(GL_INVALID_ENUM);
4189 }
4190
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004191 if(width < 0 || height < 0 || samples < 0 ||
4192 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4193 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004194 {
4195 return error(GL_INVALID_VALUE);
4196 }
4197
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004198 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004199 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004200 {
4201 return error(GL_INVALID_OPERATION);
4202 }
4203
Chris Forbes108f3e12018-08-30 19:41:59 -07004204 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004205
4206 if(context)
4207 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004208 GLuint handle = context->getRenderbufferName();
4209 if(handle == 0)
4210 {
4211 return error(GL_INVALID_OPERATION);
4212 }
4213
Nicolas Capens83463112018-06-12 23:55:16 -04004214 if(IsColorRenderable(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004215 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004216 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004217 }
Nicolas Capens83463112018-06-12 23:55:16 -04004218 else if(IsDepthRenderable(internalformat) && IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004219 {
4220 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4221 }
Nicolas Capens83463112018-06-12 23:55:16 -04004222 else if(IsDepthRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004223 {
4224 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4225 }
Nicolas Capens83463112018-06-12 23:55:16 -04004226 else if(IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004227 {
4228 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4229 }
4230 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004231 }
4232}
4233
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004234void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens400667e2017-03-29 14:40:14 -04004235{
4236 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4237}
4238
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004239void GL_APIENTRY RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004240{
Nicolas Capens400667e2017-03-29 14:40:14 -04004241 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004242}
4243
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004244void GL_APIENTRY SampleCoverage(GLclampf value, GLboolean invert)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004245{
4246 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4247
Chris Forbes108f3e12018-08-30 19:41:59 -07004248 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004249
4250 if(context)
4251 {
Nicolas Capens51814272018-10-15 13:01:22 -04004252 context->setSampleCoverageParams(es2::clamp01(value), invert != GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004253 }
4254}
4255
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004256void GL_APIENTRY SetFenceNV(GLuint fence, GLenum condition)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004257{
4258 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4259
4260 if(condition != GL_ALL_COMPLETED_NV)
4261 {
4262 return error(GL_INVALID_ENUM);
4263 }
4264
Chris Forbes108f3e12018-08-30 19:41:59 -07004265 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004266
4267 if(context)
4268 {
4269 es2::Fence *fenceObject = context->getFence(fence);
4270
4271 if(!fenceObject)
4272 {
4273 return error(GL_INVALID_OPERATION);
4274 }
4275
4276 fenceObject->setFence(condition);
4277 }
4278}
4279
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004280void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004281{
4282 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4283
4284 if(width < 0 || height < 0)
4285 {
4286 return error(GL_INVALID_VALUE);
4287 }
4288
Chris Forbes108f3e12018-08-30 19:41:59 -07004289 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004290
4291 if(context)
4292 {
4293 context->setScissorParams(x, y, width, height);
4294 }
4295}
4296
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004297void GL_APIENTRY ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004298{
4299 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4300 "const GLvoid* binary = %p, GLsizei length = %d)",
4301 n, shaders, binaryformat, binary, length);
4302
4303 // No binary shader formats are supported.
4304 return error(GL_INVALID_ENUM);
4305}
4306
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004307void GL_APIENTRY ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004308{
4309 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4310 shader, count, string, length);
4311
4312 if(count < 0)
4313 {
4314 return error(GL_INVALID_VALUE);
4315 }
4316
Chris Forbes108f3e12018-08-30 19:41:59 -07004317 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004318
4319 if(context)
4320 {
4321 es2::Shader *shaderObject = context->getShader(shader);
4322
4323 if(!shaderObject)
4324 {
4325 if(context->getProgram(shader))
4326 {
4327 return error(GL_INVALID_OPERATION);
4328 }
4329 else
4330 {
4331 return error(GL_INVALID_VALUE);
4332 }
4333 }
4334
4335 shaderObject->setSource(count, string, length);
4336 }
4337}
4338
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004339void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004340{
4341 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4342
4343 switch(face)
4344 {
4345 case GL_FRONT:
4346 case GL_BACK:
4347 case GL_FRONT_AND_BACK:
4348 break;
4349 default:
4350 return error(GL_INVALID_ENUM);
4351 }
4352
4353 switch(func)
4354 {
4355 case GL_NEVER:
4356 case GL_ALWAYS:
4357 case GL_LESS:
4358 case GL_LEQUAL:
4359 case GL_EQUAL:
4360 case GL_GEQUAL:
4361 case GL_GREATER:
4362 case GL_NOTEQUAL:
4363 break;
4364 default:
4365 return error(GL_INVALID_ENUM);
4366 }
4367
Chris Forbes108f3e12018-08-30 19:41:59 -07004368 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004369
4370 if(context)
4371 {
4372 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4373 {
4374 context->setStencilParams(func, ref, mask);
4375 }
4376
4377 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4378 {
4379 context->setStencilBackParams(func, ref, mask);
4380 }
4381 }
4382}
4383
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004384void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004385{
Nicolas Capens805d7612018-08-02 13:56:32 -04004386 StencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004387}
4388
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004389void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004390{
4391 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4392
4393 switch(face)
4394 {
4395 case GL_FRONT:
4396 case GL_BACK:
4397 case GL_FRONT_AND_BACK:
4398 break;
4399 default:
4400 return error(GL_INVALID_ENUM);
4401 }
4402
Chris Forbes108f3e12018-08-30 19:41:59 -07004403 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004404
4405 if(context)
4406 {
4407 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4408 {
4409 context->setStencilWritemask(mask);
4410 }
4411
4412 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4413 {
4414 context->setStencilBackWritemask(mask);
4415 }
4416 }
4417}
4418
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004419void GL_APIENTRY StencilMask(GLuint mask)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004420{
Nicolas Capens805d7612018-08-02 13:56:32 -04004421 StencilMaskSeparate(GL_FRONT_AND_BACK, mask);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004422}
4423
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004424void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004425{
4426 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4427 face, fail, zfail, zpass);
4428
4429 switch(face)
4430 {
4431 case GL_FRONT:
4432 case GL_BACK:
4433 case GL_FRONT_AND_BACK:
4434 break;
4435 default:
4436 return error(GL_INVALID_ENUM);
4437 }
4438
4439 switch(fail)
4440 {
4441 case GL_ZERO:
4442 case GL_KEEP:
4443 case GL_REPLACE:
4444 case GL_INCR:
4445 case GL_DECR:
4446 case GL_INVERT:
4447 case GL_INCR_WRAP:
4448 case GL_DECR_WRAP:
4449 break;
4450 default:
4451 return error(GL_INVALID_ENUM);
4452 }
4453
4454 switch(zfail)
4455 {
4456 case GL_ZERO:
4457 case GL_KEEP:
4458 case GL_REPLACE:
4459 case GL_INCR:
4460 case GL_DECR:
4461 case GL_INVERT:
4462 case GL_INCR_WRAP:
4463 case GL_DECR_WRAP:
4464 break;
4465 default:
4466 return error(GL_INVALID_ENUM);
4467 }
4468
4469 switch(zpass)
4470 {
4471 case GL_ZERO:
4472 case GL_KEEP:
4473 case GL_REPLACE:
4474 case GL_INCR:
4475 case GL_DECR:
4476 case GL_INVERT:
4477 case GL_INCR_WRAP:
4478 case GL_DECR_WRAP:
4479 break;
4480 default:
4481 return error(GL_INVALID_ENUM);
4482 }
4483
Chris Forbes108f3e12018-08-30 19:41:59 -07004484 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004485
4486 if(context)
4487 {
4488 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4489 {
4490 context->setStencilOperations(fail, zfail, zpass);
4491 }
4492
4493 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4494 {
4495 context->setStencilBackOperations(fail, zfail, zpass);
4496 }
4497 }
4498}
4499
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004500void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
Nicolas Capens805d7612018-08-02 13:56:32 -04004501{
4502 StencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4503}
4504
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004505GLboolean GL_APIENTRY TestFenceNV(GLuint fence)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004506{
4507 TRACE("(GLuint fence = %d)", fence);
4508
Chris Forbes108f3e12018-08-30 19:41:59 -07004509 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004510
4511 if(context)
4512 {
4513 es2::Fence *fenceObject = context->getFence(fence);
4514
4515 if(!fenceObject)
4516 {
4517 return error(GL_INVALID_OPERATION, GL_TRUE);
4518 }
4519
4520 return fenceObject->testFence();
4521 }
4522
4523 return GL_TRUE;
4524}
4525
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004526void GL_APIENTRY TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
4527 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004528{
4529 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004530 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
4531 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004532
4533 if(!validImageSize(level, width, height))
4534 {
4535 return error(GL_INVALID_VALUE);
4536 }
4537
Chris Forbes108f3e12018-08-30 19:41:59 -07004538 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004539
4540 if(context)
4541 {
Nicolas Capens83463112018-06-12 23:55:16 -04004542 // GL_APPLE_texture_format_BGRA8888 allows (only) GL_BGRA_EXT / GL_RGBA, while
Nicolas Capensbc62c3b2018-02-27 16:45:43 -05004543 // GL_EXT_texture_format_BGRA8888 also allows GL_BGRA_EXT / GL_BGRA_EXT.
4544 if(format == GL_BGRA_EXT && internalformat == GL_RGBA)
4545 {
4546 internalformat = GL_BGRA_EXT;
4547 }
4548
Nicolas Capens83463112018-06-12 23:55:16 -04004549 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05004550 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004551 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004552 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004553 }
4554
4555 if(border != 0)
4556 {
4557 return error(GL_INVALID_VALUE);
4558 }
4559
4560 switch(target)
4561 {
Alexis Hetu46768622018-01-16 22:09:28 -05004562 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004563 if(level != 0)
4564 {
4565 return error(GL_INVALID_VALUE); // Defining level other than 0 is not allowed
4566 }
Nicolas Capens894858a2018-03-22 00:55:23 -04004567 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -05004568 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04004569 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4570 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4571 {
4572 return error(GL_INVALID_VALUE);
4573 }
4574 break;
4575 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4576 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4577 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4578 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4579 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4580 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4581 if(width != height)
4582 {
4583 return error(GL_INVALID_VALUE);
4584 }
4585
4586 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
4587 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
4588 {
4589 return error(GL_INVALID_VALUE);
4590 }
4591 break;
4592 default:
4593 return error(GL_INVALID_ENUM);
4594 }
4595
Nicolas Capens5555af42017-12-14 13:14:03 -05004596 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004597 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05004598 {
4599 return error(validationError);
4600 }
4601
Nicolas Capens894858a2018-03-22 00:55:23 -04004602 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
4603
Alexis Hetu46768622018-01-16 22:09:28 -05004604 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004605 {
Alexis Hetu46768622018-01-16 22:09:28 -05004606 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004607
4608 if(!texture)
4609 {
4610 return error(GL_INVALID_OPERATION);
4611 }
4612
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004613 texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004614 }
4615 else
4616 {
4617 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4618
4619 if(!texture)
4620 {
4621 return error(GL_INVALID_OPERATION);
4622 }
4623
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004624 texture->setImage(target, level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004625 }
4626 }
4627}
4628
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004629void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004630{
4631 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
4632
Chris Forbes108f3e12018-08-30 19:41:59 -07004633 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004634
4635 if(context)
4636 {
Nicolas Capens24cb99d2019-03-18 12:42:22 -04004637 es2::Texture *texture = context->getTargetTexture(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004638
Nicolas Capens24cb99d2019-03-18 12:42:22 -04004639 if(!texture)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004640 {
Nicolas Capens24cb99d2019-03-18 12:42:22 -04004641 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004642 }
4643
4644 switch(pname)
4645 {
4646 case GL_TEXTURE_WRAP_S:
4647 if(!texture->setWrapS((GLenum)param))
4648 {
4649 return error(GL_INVALID_ENUM);
4650 }
4651 break;
4652 case GL_TEXTURE_WRAP_T:
4653 if(!texture->setWrapT((GLenum)param))
4654 {
4655 return error(GL_INVALID_ENUM);
4656 }
4657 break;
4658 case GL_TEXTURE_WRAP_R_OES:
4659 if(!texture->setWrapR((GLenum)param))
4660 {
4661 return error(GL_INVALID_ENUM);
4662 }
4663 break;
4664 case GL_TEXTURE_MIN_FILTER:
4665 if(!texture->setMinFilter((GLenum)param))
4666 {
4667 return error(GL_INVALID_ENUM);
4668 }
4669 break;
4670 case GL_TEXTURE_MAG_FILTER:
4671 if(!texture->setMagFilter((GLenum)param))
4672 {
4673 return error(GL_INVALID_ENUM);
4674 }
4675 break;
4676 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4677 if(!texture->setMaxAnisotropy(param))
4678 {
4679 return error(GL_INVALID_VALUE);
4680 }
4681 break;
4682 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004683 if(!texture->setBaseLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004684 {
4685 return error(GL_INVALID_VALUE);
4686 }
4687 break;
4688 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004689 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004690 {
4691 return error(GL_INVALID_VALUE);
4692 }
4693 break;
4694 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004695 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004696 {
4697 return error(GL_INVALID_VALUE);
4698 }
4699 break;
4700 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004701 if(!texture->setMaxLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004702 {
4703 return error(GL_INVALID_VALUE);
4704 }
4705 break;
4706 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004707 if(!texture->setMaxLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004708 {
4709 return error(GL_INVALID_VALUE);
4710 }
4711 break;
4712 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004713 if(!texture->setMinLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004714 {
4715 return error(GL_INVALID_VALUE);
4716 }
4717 break;
4718 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004719 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004720 {
4721 return error(GL_INVALID_VALUE);
4722 }
4723 break;
4724 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004725 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004726 {
4727 return error(GL_INVALID_VALUE);
4728 }
4729 break;
4730 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004731 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004732 {
4733 return error(GL_INVALID_VALUE);
4734 }
4735 break;
4736 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004737 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004738 {
4739 return error(GL_INVALID_VALUE);
4740 }
4741 break;
4742 default:
4743 return error(GL_INVALID_ENUM);
4744 }
4745 }
4746}
4747
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004748void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004749{
Nicolas Capens805d7612018-08-02 13:56:32 -04004750 TexParameterf(target, pname, *params);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004751}
4752
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004753void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004754{
4755 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
4756
Chris Forbes108f3e12018-08-30 19:41:59 -07004757 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004758
4759 if(context)
4760 {
Nicolas Capens24cb99d2019-03-18 12:42:22 -04004761 es2::Texture *texture = context->getTargetTexture(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004762
Nicolas Capens24cb99d2019-03-18 12:42:22 -04004763 if(!texture)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004764 {
Nicolas Capens24cb99d2019-03-18 12:42:22 -04004765 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004766 }
4767
4768 switch(pname)
4769 {
4770 case GL_TEXTURE_WRAP_S:
4771 if(!texture->setWrapS((GLenum)param))
4772 {
4773 return error(GL_INVALID_ENUM);
4774 }
4775 break;
4776 case GL_TEXTURE_WRAP_T:
4777 if(!texture->setWrapT((GLenum)param))
4778 {
4779 return error(GL_INVALID_ENUM);
4780 }
4781 break;
4782 case GL_TEXTURE_WRAP_R_OES:
4783 if(!texture->setWrapR((GLenum)param))
4784 {
4785 return error(GL_INVALID_ENUM);
4786 }
4787 break;
4788 case GL_TEXTURE_MIN_FILTER:
4789 if(!texture->setMinFilter((GLenum)param))
4790 {
4791 return error(GL_INVALID_ENUM);
4792 }
4793 break;
4794 case GL_TEXTURE_MAG_FILTER:
4795 if(!texture->setMagFilter((GLenum)param))
4796 {
4797 return error(GL_INVALID_ENUM);
4798 }
4799 break;
4800 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4801 if(!texture->setMaxAnisotropy((GLfloat)param))
4802 {
4803 return error(GL_INVALID_VALUE);
4804 }
4805 break;
4806 case GL_TEXTURE_BASE_LEVEL:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004807 if((texture->getTarget() == GL_TEXTURE_RECTANGLE_ARB) && (param != 0))
4808 {
4809 return error(GL_INVALID_OPERATION); // Base level has to be 0
4810 }
Nicolas Capens83463112018-06-12 23:55:16 -04004811 if(!texture->setBaseLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004812 {
4813 return error(GL_INVALID_VALUE);
4814 }
4815 break;
4816 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004817 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004818 {
4819 return error(GL_INVALID_VALUE);
4820 }
4821 break;
4822 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004823 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004824 {
4825 return error(GL_INVALID_VALUE);
4826 }
4827 break;
4828 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004829 if(!texture->setMaxLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004830 {
4831 return error(GL_INVALID_VALUE);
4832 }
4833 break;
4834 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004835 if(!texture->setMaxLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004836 {
4837 return error(GL_INVALID_VALUE);
4838 }
4839 break;
4840 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004841 if(!texture->setMinLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004842 {
4843 return error(GL_INVALID_VALUE);
4844 }
4845 break;
4846 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004847 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004848 {
4849 return error(GL_INVALID_VALUE);
4850 }
4851 break;
4852 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004853 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004854 {
4855 return error(GL_INVALID_VALUE);
4856 }
4857 break;
4858 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004859 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004860 {
4861 return error(GL_INVALID_VALUE);
4862 }
4863 break;
4864 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004865 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004866 {
4867 return error(GL_INVALID_VALUE);
4868 }
4869 break;
4870 default:
4871 return error(GL_INVALID_ENUM);
4872 }
4873 }
4874}
4875
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004876void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004877{
Nicolas Capens805d7612018-08-02 13:56:32 -04004878 TexParameteri(target, pname, *params);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004879}
4880
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004881void GL_APIENTRY TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
4882 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004883{
4884 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
4885 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004886 "const GLvoid* data = %p)",
4887 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004888
Antonio Maioranod1fff582019-04-16 10:08:39 -04004889 if(!es2::IsTexImageTarget(target))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004890 {
4891 return error(GL_INVALID_ENUM);
4892 }
4893
4894 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4895 {
4896 return error(GL_INVALID_VALUE);
4897 }
4898
4899 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
4900 {
4901 return error(GL_INVALID_VALUE);
4902 }
4903
4904 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
4905 {
4906 return error(GL_INVALID_VALUE);
4907 }
4908
Chris Forbes108f3e12018-08-30 19:41:59 -07004909 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004910
4911 if(context)
4912 {
Alexis Hetu46768622018-01-16 22:09:28 -05004913 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004914 {
Alexis Hetu46768622018-01-16 22:09:28 -05004915 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004916
Nicolas Capens83463112018-06-12 23:55:16 -04004917 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004918 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004919 {
4920 return error(validationError);
4921 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004922
Nicolas Capens5555af42017-12-14 13:14:03 -05004923 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004924 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004925 {
4926 return error(validationError);
4927 }
4928
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004929 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004930 }
4931 else if(es2::IsCubemapTextureTarget(target))
4932 {
4933 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4934
Nicolas Capens83463112018-06-12 23:55:16 -04004935 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004936 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004937 {
4938 return error(validationError);
4939 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004940
Nicolas Capens5555af42017-12-14 13:14:03 -05004941 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004942 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004943 {
4944 return error(validationError);
4945 }
4946
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004947 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004948 }
4949 else UNREACHABLE(target);
4950 }
4951}
4952
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004953void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004954{
4955 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
4956
4957 if(count < 0)
4958 {
4959 return error(GL_INVALID_VALUE);
4960 }
4961
Chris Forbes108f3e12018-08-30 19:41:59 -07004962 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004963
4964 if(context)
4965 {
4966 es2::Program *program = context->getCurrentProgram();
4967
4968 if(!program)
4969 {
4970 return error(GL_INVALID_OPERATION);
4971 }
4972
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004973 if(location == -1)
4974 {
4975 return;
4976 }
4977
Nicolas Capens0bac2852016-05-07 06:09:58 -04004978 if(!program->setUniform1fv(location, count, v))
4979 {
4980 return error(GL_INVALID_OPERATION);
4981 }
4982 }
4983}
4984
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004985void GL_APIENTRY Uniform1f(GLint location, GLfloat x)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004986{
Nicolas Capens805d7612018-08-02 13:56:32 -04004987 Uniform1fv(location, 1, &x);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004988}
4989
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04004990void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint* v)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004991{
4992 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
4993
4994 if(count < 0)
4995 {
4996 return error(GL_INVALID_VALUE);
4997 }
4998
Chris Forbes108f3e12018-08-30 19:41:59 -07004999 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005000
5001 if(context)
5002 {
5003 es2::Program *program = context->getCurrentProgram();
5004
5005 if(!program)
5006 {
5007 return error(GL_INVALID_OPERATION);
5008 }
5009
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005010 if(location == -1)
5011 {
5012 return;
5013 }
5014
Nicolas Capens0bac2852016-05-07 06:09:58 -04005015 if(!program->setUniform1iv(location, count, v))
5016 {
5017 return error(GL_INVALID_OPERATION);
5018 }
5019 }
5020}
5021
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005022void GL_APIENTRY Uniform1i(GLint location, GLint x)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005023{
Nicolas Capens805d7612018-08-02 13:56:32 -04005024 Uniform1iv(location, 1, &x);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005025}
5026
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005027void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005028{
5029 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5030
5031 if(count < 0)
5032 {
5033 return error(GL_INVALID_VALUE);
5034 }
5035
Chris Forbes108f3e12018-08-30 19:41:59 -07005036 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005037
5038 if(context)
5039 {
5040 es2::Program *program = context->getCurrentProgram();
5041
5042 if(!program)
5043 {
5044 return error(GL_INVALID_OPERATION);
5045 }
5046
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005047 if(location == -1)
5048 {
5049 return;
5050 }
5051
Nicolas Capens0bac2852016-05-07 06:09:58 -04005052 if(!program->setUniform2fv(location, count, v))
5053 {
5054 return error(GL_INVALID_OPERATION);
5055 }
5056 }
5057}
5058
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005059void GL_APIENTRY Uniform2f(GLint location, GLfloat x, GLfloat y)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005060{
Nicolas Capens805d7612018-08-02 13:56:32 -04005061 GLfloat xy[2] = {x, y};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005062
Nicolas Capens805d7612018-08-02 13:56:32 -04005063 Uniform2fv(location, 1, (GLfloat*)&xy);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005064}
5065
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005066void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint* v)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005067{
5068 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5069
5070 if(count < 0)
5071 {
5072 return error(GL_INVALID_VALUE);
5073 }
5074
Chris Forbes108f3e12018-08-30 19:41:59 -07005075 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005076
5077 if(context)
5078 {
5079 es2::Program *program = context->getCurrentProgram();
5080
5081 if(!program)
5082 {
5083 return error(GL_INVALID_OPERATION);
5084 }
5085
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005086 if(location == -1)
5087 {
5088 return;
5089 }
5090
Nicolas Capens0bac2852016-05-07 06:09:58 -04005091 if(!program->setUniform2iv(location, count, v))
5092 {
5093 return error(GL_INVALID_OPERATION);
5094 }
5095 }
5096}
5097
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005098void GL_APIENTRY Uniform2i(GLint location, GLint x, GLint y)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005099{
Nicolas Capens805d7612018-08-02 13:56:32 -04005100 GLint xy[4] = {x, y};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005101
Nicolas Capens805d7612018-08-02 13:56:32 -04005102 Uniform2iv(location, 1, (GLint*)&xy);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005103}
5104
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005105void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005106{
5107 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5108
5109 if(count < 0)
5110 {
5111 return error(GL_INVALID_VALUE);
5112 }
5113
Chris Forbes108f3e12018-08-30 19:41:59 -07005114 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005115
5116 if(context)
5117 {
5118 es2::Program *program = context->getCurrentProgram();
5119
5120 if(!program)
5121 {
5122 return error(GL_INVALID_OPERATION);
5123 }
5124
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005125 if(location == -1)
5126 {
5127 return;
5128 }
5129
Nicolas Capens0bac2852016-05-07 06:09:58 -04005130 if(!program->setUniform3fv(location, count, v))
5131 {
5132 return error(GL_INVALID_OPERATION);
5133 }
5134 }
5135}
5136
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005137void GL_APIENTRY Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005138{
Nicolas Capens805d7612018-08-02 13:56:32 -04005139 GLfloat xyz[3] = {x, y, z};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005140
Nicolas Capens805d7612018-08-02 13:56:32 -04005141 Uniform3fv(location, 1, (GLfloat*)&xyz);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005142}
5143
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005144void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint* v)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005145{
5146 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5147
5148 if(count < 0)
5149 {
5150 return error(GL_INVALID_VALUE);
5151 }
5152
Chris Forbes108f3e12018-08-30 19:41:59 -07005153 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005154
5155 if(context)
5156 {
5157 es2::Program *program = context->getCurrentProgram();
5158
5159 if(!program)
5160 {
5161 return error(GL_INVALID_OPERATION);
5162 }
5163
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005164 if(location == -1)
5165 {
5166 return;
5167 }
5168
Nicolas Capens0bac2852016-05-07 06:09:58 -04005169 if(!program->setUniform3iv(location, count, v))
5170 {
5171 return error(GL_INVALID_OPERATION);
5172 }
5173 }
5174}
5175
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005176void GL_APIENTRY Uniform3i(GLint location, GLint x, GLint y, GLint z)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005177{
Nicolas Capens805d7612018-08-02 13:56:32 -04005178 GLint xyz[3] = {x, y, z};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005179
Nicolas Capens805d7612018-08-02 13:56:32 -04005180 Uniform3iv(location, 1, (GLint*)&xyz);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005181}
5182
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005183void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005184{
5185 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5186
5187 if(count < 0)
5188 {
5189 return error(GL_INVALID_VALUE);
5190 }
5191
Chris Forbes108f3e12018-08-30 19:41:59 -07005192 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005193
5194 if(context)
5195 {
5196 es2::Program *program = context->getCurrentProgram();
5197
5198 if(!program)
5199 {
5200 return error(GL_INVALID_OPERATION);
5201 }
5202
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005203 if(location == -1)
5204 {
5205 return;
5206 }
5207
Nicolas Capens0bac2852016-05-07 06:09:58 -04005208 if(!program->setUniform4fv(location, count, v))
5209 {
5210 return error(GL_INVALID_OPERATION);
5211 }
5212 }
5213}
5214
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005215void GL_APIENTRY Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005216{
Nicolas Capens805d7612018-08-02 13:56:32 -04005217 GLfloat xyzw[4] = {x, y, z, w};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005218
Nicolas Capens805d7612018-08-02 13:56:32 -04005219 Uniform4fv(location, 1, (GLfloat*)&xyzw);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005220}
5221
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005222void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint* v)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005223{
5224 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5225
5226 if(count < 0)
5227 {
5228 return error(GL_INVALID_VALUE);
5229 }
5230
Chris Forbes108f3e12018-08-30 19:41:59 -07005231 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005232
5233 if(context)
5234 {
5235 es2::Program *program = context->getCurrentProgram();
5236
5237 if(!program)
5238 {
5239 return error(GL_INVALID_OPERATION);
5240 }
5241
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005242 if(location == -1)
5243 {
5244 return;
5245 }
5246
Nicolas Capens0bac2852016-05-07 06:09:58 -04005247 if(!program->setUniform4iv(location, count, v))
5248 {
5249 return error(GL_INVALID_OPERATION);
5250 }
5251 }
5252}
5253
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005254void GL_APIENTRY Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
Nicolas Capens805d7612018-08-02 13:56:32 -04005255{
5256 GLint xyzw[4] = {x, y, z, w};
5257
5258 Uniform4iv(location, 1, (GLint*)&xyzw);
5259}
5260
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005261void GL_APIENTRY UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005262{
5263 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5264 location, count, transpose, value);
5265
5266 if(count < 0)
5267 {
5268 return error(GL_INVALID_VALUE);
5269 }
5270
Chris Forbes108f3e12018-08-30 19:41:59 -07005271 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005272
5273 if(context)
5274 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005275 es2::Program *program = context->getCurrentProgram();
5276
5277 if(!program)
5278 {
5279 return error(GL_INVALID_OPERATION);
5280 }
5281
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005282 if(location == -1)
5283 {
5284 return;
5285 }
5286
Nicolas Capens0bac2852016-05-07 06:09:58 -04005287 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5288 {
5289 return error(GL_INVALID_OPERATION);
5290 }
5291 }
5292}
5293
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005294void GL_APIENTRY UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005295{
5296 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5297 location, count, transpose, value);
5298
5299 if(count < 0)
5300 {
5301 return error(GL_INVALID_VALUE);
5302 }
5303
Chris Forbes108f3e12018-08-30 19:41:59 -07005304 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005305
5306 if(context)
5307 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005308 es2::Program *program = context->getCurrentProgram();
5309
5310 if(!program)
5311 {
5312 return error(GL_INVALID_OPERATION);
5313 }
5314
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005315 if(location == -1)
5316 {
5317 return;
5318 }
5319
Nicolas Capens0bac2852016-05-07 06:09:58 -04005320 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5321 {
5322 return error(GL_INVALID_OPERATION);
5323 }
5324 }
5325}
5326
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005327void GL_APIENTRY UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005328{
5329 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5330 location, count, transpose, value);
5331
5332 if(count < 0)
5333 {
5334 return error(GL_INVALID_VALUE);
5335 }
5336
Chris Forbes108f3e12018-08-30 19:41:59 -07005337 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005338
5339 if(context)
5340 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005341 es2::Program *program = context->getCurrentProgram();
5342
5343 if(!program)
5344 {
5345 return error(GL_INVALID_OPERATION);
5346 }
5347
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005348 if(location == -1)
5349 {
5350 return;
5351 }
5352
Nicolas Capens0bac2852016-05-07 06:09:58 -04005353 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5354 {
5355 return error(GL_INVALID_OPERATION);
5356 }
5357 }
5358}
5359
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005360void GL_APIENTRY UseProgram(GLuint program)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005361{
5362 TRACE("(GLuint program = %d)", program);
5363
Chris Forbes108f3e12018-08-30 19:41:59 -07005364 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005365
5366 if(context)
5367 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005368 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5369 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5370 {
5371 return error(GL_INVALID_OPERATION);
5372 }
5373
Nicolas Capens0bac2852016-05-07 06:09:58 -04005374 es2::Program *programObject = context->getProgram(program);
5375
5376 if(!programObject && program != 0)
5377 {
5378 if(context->getShader(program))
5379 {
5380 return error(GL_INVALID_OPERATION);
5381 }
5382 else
5383 {
5384 return error(GL_INVALID_VALUE);
5385 }
5386 }
5387
5388 if(program != 0 && !programObject->isLinked())
5389 {
5390 return error(GL_INVALID_OPERATION);
5391 }
5392
5393 context->useProgram(program);
5394 }
5395}
5396
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005397void GL_APIENTRY ValidateProgram(GLuint program)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005398{
5399 TRACE("(GLuint program = %d)", program);
5400
Chris Forbes108f3e12018-08-30 19:41:59 -07005401 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005402
5403 if(context)
5404 {
5405 es2::Program *programObject = context->getProgram(program);
5406
5407 if(!programObject)
5408 {
5409 if(context->getShader(program))
5410 {
5411 return error(GL_INVALID_OPERATION);
5412 }
5413 else
5414 {
5415 return error(GL_INVALID_VALUE);
5416 }
5417 }
5418
Ben Vanik1fd3b282017-07-10 14:08:12 -07005419 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005420 }
5421}
5422
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005423void GL_APIENTRY VertexAttrib1f(GLuint index, GLfloat x)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005424{
5425 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5426
5427 if(index >= es2::MAX_VERTEX_ATTRIBS)
5428 {
5429 return error(GL_INVALID_VALUE);
5430 }
5431
Chris Forbes108f3e12018-08-30 19:41:59 -07005432 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005433
5434 if(context)
5435 {
5436 GLfloat vals[4] = { x, 0, 0, 1 };
5437 context->setVertexAttrib(index, vals);
5438 }
5439}
5440
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005441void GL_APIENTRY VertexAttrib1fv(GLuint index, const GLfloat* values)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005442{
5443 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5444
5445 if(index >= es2::MAX_VERTEX_ATTRIBS)
5446 {
5447 return error(GL_INVALID_VALUE);
5448 }
5449
Chris Forbes108f3e12018-08-30 19:41:59 -07005450 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005451
5452 if(context)
5453 {
5454 GLfloat vals[4] = { values[0], 0, 0, 1 };
5455 context->setVertexAttrib(index, vals);
5456 }
5457}
5458
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005459void GL_APIENTRY VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005460{
5461 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5462
5463 if(index >= es2::MAX_VERTEX_ATTRIBS)
5464 {
5465 return error(GL_INVALID_VALUE);
5466 }
5467
Chris Forbes108f3e12018-08-30 19:41:59 -07005468 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005469
5470 if(context)
5471 {
5472 GLfloat vals[4] = { x, y, 0, 1 };
5473 context->setVertexAttrib(index, vals);
5474 }
5475}
5476
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005477void GL_APIENTRY VertexAttrib2fv(GLuint index, const GLfloat* values)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005478{
5479 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5480
5481 if(index >= es2::MAX_VERTEX_ATTRIBS)
5482 {
5483 return error(GL_INVALID_VALUE);
5484 }
5485
Chris Forbes108f3e12018-08-30 19:41:59 -07005486 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005487
5488 if(context)
5489 {
5490 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5491 context->setVertexAttrib(index, vals);
5492 }
5493}
5494
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005495void GL_APIENTRY VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005496{
5497 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5498
5499 if(index >= es2::MAX_VERTEX_ATTRIBS)
5500 {
5501 return error(GL_INVALID_VALUE);
5502 }
5503
Chris Forbes108f3e12018-08-30 19:41:59 -07005504 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005505
5506 if(context)
5507 {
5508 GLfloat vals[4] = { x, y, z, 1 };
5509 context->setVertexAttrib(index, vals);
5510 }
5511}
5512
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005513void GL_APIENTRY VertexAttrib3fv(GLuint index, const GLfloat* values)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005514{
5515 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5516
5517 if(index >= es2::MAX_VERTEX_ATTRIBS)
5518 {
5519 return error(GL_INVALID_VALUE);
5520 }
5521
Chris Forbes108f3e12018-08-30 19:41:59 -07005522 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005523
5524 if(context)
5525 {
5526 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
5527 context->setVertexAttrib(index, vals);
5528 }
5529}
5530
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005531void GL_APIENTRY VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005532{
5533 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
5534
5535 if(index >= es2::MAX_VERTEX_ATTRIBS)
5536 {
5537 return error(GL_INVALID_VALUE);
5538 }
5539
Chris Forbes108f3e12018-08-30 19:41:59 -07005540 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005541
5542 if(context)
5543 {
5544 GLfloat vals[4] = { x, y, z, w };
5545 context->setVertexAttrib(index, vals);
5546 }
5547}
5548
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005549void GL_APIENTRY VertexAttrib4fv(GLuint index, const GLfloat* values)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005550{
5551 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5552
5553 if(index >= es2::MAX_VERTEX_ATTRIBS)
5554 {
5555 return error(GL_INVALID_VALUE);
5556 }
5557
Chris Forbes108f3e12018-08-30 19:41:59 -07005558 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005559
5560 if(context)
5561 {
5562 context->setVertexAttrib(index, values);
5563 }
5564}
5565
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005566void GL_APIENTRY VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005567{
5568 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
5569 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
5570 index, size, type, normalized, stride, ptr);
5571
5572 if(index >= es2::MAX_VERTEX_ATTRIBS)
5573 {
5574 return error(GL_INVALID_VALUE);
5575 }
5576
5577 if(size < 1 || size > 4)
5578 {
5579 return error(GL_INVALID_VALUE);
5580 }
5581
Nicolas Capens0bac2852016-05-07 06:09:58 -04005582 switch(type)
5583 {
5584 case GL_BYTE:
5585 case GL_UNSIGNED_BYTE:
5586 case GL_SHORT:
5587 case GL_UNSIGNED_SHORT:
5588 case GL_FIXED:
5589 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04005590 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capensce8eb942018-04-26 16:38:05 -04005591 case GL_HALF_FLOAT:
Nicolas Capens7cfb50c2018-12-08 12:35:32 -08005592 case GL_INT:
5593 case GL_UNSIGNED_INT:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005594 break;
5595 case GL_INT_2_10_10_10_REV:
5596 case GL_UNSIGNED_INT_2_10_10_10_REV:
Nicolas Capens83463112018-06-12 23:55:16 -04005597 if(size != 4)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005598 {
Nicolas Capens83463112018-06-12 23:55:16 -04005599 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005600 }
Nicolas Capens83463112018-06-12 23:55:16 -04005601 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005602 default:
5603 return error(GL_INVALID_ENUM);
5604 }
5605
5606 if(stride < 0)
5607 {
5608 return error(GL_INVALID_VALUE);
5609 }
5610
Chris Forbes108f3e12018-08-30 19:41:59 -07005611 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005612
5613 if(context)
5614 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05005615 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
5616 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
5617 {
5618 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
5619 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
5620 return error(GL_INVALID_OPERATION);
5621 }
5622
Nicolas Capens51814272018-10-15 13:01:22 -04005623 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized != GL_FALSE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005624 }
5625}
5626
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005627void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005628{
5629 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
5630
5631 if(width < 0 || height < 0)
5632 {
5633 return error(GL_INVALID_VALUE);
5634 }
5635
Chris Forbes108f3e12018-08-30 19:41:59 -07005636 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005637
5638 if(context)
5639 {
5640 context->setViewportParams(x, y, width, height);
5641 }
5642}
5643
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005644static void GL_APIENTRY BlitFramebufferSW(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter, bool allowPartialDepthStencilBlit)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005645{
5646 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
5647 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
5648 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
5649 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5650
5651 switch(filter)
5652 {
5653 case GL_NEAREST:
5654 break;
5655 default:
5656 return error(GL_INVALID_ENUM);
5657 }
5658
5659 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
5660 {
5661 return error(GL_INVALID_VALUE);
5662 }
5663
Chris Forbes108f3e12018-08-30 19:41:59 -07005664 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005665
5666 if(context)
5667 {
5668 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
5669 {
5670 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
5671 return error(GL_INVALID_OPERATION);
5672 }
5673
Alexis Hetub9dda642016-10-06 11:25:32 -04005674 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005675 }
5676}
5677
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005678void GL_APIENTRY BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
Alexis Hetub9dda642016-10-06 11:25:32 -04005679{
Nicolas Capens805d7612018-08-02 13:56:32 -04005680 BlitFramebufferSW(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
Alexis Hetub9dda642016-10-06 11:25:32 -04005681}
5682
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005683void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5684 GLbitfield mask, GLenum filter)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005685{
5686 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
5687 {
5688 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
5689 return error(GL_INVALID_OPERATION);
5690 }
5691
Nicolas Capens805d7612018-08-02 13:56:32 -04005692 BlitFramebufferSW(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005693}
5694
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005695void GL_APIENTRY TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
5696 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005697{
5698 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
5699 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005700 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5701 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005702
5703 switch(target)
5704 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005705 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005706 switch(format)
5707 {
5708 case GL_DEPTH_COMPONENT:
5709 case GL_DEPTH_STENCIL_OES:
5710 return error(GL_INVALID_OPERATION);
5711 default:
5712 break;
5713 }
5714 break;
5715 default:
5716 return error(GL_INVALID_ENUM);
5717 }
5718
Nicolas Capensc61f46b2017-12-04 16:07:22 -05005719 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005720 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005721 return error(GL_INVALID_OPERATION);
5722 }
5723
Nicolas Capens83463112018-06-12 23:55:16 -04005724 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05005725 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005726 {
5727 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005728 }
5729
5730 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5731 {
5732 return error(GL_INVALID_VALUE);
5733 }
5734
Nicolas Capensefdf1032018-05-08 16:03:16 -04005735 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005736 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
5737 {
5738 return error(GL_INVALID_VALUE);
5739 }
5740
5741 if(border != 0)
5742 {
5743 return error(GL_INVALID_VALUE);
5744 }
5745
Chris Forbes108f3e12018-08-30 19:41:59 -07005746 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005747
5748 if(context)
5749 {
5750 es2::Texture3D *texture = context->getTexture3D();
5751
5752 if(!texture)
5753 {
5754 return error(GL_INVALID_OPERATION);
5755 }
5756
Nicolas Capens2fc90512018-01-23 22:24:22 +00005757 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005758 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005759 {
5760 return error(validationError);
5761 }
5762
Nicolas Capens894858a2018-03-22 00:55:23 -04005763 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005764 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005765 }
5766}
5767
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005768void GL_APIENTRY TexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005769{
5770 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5771 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005772 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5773 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005774
5775 switch(target)
5776 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005777 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005778 break;
5779 default:
5780 return error(GL_INVALID_ENUM);
5781 }
5782
Nicolas Capens0bac2852016-05-07 06:09:58 -04005783 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5784 {
5785 return error(GL_INVALID_VALUE);
5786 }
5787
5788 if((width < 0) || (height < 0) || (depth < 0))
5789 {
5790 return error(GL_INVALID_VALUE);
5791 }
5792
Chris Forbes108f3e12018-08-30 19:41:59 -07005793 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005794
5795 if(context)
5796 {
5797 es2::Texture3D *texture = context->getTexture3D();
5798
Nicolas Capens83463112018-06-12 23:55:16 -04005799 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05005800 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005801 {
5802 return error(validationError);
5803 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005804
Nicolas Capens5555af42017-12-14 13:14:03 -05005805 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005806 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005807 {
5808 return error(validationError);
5809 }
5810
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005811 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005812 }
5813}
5814
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005815void GL_APIENTRY CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005816{
5817 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5818 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
5819 target, level, xoffset, yoffset, zoffset, x, y, width, height);
5820
5821 switch(target)
5822 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005823 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005824 break;
5825 default:
5826 return error(GL_INVALID_ENUM);
5827 }
5828
5829 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5830 {
5831 return error(GL_INVALID_VALUE);
5832 }
5833
Chris Forbes108f3e12018-08-30 19:41:59 -07005834 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005835
5836 if(context)
5837 {
5838 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
5839
Alexis Hetu5cd502b2018-03-22 08:29:31 -04005840 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005841 {
5842 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
5843 }
5844
5845 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
5846
5847 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
5848 {
5849 return error(GL_INVALID_OPERATION);
5850 }
5851
5852 es2::Texture3D *texture = context->getTexture3D();
5853
Nicolas Capens83463112018-06-12 23:55:16 -04005854 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, zoffset, width, height, 1, GL_NONE, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05005855 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005856 {
5857 return error(validationError);
5858 }
5859
Nicolas Capens1529c2c2018-02-06 14:44:47 -05005860 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005861 }
5862}
5863
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005864void GL_APIENTRY CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005865{
5866 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
5867 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
5868 target, level, internalformat, width, height, depth, border, imageSize, data);
5869
5870 switch(target)
5871 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005872 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005873 break;
5874 default:
5875 return error(GL_INVALID_ENUM);
5876 }
5877
5878 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5879 {
5880 return error(GL_INVALID_VALUE);
5881 }
5882
Nicolas Capensefdf1032018-05-08 16:03:16 -04005883 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005884 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
5885 {
5886 return error(GL_INVALID_VALUE);
5887 }
5888
Nicolas Capens83463112018-06-12 23:55:16 -04005889 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005890 {
Nicolas Capens03589982018-02-01 17:28:32 -05005891 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005892 }
5893
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005894 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005895 {
5896 return error(GL_INVALID_VALUE);
5897 }
5898
Chris Forbes108f3e12018-08-30 19:41:59 -07005899 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005900
5901 if(context)
5902 {
5903 es2::Texture3D *texture = context->getTexture3D();
5904
5905 if(!texture)
5906 {
5907 return error(GL_INVALID_OPERATION);
5908 }
5909
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005910 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005911
Nicolas Capense65f5642018-02-26 17:47:06 -05005912 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005913 {
5914 return error(validationError);
5915 }
5916
Nicolas Capens0bac2852016-05-07 06:09:58 -04005917 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
5918 }
5919}
5920
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005921void GL_APIENTRY CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005922{
5923 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5924 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
5925 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
5926 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
5927
5928 switch(target)
5929 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005930 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005931 break;
5932 default:
5933 return error(GL_INVALID_ENUM);
5934 }
5935
5936 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5937 {
5938 return error(GL_INVALID_VALUE);
5939 }
5940
5941 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
5942 {
5943 return error(GL_INVALID_VALUE);
5944 }
5945
Nicolas Capens83463112018-06-12 23:55:16 -04005946 if(!IsCompressed(format))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005947 {
Nicolas Capens03589982018-02-01 17:28:32 -05005948 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005949 }
5950
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005951 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005952 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05005953 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005954 }
5955
Chris Forbes108f3e12018-08-30 19:41:59 -07005956 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005957
5958 if(context)
5959 {
5960 es2::Texture3D *texture = context->getTexture3D();
5961
5962 if(!texture)
5963 {
5964 return error(GL_INVALID_OPERATION);
5965 }
5966
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005967 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -05005968 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005969 {
5970 return error(validationError);
5971 }
5972
5973 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005974 }
5975}
5976
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04005977void GL_APIENTRY FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005978{
5979 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
5980 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
5981
Nicolas Capens6c4564a2018-01-26 01:14:34 +00005982 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005983 {
5984 return error(GL_INVALID_ENUM);
5985 }
5986
Chris Forbes108f3e12018-08-30 19:41:59 -07005987 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005988
5989 if(context)
5990 {
5991 if(texture == 0)
5992 {
5993 textarget = GL_NONE;
5994 }
5995 else
5996 {
5997 es2::Texture *tex = context->getTexture(texture);
5998
5999 if(!tex)
6000 {
6001 return error(GL_INVALID_OPERATION);
6002 }
6003
Nicolas Capens0bac2852016-05-07 06:09:58 -04006004 switch(textarget)
6005 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006006 case GL_TEXTURE_3D:
6007 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006008 {
6009 return error(GL_INVALID_OPERATION);
6010 }
6011 break;
6012 default:
6013 return error(GL_INVALID_ENUM);
6014 }
6015
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006016 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006017 {
6018 return error(GL_INVALID_VALUE);
6019 }
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006020
6021 if(tex->isCompressed(textarget, level))
6022 {
6023 return error(GL_INVALID_OPERATION);
6024 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006025 }
6026
6027 es2::Framebuffer *framebuffer = nullptr;
6028 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006029 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006030 {
6031 framebuffer = context->getReadFramebuffer();
6032 framebufferName = context->getReadFramebufferName();
6033 }
6034 else
6035 {
6036 framebuffer = context->getDrawFramebuffer();
6037 framebufferName = context->getDrawFramebufferName();
6038 }
6039
6040 if(framebufferName == 0 || !framebuffer)
6041 {
6042 return error(GL_INVALID_OPERATION);
6043 }
6044
Nicolas Capens0bac2852016-05-07 06:09:58 -04006045 switch(attachment)
6046 {
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006047 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
6048 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
Nicolas Capens83463112018-06-12 23:55:16 -04006049 default:
Nicolas Capens4e344192018-10-24 21:01:17 -04006050 if(attachment < GL_COLOR_ATTACHMENT0 || attachment > GL_COLOR_ATTACHMENT31)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006051 {
6052 return error(GL_INVALID_ENUM);
6053 }
Nicolas Capens4e344192018-10-24 21:01:17 -04006054
6055 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6056 {
6057 return error(GL_INVALID_OPERATION);
6058 }
6059
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006060 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006061 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006062 }
6063 }
6064}
6065
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006066void GL_APIENTRY EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006067{
Nicolas Capens0bac2852016-05-07 06:09:58 -04006068 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6069
6070 switch(target)
6071 {
6072 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006073 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006074 case GL_TEXTURE_EXTERNAL_OES:
6075 break;
6076 default:
6077 return error(GL_INVALID_ENUM);
6078 }
6079
Chris Forbes108f3e12018-08-30 19:41:59 -07006080 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006081
6082 if(context)
6083 {
Alexis Hetu46768622018-01-16 22:09:28 -05006084 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006085
6086 if(!texture)
6087 {
6088 return error(GL_INVALID_OPERATION);
6089 }
6090
Nicolas Capens58df2f62016-06-07 14:48:56 -04006091 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006092
Nicolas Capens58df2f62016-06-07 14:48:56 -04006093 if(!eglImage)
6094 {
6095 return error(GL_INVALID_OPERATION);
6096 }
6097
6098 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006099 }
6100}
6101
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006102void GL_APIENTRY EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006103{
6104 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6105
6106 UNIMPLEMENTED();
6107}
6108
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006109GLboolean GL_APIENTRY IsRenderbufferOES(GLuint renderbuffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006110{
6111 return IsRenderbuffer(renderbuffer);
6112}
6113
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006114void GL_APIENTRY BindRenderbufferOES(GLenum target, GLuint renderbuffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006115{
6116 BindRenderbuffer(target, renderbuffer);
6117}
6118
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006119void GL_APIENTRY DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006120{
6121 DeleteRenderbuffers(n, renderbuffers);
6122}
6123
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006124void GL_APIENTRY GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006125{
6126 GenRenderbuffers(n, renderbuffers);
6127}
6128
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006129void GL_APIENTRY RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006130{
6131 RenderbufferStorage(target, internalformat, width, height);
6132}
6133
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006134void GL_APIENTRY GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006135{
6136 GetRenderbufferParameteriv(target, pname, params);
6137}
6138
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006139GLboolean GL_APIENTRY IsFramebufferOES(GLuint framebuffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006140{
6141 return IsFramebuffer(framebuffer);
6142}
6143
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006144void GL_APIENTRY BindFramebufferOES(GLenum target, GLuint framebuffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006145{
6146 BindFramebuffer(target, framebuffer);
6147}
6148
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006149void GL_APIENTRY DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006150{
6151 DeleteFramebuffers(n, framebuffers);
6152}
6153
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006154void GL_APIENTRY GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006155{
6156 GenFramebuffers(n, framebuffers);
6157}
6158
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006159GLenum GL_APIENTRY CheckFramebufferStatusOES(GLenum target)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006160{
6161 return CheckFramebufferStatus(target);
6162}
6163
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006164void GL_APIENTRY FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006165{
6166 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6167}
6168
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006169void GL_APIENTRY FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006170{
6171 FramebufferTexture2D(target, attachment, textarget, texture, level);
6172}
6173
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006174void GL_APIENTRY GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006175{
6176 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6177}
6178
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006179void GL_APIENTRY GenerateMipmapOES(GLenum target)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006180{
6181 GenerateMipmap(target);
6182}
6183
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04006184void GL_APIENTRY DrawBuffersEXT(GLsizei n, const GLenum *bufs)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006185{
6186 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6187
6188 if(n < 0 || n > MAX_DRAW_BUFFERS)
6189 {
6190 return error(GL_INVALID_VALUE);
6191 }
6192
Chris Forbes108f3e12018-08-30 19:41:59 -07006193 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006194
6195 if(context)
6196 {
6197 GLuint drawFramebufferName = context->getDrawFramebufferName();
6198
6199 if((drawFramebufferName == 0) && (n != 1))
6200 {
6201 return error(GL_INVALID_OPERATION);
6202 }
6203
6204 for(unsigned int i = 0; i < (unsigned)n; i++)
6205 {
6206 switch(bufs[i])
6207 {
6208 case GL_BACK:
6209 if(drawFramebufferName != 0)
6210 {
6211 return error(GL_INVALID_OPERATION);
6212 }
6213 break;
6214 case GL_NONE:
6215 break;
6216 case GL_COLOR_ATTACHMENT0_EXT:
6217 case GL_COLOR_ATTACHMENT1_EXT:
6218 case GL_COLOR_ATTACHMENT2_EXT:
6219 case GL_COLOR_ATTACHMENT3_EXT:
6220 case GL_COLOR_ATTACHMENT4_EXT:
6221 case GL_COLOR_ATTACHMENT5_EXT:
6222 case GL_COLOR_ATTACHMENT6_EXT:
6223 case GL_COLOR_ATTACHMENT7_EXT:
6224 case GL_COLOR_ATTACHMENT8_EXT:
6225 case GL_COLOR_ATTACHMENT9_EXT:
6226 case GL_COLOR_ATTACHMENT10_EXT:
6227 case GL_COLOR_ATTACHMENT11_EXT:
6228 case GL_COLOR_ATTACHMENT12_EXT:
6229 case GL_COLOR_ATTACHMENT13_EXT:
6230 case GL_COLOR_ATTACHMENT14_EXT:
6231 case GL_COLOR_ATTACHMENT15_EXT:
6232 {
6233 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6234
6235 if(index >= MAX_COLOR_ATTACHMENTS)
6236 {
6237 return error(GL_INVALID_OPERATION);
6238 }
6239
6240 if(index != i)
6241 {
6242 return error(GL_INVALID_OPERATION);
6243 }
6244
6245 if(drawFramebufferName == 0)
6246 {
6247 return error(GL_INVALID_OPERATION);
6248 }
6249 }
6250 break;
6251 default:
6252 return error(GL_INVALID_ENUM);
6253 }
6254 }
6255
6256 context->setFramebufferDrawBuffers(n, bufs);
6257 }
6258}
6259
6260}
6261
Nicolas Capens805d7612018-08-02 13:56:32 -04006262#include "entry_points.h"
6263
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006264extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006265{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006266 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006267 {
6268 const char *name;
6269 __eglMustCastToProperFunctionPointerType address;
6270 };
6271
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006272 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006273 {
Nicolas Capens805d7612018-08-02 13:56:32 -04006274 #define FUNCTION(name) {"gl" #name, (__eglMustCastToProperFunctionPointerType)gl::name}
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006275
Nicolas Capens805d7612018-08-02 13:56:32 -04006276 FUNCTION(ActiveTexture),
6277 FUNCTION(AttachShader),
6278 FUNCTION(BeginQuery),
6279 FUNCTION(BeginQueryEXT),
6280 FUNCTION(BeginTransformFeedback),
6281 FUNCTION(BindAttribLocation),
6282 FUNCTION(BindBuffer),
6283 FUNCTION(BindBufferBase),
6284 FUNCTION(BindBufferRange),
6285 FUNCTION(BindFramebuffer),
6286 FUNCTION(BindFramebufferOES),
6287 FUNCTION(BindRenderbuffer),
6288 FUNCTION(BindRenderbufferOES),
6289 FUNCTION(BindSampler),
6290 FUNCTION(BindTexture),
6291 FUNCTION(BindTransformFeedback),
6292 FUNCTION(BindVertexArray),
6293 FUNCTION(BindVertexArrayOES),
6294 FUNCTION(BlendColor),
6295 FUNCTION(BlendEquation),
6296 FUNCTION(BlendEquationSeparate),
6297 FUNCTION(BlendFunc),
6298 FUNCTION(BlendFuncSeparate),
6299 FUNCTION(BlitFramebuffer),
6300 FUNCTION(BlitFramebufferANGLE),
6301 FUNCTION(BufferData),
6302 FUNCTION(BufferSubData),
6303 FUNCTION(CheckFramebufferStatus),
6304 FUNCTION(CheckFramebufferStatusOES),
6305 FUNCTION(Clear),
6306 FUNCTION(ClearBufferfi),
6307 FUNCTION(ClearBufferfv),
6308 FUNCTION(ClearBufferiv),
6309 FUNCTION(ClearBufferuiv),
6310 FUNCTION(ClearColor),
6311 FUNCTION(ClearDepthf),
6312 FUNCTION(ClearStencil),
6313 FUNCTION(ClientWaitSync),
6314 FUNCTION(ColorMask),
6315 FUNCTION(CompileShader),
6316 FUNCTION(CompressedTexImage2D),
6317 FUNCTION(CompressedTexImage3D),
6318 FUNCTION(CompressedTexSubImage2D),
6319 FUNCTION(CompressedTexSubImage3D),
6320 FUNCTION(CopyBufferSubData),
6321 FUNCTION(CopyTexImage2D),
6322 FUNCTION(CopyTexSubImage2D),
6323 FUNCTION(CopyTexSubImage3D),
6324 FUNCTION(CreateProgram),
6325 FUNCTION(CreateShader),
6326 FUNCTION(CullFace),
6327 FUNCTION(DeleteBuffers),
6328 FUNCTION(DeleteFencesNV),
6329 FUNCTION(DeleteFramebuffers),
6330 FUNCTION(DeleteFramebuffersOES),
6331 FUNCTION(DeleteProgram),
6332 FUNCTION(DeleteQueries),
6333 FUNCTION(DeleteQueriesEXT),
6334 FUNCTION(DeleteRenderbuffers),
6335 FUNCTION(DeleteRenderbuffersOES),
6336 FUNCTION(DeleteSamplers),
6337 FUNCTION(DeleteShader),
6338 FUNCTION(DeleteSync),
6339 FUNCTION(DeleteTextures),
6340 FUNCTION(DeleteTransformFeedbacks),
6341 FUNCTION(DeleteVertexArrays),
6342 FUNCTION(DeleteVertexArraysOES),
6343 FUNCTION(DepthFunc),
6344 FUNCTION(DepthMask),
6345 FUNCTION(DepthRangef),
6346 FUNCTION(DetachShader),
6347 FUNCTION(Disable),
6348 FUNCTION(DisableVertexAttribArray),
6349 FUNCTION(DrawArrays),
6350 FUNCTION(DrawArraysInstanced),
6351 FUNCTION(DrawBuffers),
6352 FUNCTION(DrawBuffersEXT),
6353 FUNCTION(DrawElements),
6354 FUNCTION(DrawElementsInstanced),
6355 FUNCTION(DrawRangeElements),
6356 FUNCTION(EGLImageTargetRenderbufferStorageOES),
6357 FUNCTION(EGLImageTargetTexture2DOES),
6358 FUNCTION(Enable),
6359 FUNCTION(EnableVertexAttribArray),
6360 FUNCTION(EndQuery),
6361 FUNCTION(EndQueryEXT),
6362 FUNCTION(EndTransformFeedback),
6363 FUNCTION(FenceSync),
6364 FUNCTION(Finish),
6365 FUNCTION(FinishFenceNV),
6366 FUNCTION(Flush),
6367 FUNCTION(FlushMappedBufferRange),
6368 FUNCTION(FramebufferRenderbuffer),
6369 FUNCTION(FramebufferRenderbufferOES),
6370 FUNCTION(FramebufferTexture2D),
6371 FUNCTION(FramebufferTexture2DOES),
6372 FUNCTION(FramebufferTextureLayer),
6373 FUNCTION(FrontFace),
6374 FUNCTION(GenBuffers),
6375 FUNCTION(GenFencesNV),
6376 FUNCTION(GenFramebuffers),
6377 FUNCTION(GenFramebuffersOES),
6378 FUNCTION(GenQueries),
6379 FUNCTION(GenQueriesEXT),
6380 FUNCTION(GenRenderbuffers),
6381 FUNCTION(GenRenderbuffersOES),
6382 FUNCTION(GenSamplers),
6383 FUNCTION(GenTextures),
6384 FUNCTION(GenTransformFeedbacks),
6385 FUNCTION(GenVertexArrays),
6386 FUNCTION(GenVertexArraysOES),
6387 FUNCTION(GenerateMipmap),
6388 FUNCTION(GenerateMipmapOES),
6389 FUNCTION(GetActiveAttrib),
6390 FUNCTION(GetActiveUniform),
6391 FUNCTION(GetActiveUniformBlockName),
6392 FUNCTION(GetActiveUniformBlockiv),
6393 FUNCTION(GetActiveUniformsiv),
6394 FUNCTION(GetAttachedShaders),
6395 FUNCTION(GetAttribLocation),
6396 FUNCTION(GetBooleanv),
6397 FUNCTION(GetBufferParameteri64v),
6398 FUNCTION(GetBufferParameteriv),
6399 FUNCTION(GetBufferPointerv),
6400 FUNCTION(GetError),
6401 FUNCTION(GetFenceivNV),
6402 FUNCTION(GetFloatv),
6403 FUNCTION(GetFragDataLocation),
6404 FUNCTION(GetFramebufferAttachmentParameteriv),
6405 FUNCTION(GetFramebufferAttachmentParameterivOES),
6406 FUNCTION(GetGraphicsResetStatusEXT),
6407 FUNCTION(GetInteger64i_v),
6408 FUNCTION(GetInteger64v),
6409 FUNCTION(GetIntegeri_v),
6410 FUNCTION(GetIntegerv),
6411 FUNCTION(GetInternalformativ),
6412 FUNCTION(GetProgramBinary),
6413 FUNCTION(GetProgramInfoLog),
6414 FUNCTION(GetProgramiv),
6415 FUNCTION(GetQueryObjectuiv),
6416 FUNCTION(GetQueryObjectuivEXT),
6417 FUNCTION(GetQueryiv),
6418 FUNCTION(GetQueryivEXT),
6419 FUNCTION(GetRenderbufferParameteriv),
6420 FUNCTION(GetRenderbufferParameterivOES),
6421 FUNCTION(GetSamplerParameterfv),
6422 FUNCTION(GetSamplerParameteriv),
6423 FUNCTION(GetShaderInfoLog),
6424 FUNCTION(GetShaderPrecisionFormat),
6425 FUNCTION(GetShaderSource),
6426 FUNCTION(GetShaderiv),
6427 FUNCTION(GetString),
6428 FUNCTION(GetStringi),
6429 FUNCTION(GetSynciv),
6430 FUNCTION(GetTexParameterfv),
6431 FUNCTION(GetTexParameteriv),
6432 FUNCTION(GetTransformFeedbackVarying),
6433 FUNCTION(GetUniformBlockIndex),
6434 FUNCTION(GetUniformIndices),
6435 FUNCTION(GetUniformLocation),
6436 FUNCTION(GetUniformfv),
6437 FUNCTION(GetUniformiv),
6438 FUNCTION(GetUniformuiv),
6439 FUNCTION(GetVertexAttribIiv),
6440 FUNCTION(GetVertexAttribIuiv),
6441 FUNCTION(GetVertexAttribPointerv),
6442 FUNCTION(GetVertexAttribfv),
6443 FUNCTION(GetVertexAttribiv),
6444 FUNCTION(GetnUniformfvEXT),
6445 FUNCTION(GetnUniformivEXT),
6446 FUNCTION(Hint),
6447 FUNCTION(InvalidateFramebuffer),
6448 FUNCTION(InvalidateSubFramebuffer),
6449 FUNCTION(IsBuffer),
6450 FUNCTION(IsEnabled),
6451 FUNCTION(IsFenceNV),
6452 FUNCTION(IsFramebuffer),
6453 FUNCTION(IsFramebufferOES),
6454 FUNCTION(IsProgram),
6455 FUNCTION(IsQuery),
6456 FUNCTION(IsQueryEXT),
6457 FUNCTION(IsRenderbuffer),
6458 FUNCTION(IsRenderbufferOES),
6459 FUNCTION(IsSampler),
6460 FUNCTION(IsShader),
6461 FUNCTION(IsSync),
6462 FUNCTION(IsTexture),
6463 FUNCTION(IsTransformFeedback),
6464 FUNCTION(IsVertexArray),
6465 FUNCTION(IsVertexArrayOES),
6466 FUNCTION(LineWidth),
6467 FUNCTION(LinkProgram),
6468 FUNCTION(MapBufferRange),
6469 FUNCTION(PauseTransformFeedback),
6470 FUNCTION(PixelStorei),
6471 FUNCTION(PolygonOffset),
6472 FUNCTION(ProgramBinary),
6473 FUNCTION(ProgramParameteri),
6474 FUNCTION(ReadBuffer),
6475 FUNCTION(ReadPixels),
6476 FUNCTION(ReadnPixelsEXT),
6477 FUNCTION(ReleaseShaderCompiler),
6478 FUNCTION(RenderbufferStorage),
6479 FUNCTION(RenderbufferStorageMultisample),
6480 FUNCTION(RenderbufferStorageMultisampleANGLE),
6481 FUNCTION(RenderbufferStorageOES),
6482 FUNCTION(ResumeTransformFeedback),
6483 FUNCTION(SampleCoverage),
6484 FUNCTION(SamplerParameterf),
6485 FUNCTION(SamplerParameterfv),
6486 FUNCTION(SamplerParameteri),
6487 FUNCTION(SamplerParameteriv),
6488 FUNCTION(Scissor),
6489 FUNCTION(SetFenceNV),
6490 FUNCTION(ShaderBinary),
6491 FUNCTION(ShaderSource),
6492 FUNCTION(StencilFunc),
6493 FUNCTION(StencilFuncSeparate),
6494 FUNCTION(StencilMask),
6495 FUNCTION(StencilMaskSeparate),
6496 FUNCTION(StencilOp),
6497 FUNCTION(StencilOpSeparate),
6498 FUNCTION(TestFenceNV),
6499 FUNCTION(TexImage2D),
6500 FUNCTION(TexImage3D),
6501 FUNCTION(TexImage3DOES),
6502 FUNCTION(TexParameterf),
6503 FUNCTION(TexParameterfv),
6504 FUNCTION(TexParameteri),
6505 FUNCTION(TexParameteriv),
6506 FUNCTION(TexStorage2D),
6507 FUNCTION(TexStorage3D),
6508 FUNCTION(TexSubImage2D),
6509 FUNCTION(TexSubImage3D),
6510 FUNCTION(TransformFeedbackVaryings),
6511 FUNCTION(Uniform1f),
6512 FUNCTION(Uniform1fv),
6513 FUNCTION(Uniform1i),
6514 FUNCTION(Uniform1iv),
6515 FUNCTION(Uniform1ui),
6516 FUNCTION(Uniform1uiv),
6517 FUNCTION(Uniform2f),
6518 FUNCTION(Uniform2fv),
6519 FUNCTION(Uniform2i),
6520 FUNCTION(Uniform2iv),
6521 FUNCTION(Uniform2ui),
6522 FUNCTION(Uniform2uiv),
6523 FUNCTION(Uniform3f),
6524 FUNCTION(Uniform3fv),
6525 FUNCTION(Uniform3i),
6526 FUNCTION(Uniform3iv),
6527 FUNCTION(Uniform3ui),
6528 FUNCTION(Uniform3uiv),
6529 FUNCTION(Uniform4f),
6530 FUNCTION(Uniform4fv),
6531 FUNCTION(Uniform4i),
6532 FUNCTION(Uniform4iv),
6533 FUNCTION(Uniform4ui),
6534 FUNCTION(Uniform4uiv),
6535 FUNCTION(UniformBlockBinding),
6536 FUNCTION(UniformMatrix2fv),
6537 FUNCTION(UniformMatrix2x3fv),
6538 FUNCTION(UniformMatrix2x4fv),
6539 FUNCTION(UniformMatrix3fv),
6540 FUNCTION(UniformMatrix3x2fv),
6541 FUNCTION(UniformMatrix3x4fv),
6542 FUNCTION(UniformMatrix4fv),
6543 FUNCTION(UniformMatrix4x2fv),
6544 FUNCTION(UniformMatrix4x3fv),
6545 FUNCTION(UnmapBuffer),
6546 FUNCTION(UseProgram),
6547 FUNCTION(ValidateProgram),
6548 FUNCTION(VertexAttrib1f),
6549 FUNCTION(VertexAttrib1fv),
6550 FUNCTION(VertexAttrib2f),
6551 FUNCTION(VertexAttrib2fv),
6552 FUNCTION(VertexAttrib3f),
6553 FUNCTION(VertexAttrib3fv),
6554 FUNCTION(VertexAttrib4f),
6555 FUNCTION(VertexAttrib4fv),
6556 FUNCTION(VertexAttribDivisor),
6557 FUNCTION(VertexAttribDivisorANGLE),
6558 FUNCTION(VertexAttribDivisorEXT),
6559 FUNCTION(VertexAttribI4i),
6560 FUNCTION(VertexAttribI4iv),
6561 FUNCTION(VertexAttribI4ui),
6562 FUNCTION(VertexAttribI4uiv),
6563 FUNCTION(VertexAttribIPointer),
6564 FUNCTION(VertexAttribPointer),
6565 FUNCTION(Viewport),
6566 FUNCTION(WaitSync),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006567
6568 #undef FUNCTION
6569 };
6570
6571 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
6572 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
6573
Nicolas Capens48908cb2018-01-08 13:07:14 -05006574 // The array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6575 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6576 #ifndef NDEBUG
6577 for(size_t i = 0; i < numFunctions - 1; i++)
6578 {
6579 ASSERT(strcmp(glFunctions[i].name, glFunctions[i + 1].name) < 0);
6580 }
6581 #endif
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006582
6583 if(procname && strncmp("gl", procname, 2) == 0)
6584 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05006585 struct CompareFunctor
6586 {
6587 bool operator()(const Function &a, const Function &b) const
6588 {
6589 return strcmp(a.name, b.name) < 0;
6590 }
6591 };
6592
6593 Function needle;
6594 needle.name = procname;
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006595 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
Nicolas Capens48908cb2018-01-08 13:07:14 -05006596
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006597 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006598 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006599 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006600 }
6601 }
6602
6603 return nullptr;
6604}