blob: 209853a5ec17c5bc39912b490d4e02be17fac445 [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
16#include "main.h"
17#include "mathutil.h"
18#include "utilities.h"
19#include "Buffer.h"
20#include "Context.h"
21#include "Fence.h"
22#include "Framebuffer.h"
23#include "Program.h"
24#include "Renderbuffer.h"
25#include "Shader.h"
26#include "Texture.h"
27#include "Query.h"
28#include "TransformFeedback.h"
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -050029#include "VertexArray.h"
Nicolas Capens0bac2852016-05-07 06:09:58 -040030#include "common/debug.h"
31#include "Common/Version.h"
32
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{
45 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)
46 {
47 return false;
48 }
49
50 return true;
51}
52
Nicolas Capens0bac2852016-05-07 06:09:58 -040053void ActiveTexture(GLenum texture)
54{
55 TRACE("(GLenum texture = 0x%X)", texture);
56
Chris Forbes108f3e12018-08-30 19:41:59 -070057 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -040058
59 if(context)
60 {
61 if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
62 {
63 return error(GL_INVALID_ENUM);
64 }
65
66 context->setActiveSampler(texture - GL_TEXTURE0);
67 }
68}
69
70void AttachShader(GLuint program, GLuint shader)
71{
72 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
73
Chris Forbes108f3e12018-08-30 19:41:59 -070074 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -040075
76 if(context)
77 {
78 es2::Program *programObject = context->getProgram(program);
79 es2::Shader *shaderObject = context->getShader(shader);
80
81 if(!programObject)
82 {
83 if(context->getShader(program))
84 {
85 return error(GL_INVALID_OPERATION);
86 }
87 else
88 {
89 return error(GL_INVALID_VALUE);
90 }
91 }
92
93 if(!shaderObject)
94 {
95 if(context->getProgram(shader))
96 {
97 return error(GL_INVALID_OPERATION);
98 }
99 else
100 {
101 return error(GL_INVALID_VALUE);
102 }
103 }
104
105 if(!programObject->attachShader(shaderObject))
106 {
107 return error(GL_INVALID_OPERATION);
108 }
109 }
110}
111
112void BeginQueryEXT(GLenum target, GLuint name)
113{
114 TRACE("(GLenum target = 0x%X, GLuint name = %d)", target, name);
115
116 switch(target)
117 {
118 case GL_ANY_SAMPLES_PASSED_EXT:
119 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
120 break;
121 default:
122 return error(GL_INVALID_ENUM);
123 }
124
125 if(name == 0)
126 {
127 return error(GL_INVALID_OPERATION);
128 }
129
Chris Forbes108f3e12018-08-30 19:41:59 -0700130 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400131
132 if(context)
133 {
134 context->beginQuery(target, name);
135 }
136}
137
138void BindAttribLocation(GLuint program, GLuint index, const GLchar* name)
139{
140 TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = %s)", program, index, name);
141
142 if(index >= es2::MAX_VERTEX_ATTRIBS)
143 {
144 return error(GL_INVALID_VALUE);
145 }
146
Chris Forbes108f3e12018-08-30 19:41:59 -0700147 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400148
149 if(context)
150 {
151 es2::Program *programObject = context->getProgram(program);
152
153 if(!programObject)
154 {
155 if(context->getShader(program))
156 {
157 return error(GL_INVALID_OPERATION);
158 }
159 else
160 {
161 return error(GL_INVALID_VALUE);
162 }
163 }
164
165 if(strncmp(name, "gl_", 3) == 0)
166 {
167 return error(GL_INVALID_OPERATION);
168 }
169
170 programObject->bindAttributeLocation(index, name);
171 }
172}
173
174void BindBuffer(GLenum target, GLuint buffer)
175{
176 TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
177
Chris Forbes108f3e12018-08-30 19:41:59 -0700178 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400179
180 if(context)
181 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400182 switch(target)
183 {
184 case GL_ARRAY_BUFFER:
185 context->bindArrayBuffer(buffer);
186 return;
187 case GL_ELEMENT_ARRAY_BUFFER:
188 context->bindElementArrayBuffer(buffer);
189 return;
190 case GL_COPY_READ_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400191 context->bindCopyReadBuffer(buffer);
192 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400193 case GL_COPY_WRITE_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400194 context->bindCopyWriteBuffer(buffer);
195 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400196 case GL_PIXEL_PACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400197 context->bindPixelPackBuffer(buffer);
198 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400199 case GL_PIXEL_UNPACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400200 context->bindPixelUnpackBuffer(buffer);
201 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400202 case GL_TRANSFORM_FEEDBACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400203 context->bindTransformFeedbackBuffer(buffer);
204 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400205 case GL_UNIFORM_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400206 context->bindGenericUniformBuffer(buffer);
207 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400208 default:
209 return error(GL_INVALID_ENUM);
210 }
211 }
212}
213
214void BindFramebuffer(GLenum target, GLuint framebuffer)
215{
216 TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
217
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000218 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400219 {
220 return error(GL_INVALID_ENUM);
221 }
222
Chris Forbes108f3e12018-08-30 19:41:59 -0700223 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400224
225 if(context)
226 {
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000227 if(target == GL_READ_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400228 {
229 context->bindReadFramebuffer(framebuffer);
230 }
231
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000232 if(target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400233 {
234 context->bindDrawFramebuffer(framebuffer);
235 }
236 }
237}
238
239void BindRenderbuffer(GLenum target, GLuint renderbuffer)
240{
241 TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
242
243 if(target != GL_RENDERBUFFER)
244 {
245 return error(GL_INVALID_ENUM);
246 }
247
Chris Forbes108f3e12018-08-30 19:41:59 -0700248 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400249
250 if(context)
251 {
252 // [OpenGL ES 2.0.25] Section 4.4.3 page 110
253 // [OpenGL ES 3.0.4] Section 4.4.2 page 204
254 // If renderbuffer is not zero, then the resulting renderbuffer object
255 // is a new state vector, initialized with a zero-sized memory buffer.
256 context->bindRenderbuffer(renderbuffer);
257 }
258}
259
260void BindTexture(GLenum target, GLuint texture)
261{
262 TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
263
Chris Forbes108f3e12018-08-30 19:41:59 -0700264 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400265
266 if(context)
267 {
268 es2::Texture *textureObject = context->getTexture(texture);
269
270 if(textureObject && textureObject->getTarget() != target && texture != 0)
271 {
272 return error(GL_INVALID_OPERATION);
273 }
274
Nicolas Capens0bac2852016-05-07 06:09:58 -0400275 switch(target)
276 {
277 case GL_TEXTURE_2D:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500278 context->bindTexture(TEXTURE_2D, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400279 break;
280 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500281 context->bindTexture(TEXTURE_CUBE, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400282 break;
283 case GL_TEXTURE_EXTERNAL_OES:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500284 context->bindTexture(TEXTURE_EXTERNAL, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400285 break;
286 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500287 context->bindTexture(TEXTURE_2D_ARRAY, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400288 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -0500289 case GL_TEXTURE_3D:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500290 context->bindTexture(TEXTURE_3D, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400291 break;
Alexis Hetu46768622018-01-16 22:09:28 -0500292 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500293 context->bindTexture(TEXTURE_2D_RECT, texture);
Alexis Hetu46768622018-01-16 22:09:28 -0500294 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400295 default:
296 return error(GL_INVALID_ENUM);
297 }
298 }
299}
300
301void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
302{
303 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
304 red, green, blue, alpha);
305
Chris Forbes108f3e12018-08-30 19:41:59 -0700306 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400307
308 if(context)
309 {
310 context->setBlendColor(es2::clamp01(red), es2::clamp01(green), es2::clamp01(blue), es2::clamp01(alpha));
311 }
312}
313
314void BlendEquation(GLenum mode)
315{
316 glBlendEquationSeparate(mode, mode);
317}
318
319void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
320{
321 TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
322
323 switch(modeRGB)
324 {
325 case GL_FUNC_ADD:
326 case GL_FUNC_SUBTRACT:
327 case GL_FUNC_REVERSE_SUBTRACT:
328 case GL_MIN_EXT:
329 case GL_MAX_EXT:
330 break;
331 default:
332 return error(GL_INVALID_ENUM);
333 }
334
335 switch(modeAlpha)
336 {
337 case GL_FUNC_ADD:
338 case GL_FUNC_SUBTRACT:
339 case GL_FUNC_REVERSE_SUBTRACT:
340 case GL_MIN_EXT:
341 case GL_MAX_EXT:
342 break;
343 default:
344 return error(GL_INVALID_ENUM);
345 }
346
Chris Forbes108f3e12018-08-30 19:41:59 -0700347 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400348
349 if(context)
350 {
351 context->setBlendEquation(modeRGB, modeAlpha);
352 }
353}
354
355void BlendFunc(GLenum sfactor, GLenum dfactor)
356{
357 glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
358}
359
360void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
361{
362 TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
363 srcRGB, dstRGB, srcAlpha, dstAlpha);
364
Nicolas Capens0bac2852016-05-07 06:09:58 -0400365 switch(srcRGB)
366 {
367 case GL_ZERO:
368 case GL_ONE:
369 case GL_SRC_COLOR:
370 case GL_ONE_MINUS_SRC_COLOR:
371 case GL_DST_COLOR:
372 case GL_ONE_MINUS_DST_COLOR:
373 case GL_SRC_ALPHA:
374 case GL_ONE_MINUS_SRC_ALPHA:
375 case GL_DST_ALPHA:
376 case GL_ONE_MINUS_DST_ALPHA:
377 case GL_CONSTANT_COLOR:
378 case GL_ONE_MINUS_CONSTANT_COLOR:
379 case GL_CONSTANT_ALPHA:
380 case GL_ONE_MINUS_CONSTANT_ALPHA:
381 case GL_SRC_ALPHA_SATURATE:
382 break;
383 default:
384 return error(GL_INVALID_ENUM);
385 }
386
387 switch(dstRGB)
388 {
389 case GL_ZERO:
390 case GL_ONE:
391 case GL_SRC_COLOR:
392 case GL_ONE_MINUS_SRC_COLOR:
393 case GL_DST_COLOR:
394 case GL_ONE_MINUS_DST_COLOR:
395 case GL_SRC_ALPHA:
396 case GL_ONE_MINUS_SRC_ALPHA:
397 case GL_DST_ALPHA:
398 case GL_ONE_MINUS_DST_ALPHA:
399 case GL_CONSTANT_COLOR:
400 case GL_ONE_MINUS_CONSTANT_COLOR:
401 case GL_CONSTANT_ALPHA:
402 case GL_ONE_MINUS_CONSTANT_ALPHA:
403 break;
404 case GL_SRC_ALPHA_SATURATE:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400405 break;
406 default:
407 return error(GL_INVALID_ENUM);
408 }
409
410 switch(srcAlpha)
411 {
412 case GL_ZERO:
413 case GL_ONE:
414 case GL_SRC_COLOR:
415 case GL_ONE_MINUS_SRC_COLOR:
416 case GL_DST_COLOR:
417 case GL_ONE_MINUS_DST_COLOR:
418 case GL_SRC_ALPHA:
419 case GL_ONE_MINUS_SRC_ALPHA:
420 case GL_DST_ALPHA:
421 case GL_ONE_MINUS_DST_ALPHA:
422 case GL_CONSTANT_COLOR:
423 case GL_ONE_MINUS_CONSTANT_COLOR:
424 case GL_CONSTANT_ALPHA:
425 case GL_ONE_MINUS_CONSTANT_ALPHA:
426 case GL_SRC_ALPHA_SATURATE:
427 break;
428 default:
429 return error(GL_INVALID_ENUM);
430 }
431
432 switch(dstAlpha)
433 {
434 case GL_ZERO:
435 case GL_ONE:
436 case GL_SRC_COLOR:
437 case GL_ONE_MINUS_SRC_COLOR:
438 case GL_DST_COLOR:
439 case GL_ONE_MINUS_DST_COLOR:
440 case GL_SRC_ALPHA:
441 case GL_ONE_MINUS_SRC_ALPHA:
442 case GL_DST_ALPHA:
443 case GL_ONE_MINUS_DST_ALPHA:
444 case GL_CONSTANT_COLOR:
445 case GL_ONE_MINUS_CONSTANT_COLOR:
446 case GL_CONSTANT_ALPHA:
447 case GL_ONE_MINUS_CONSTANT_ALPHA:
448 break;
449 case GL_SRC_ALPHA_SATURATE:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400450 break;
451 default:
452 return error(GL_INVALID_ENUM);
453 }
454
Chris Forbes108f3e12018-08-30 19:41:59 -0700455 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400456
457 if(context)
458 {
459 context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
460 }
461}
462
463void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
464{
465 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
466
467 TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = %p, GLenum usage = %d)",
468 target, size, data, usage);
469
470 if(size < 0)
471 {
472 return error(GL_INVALID_VALUE);
473 }
474
Nicolas Capens0bac2852016-05-07 06:09:58 -0400475 switch(usage)
476 {
477 case GL_STREAM_DRAW:
478 case GL_STATIC_DRAW:
479 case GL_DYNAMIC_DRAW:
480 break;
481 case GL_STREAM_READ:
482 case GL_STREAM_COPY:
483 case GL_STATIC_READ:
484 case GL_STATIC_COPY:
485 case GL_DYNAMIC_READ:
486 case GL_DYNAMIC_COPY:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400487 break;
488 default:
489 return error(GL_INVALID_ENUM);
490 }
491
Chris Forbes108f3e12018-08-30 19:41:59 -0700492 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400493
494 if(context)
495 {
496 es2::Buffer *buffer = nullptr;
497 if(!context->getBuffer(target, &buffer))
498 {
499 return error(GL_INVALID_ENUM);
500 }
501
502 if(!buffer)
503 {
504 // A null buffer means that "0" is bound to the requested buffer target
505 return error(GL_INVALID_OPERATION);
506 }
507
508 buffer->bufferData(data, size, usage);
509 }
510}
511
512void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
513{
514 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
515 offset = static_cast<GLint>(offset);
516
517 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = %p)",
518 target, offset, size, data);
519
520 if(size < 0 || offset < 0)
521 {
522 return error(GL_INVALID_VALUE);
523 }
524
Chris Forbes108f3e12018-08-30 19:41:59 -0700525 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400526
527 if(context)
528 {
529 es2::Buffer *buffer = nullptr;
530 if(!context->getBuffer(target, &buffer))
531 {
532 return error(GL_INVALID_ENUM);
533 }
534
535 if(!buffer)
536 {
537 // A null buffer means that "0" is bound to the requested buffer target
538 return error(GL_INVALID_OPERATION);
539 }
540
Alexis Hetu6e864492017-11-14 15:27:00 -0500541 if(buffer->isMapped())
542 {
543 // It is an invalid operation to update an already mapped buffer
544 return error(GL_INVALID_OPERATION);
545 }
546
Nicolas Capens0bac2852016-05-07 06:09:58 -0400547 if((size_t)size + offset > buffer->size())
548 {
549 return error(GL_INVALID_VALUE);
550 }
551
552 buffer->bufferSubData(data, size, offset);
553 }
554}
555
556GLenum CheckFramebufferStatus(GLenum target)
557{
558 TRACE("(GLenum target = 0x%X)", target);
559
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000560 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400561 {
562 return error(GL_INVALID_ENUM, 0);
563 }
564
Chris Forbes108f3e12018-08-30 19:41:59 -0700565 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400566
567 if(context)
568 {
569 es2::Framebuffer *framebuffer = nullptr;
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000570 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400571 {
572 framebuffer = context->getReadFramebuffer();
573 }
574 else
575 {
576 framebuffer = context->getDrawFramebuffer();
577 }
578
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400579 if(!framebuffer)
580 {
581 return GL_FRAMEBUFFER_UNDEFINED_OES;
582 }
583
Nicolas Capens0bac2852016-05-07 06:09:58 -0400584 return framebuffer->completeness();
585 }
586
587 return 0;
588}
589
590void Clear(GLbitfield mask)
591{
592 TRACE("(GLbitfield mask = %X)", mask);
593
594 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
595 {
596 return error(GL_INVALID_VALUE);
597 }
598
Chris Forbes108f3e12018-08-30 19:41:59 -0700599 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400600
601 if(context)
602 {
603 context->clear(mask);
604 }
605}
606
607void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
608{
609 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
610 red, green, blue, alpha);
611
Chris Forbes108f3e12018-08-30 19:41:59 -0700612 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400613
614 if(context)
615 {
616 context->setClearColor(red, green, blue, alpha);
617 }
618}
619
620void ClearDepthf(GLclampf depth)
621{
622 TRACE("(GLclampf depth = %f)", depth);
623
Chris Forbes108f3e12018-08-30 19:41:59 -0700624 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400625
626 if(context)
627 {
628 context->setClearDepth(depth);
629 }
630}
631
632void ClearStencil(GLint s)
633{
634 TRACE("(GLint s = %d)", s);
635
Chris Forbes108f3e12018-08-30 19:41:59 -0700636 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400637
638 if(context)
639 {
640 context->setClearStencil(s);
641 }
642}
643
644void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
645{
646 TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
647 red, green, blue, alpha);
648
Chris Forbes108f3e12018-08-30 19:41:59 -0700649 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400650
651 if(context)
652 {
Nicolas Capens51814272018-10-15 13:01:22 -0400653 context->setColorMask(red != GL_FALSE, green != GL_FALSE, blue != GL_FALSE, alpha != GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400654 }
655}
656
657void CompileShader(GLuint shader)
658{
659 TRACE("(GLuint shader = %d)", shader);
660
Chris Forbes108f3e12018-08-30 19:41:59 -0700661 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400662
663 if(context)
664 {
665 es2::Shader *shaderObject = context->getShader(shader);
666
667 if(!shaderObject)
668 {
669 if(context->getProgram(shader))
670 {
671 return error(GL_INVALID_OPERATION);
672 }
673 else
674 {
675 return error(GL_INVALID_VALUE);
676 }
677 }
678
679 shaderObject->compile();
680 }
681}
682
683void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
684 GLint border, GLsizei imageSize, const GLvoid* data)
685{
686 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
687 "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
688 target, level, internalformat, width, height, border, imageSize, data);
689
690 if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)
691 {
692 return error(GL_INVALID_VALUE);
693 }
694
Nicolas Capens83463112018-06-12 23:55:16 -0400695 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400696 {
Nicolas Capens03589982018-02-01 17:28:32 -0500697 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400698 }
699
700 if(border != 0)
701 {
702 return error(GL_INVALID_VALUE);
703 }
704
Chris Forbes108f3e12018-08-30 19:41:59 -0700705 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400706
707 if(context)
708 {
709 if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
710 {
711 return error(GL_INVALID_VALUE);
712 }
713
714 switch(target)
715 {
716 case GL_TEXTURE_2D:
717 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
718 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
719 {
720 return error(GL_INVALID_VALUE);
721 }
722 break;
723 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
724 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
725 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
726 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
727 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
728 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
729 if(width != height)
730 {
731 return error(GL_INVALID_VALUE);
732 }
733
734 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
735 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
736 {
737 return error(GL_INVALID_VALUE);
738 }
739 break;
Alexis Hetu0988fb82018-02-02 17:23:48 -0500740 case GL_TEXTURE_RECTANGLE_ARB: // Rectangle textures cannot be compressed
Nicolas Capens0bac2852016-05-07 06:09:58 -0400741 default:
742 return error(GL_INVALID_ENUM);
743 }
744
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500745 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400746 {
747 return error(GL_INVALID_VALUE);
748 }
749
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500750 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500751 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500752 {
753 return error(validationError);
754 }
755
Alexis Hetu46768622018-01-16 22:09:28 -0500756 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400757 {
Alexis Hetu46768622018-01-16 22:09:28 -0500758 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400759
760 if(!texture)
761 {
762 return error(GL_INVALID_OPERATION);
763 }
764
765 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
766 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500767 else if(es2::IsCubemapTextureTarget(target))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400768 {
769 es2::TextureCubeMap *texture = context->getTextureCubeMap();
770
771 if(!texture)
772 {
773 return error(GL_INVALID_OPERATION);
774 }
775
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500776 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400777 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500778 else UNREACHABLE(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400779 }
780}
781
782void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
783 GLenum format, GLsizei imageSize, const GLvoid* data)
784{
785 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
786 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
787 "GLsizei imageSize = %d, const GLvoid* data = %p)",
788 target, level, xoffset, yoffset, width, height, format, imageSize, data);
789
790 if(!es2::IsTextureTarget(target))
791 {
792 return error(GL_INVALID_ENUM);
793 }
794
795 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
796 {
797 return error(GL_INVALID_VALUE);
798 }
799
800 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
801 {
802 return error(GL_INVALID_VALUE);
803 }
804
Merck Hung9b768842018-10-16 14:28:26 +0900805 if(!IsCompressed(format))
806 {
807 return error(GL_INVALID_ENUM);
808 }
809
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500810 if(imageSize != gl::ComputeCompressedSize(width, height, format))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400811 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500812 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400813 }
814
Chris Forbes108f3e12018-08-30 19:41:59 -0700815 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400816
817 if(context)
818 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400819 if(xoffset % 4 != 0 || yoffset % 4 != 0)
820 {
821 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
822 return error(GL_INVALID_OPERATION);
823 }
824
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500825 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500826 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500827 {
828 return error(validationError);
829 }
830
Alexis Hetu46768622018-01-16 22:09:28 -0500831 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400832 {
Alexis Hetu46768622018-01-16 22:09:28 -0500833 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400834
Nicolas Capens83463112018-06-12 23:55:16 -0400835 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -0500836 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400837 {
838 return error(validationError);
839 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500840
Nicolas Capenseab70762018-02-06 16:49:36 -0500841 texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400842 }
843 else if(es2::IsCubemapTextureTarget(target))
844 {
845 es2::TextureCubeMap *texture = context->getTextureCubeMap();
846
Nicolas Capens83463112018-06-12 23:55:16 -0400847 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -0500848 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400849 {
850 return error(validationError);
851 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500852
Nicolas Capenseab70762018-02-06 16:49:36 -0500853 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400854 }
855 else UNREACHABLE(target);
856 }
857}
858
859void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
860{
861 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
862 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
863 target, level, internalformat, x, y, width, height, border);
864
865 if(!validImageSize(level, width, height))
866 {
867 return error(GL_INVALID_VALUE);
868 }
869
870 if(border != 0)
871 {
872 return error(GL_INVALID_VALUE);
873 }
874
Chris Forbes108f3e12018-08-30 19:41:59 -0700875 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400876
877 if(context)
878 {
879 switch(target)
880 {
Alexis Hetu46768622018-01-16 22:09:28 -0500881 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -0500882 if(level != 0)
883 {
884 return error(GL_INVALID_VALUE);
885 }
Nicolas Capens894858a2018-03-22 00:55:23 -0400886 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -0500887 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400888 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
889 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
890 {
891 return error(GL_INVALID_VALUE);
892 }
893 break;
894 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
895 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
896 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
897 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
898 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
899 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
900 if(width != height)
901 {
902 return error(GL_INVALID_VALUE);
903 }
904
905 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
906 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
907 {
908 return error(GL_INVALID_VALUE);
909 }
910 break;
911 default:
912 return error(GL_INVALID_ENUM);
913 }
914
915 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
916
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400917 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400918 {
919 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
920 }
921
922 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
923
924 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
925 {
926 return error(GL_INVALID_OPERATION);
927 }
928
929 GLenum colorbufferFormat = source->getFormat();
930
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500931 // Determine the sized internal format.
932 if(gl::IsUnsizedInternalFormat(internalformat))
933 {
Nicolas Capense1fa9ea2018-07-05 12:13:56 -0400934 if(colorbufferFormat == GL_RGB10_A2)
935 {
936 // Not supported with unsized internalformat.
937 // https://www.khronos.org/members/login/bugzilla/show_bug.cgi?id=9807#c56
938 return error(GL_INVALID_OPERATION);
939 }
940
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500941 if(gl::GetBaseInternalFormat(colorbufferFormat) == internalformat)
942 {
943 internalformat = colorbufferFormat;
944 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400945 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_NORMALIZED && GetRedSize(colorbufferFormat) <= 8)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500946 {
Nicolas Capens667ab102018-03-22 13:22:20 -0400947 // TODO: Convert to the smallest format that fits all components.
948 // e.g. Copying RGBA4 to RGB should result in RGB565, not RGB8.
949
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500950 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_BYTE);
951 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400952 else if(GetColorComponentType(colorbufferFormat) == GL_INT)
953 {
954 internalformat = gl::GetSizedInternalFormat(internalformat, GL_INT);
955 }
956 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_INT)
957 {
958 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_INT);
959 }
960 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 16) // GL_EXT_color_buffer_half_float
961 {
962 internalformat = gl::GetSizedInternalFormat(internalformat, GL_HALF_FLOAT_OES);
963 }
Nicolas Capens659d89e2018-06-22 13:57:37 -0400964 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 32) // GL_EXT_color_buffer_float
965 {
966 internalformat = gl::GetSizedInternalFormat(internalformat, GL_FLOAT);
967 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500968 else
969 {
Nicolas Capensa5dfd972018-09-28 15:27:08 -0400970 UNIMPLEMENTED("internalformat = %x, colorbufferFormat = %X", internalformat, colorbufferFormat);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500971
972 return error(GL_INVALID_OPERATION);
973 }
974 }
975
Nicolas Capens8f215a42018-02-02 13:25:53 -0500976 if(!ValidateCopyFormats(internalformat, colorbufferFormat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400977 {
978 return;
979 }
980
Alexis Hetu46768622018-01-16 22:09:28 -0500981 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400982 {
Alexis Hetu46768622018-01-16 22:09:28 -0500983 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400984
985 if(!texture)
986 {
987 return error(GL_INVALID_OPERATION);
988 }
989
Nicolas Capens1529c2c2018-02-06 14:44:47 -0500990 texture->copyImage(level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400991 }
992 else if(es2::IsCubemapTextureTarget(target))
993 {
994 es2::TextureCubeMap *texture = context->getTextureCubeMap();
995
996 if(!texture)
997 {
998 return error(GL_INVALID_OPERATION);
999 }
1000
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001001 texture->copyImage(target, level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001002 }
1003 else UNREACHABLE(target);
1004 }
1005}
1006
1007void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1008{
1009 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1010 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1011 target, level, xoffset, yoffset, x, y, width, height);
1012
1013 if(!es2::IsTextureTarget(target))
1014 {
1015 return error(GL_INVALID_ENUM);
1016 }
1017
1018 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1019 {
1020 return error(GL_INVALID_VALUE);
1021 }
1022
1023 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1024 {
1025 return error(GL_INVALID_VALUE);
1026 }
1027
1028 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1029 {
1030 return error(GL_INVALID_VALUE);
1031 }
1032
Chris Forbes108f3e12018-08-30 19:41:59 -07001033 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001034
1035 if(context)
1036 {
1037 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1038
Alexis Hetu5cd502b2018-03-22 08:29:31 -04001039 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001040 {
1041 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1042 }
1043
1044 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1045
1046 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1047 {
1048 return error(GL_INVALID_OPERATION);
1049 }
1050
1051 es2::Texture *texture = nullptr;
1052
Alexis Hetu46768622018-01-16 22:09:28 -05001053 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001054 {
Alexis Hetu46768622018-01-16 22:09:28 -05001055 texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001056 }
1057 else if(es2::IsCubemapTextureTarget(target))
1058 {
1059 texture = context->getTextureCubeMap();
1060 }
1061 else UNREACHABLE(target);
1062
Nicolas Capens83463112018-06-12 23:55:16 -04001063 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05001064 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001065 {
1066 return error(validationError);
1067 }
1068
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001069 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001070 }
1071}
1072
1073GLuint CreateProgram(void)
1074{
1075 TRACE("()");
1076
Chris Forbes108f3e12018-08-30 19:41:59 -07001077 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001078
1079 if(context)
1080 {
1081 return context->createProgram();
1082 }
1083
1084 return 0;
1085}
1086
1087GLuint CreateShader(GLenum type)
1088{
1089 TRACE("(GLenum type = 0x%X)", type);
1090
Chris Forbes108f3e12018-08-30 19:41:59 -07001091 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001092
1093 if(context)
1094 {
1095 switch(type)
1096 {
1097 case GL_FRAGMENT_SHADER:
1098 case GL_VERTEX_SHADER:
1099 return context->createShader(type);
1100 default:
1101 return error(GL_INVALID_ENUM, 0);
1102 }
1103 }
1104
1105 return 0;
1106}
1107
1108void CullFace(GLenum mode)
1109{
1110 TRACE("(GLenum mode = 0x%X)", mode);
1111
1112 switch(mode)
1113 {
1114 case GL_FRONT:
1115 case GL_BACK:
1116 case GL_FRONT_AND_BACK:
1117 {
Chris Forbes108f3e12018-08-30 19:41:59 -07001118 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001119
1120 if(context)
1121 {
1122 context->setCullMode(mode);
1123 }
1124 }
1125 break;
1126 default:
1127 return error(GL_INVALID_ENUM);
1128 }
1129}
1130
1131void DeleteBuffers(GLsizei n, const GLuint* buffers)
1132{
1133 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1134
1135 if(n < 0)
1136 {
1137 return error(GL_INVALID_VALUE);
1138 }
1139
Chris Forbes108f3e12018-08-30 19:41:59 -07001140 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001141
1142 if(context)
1143 {
1144 for(int i = 0; i < n; i++)
1145 {
1146 context->deleteBuffer(buffers[i]);
1147 }
1148 }
1149}
1150
1151void DeleteFencesNV(GLsizei n, const GLuint* fences)
1152{
1153 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1154
1155 if(n < 0)
1156 {
1157 return error(GL_INVALID_VALUE);
1158 }
1159
Chris Forbes108f3e12018-08-30 19:41:59 -07001160 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001161
1162 if(context)
1163 {
1164 for(int i = 0; i < n; i++)
1165 {
1166 context->deleteFence(fences[i]);
1167 }
1168 }
1169}
1170
1171void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1172{
1173 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1174
1175 if(n < 0)
1176 {
1177 return error(GL_INVALID_VALUE);
1178 }
1179
Chris Forbes108f3e12018-08-30 19:41:59 -07001180 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001181
1182 if(context)
1183 {
1184 for(int i = 0; i < n; i++)
1185 {
Nicolas Capens56eacf02018-09-27 13:54:27 -04001186 if(framebuffers[i] != 0) // Attempts to delete default framebuffer silently ignored.
Nicolas Capens0bac2852016-05-07 06:09:58 -04001187 {
1188 context->deleteFramebuffer(framebuffers[i]);
1189 }
1190 }
1191 }
1192}
1193
1194void DeleteProgram(GLuint program)
1195{
1196 TRACE("(GLuint program = %d)", program);
1197
1198 if(program == 0)
1199 {
1200 return;
1201 }
1202
Chris Forbes108f3e12018-08-30 19:41:59 -07001203 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001204
1205 if(context)
1206 {
1207 if(!context->getProgram(program))
1208 {
1209 if(context->getShader(program))
1210 {
1211 return error(GL_INVALID_OPERATION);
1212 }
1213 else
1214 {
1215 return error(GL_INVALID_VALUE);
1216 }
1217 }
1218
1219 context->deleteProgram(program);
1220 }
1221}
1222
1223void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
1224{
1225 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1226
1227 if(n < 0)
1228 {
1229 return error(GL_INVALID_VALUE);
1230 }
1231
Chris Forbes108f3e12018-08-30 19:41:59 -07001232 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001233
1234 if(context)
1235 {
1236 for(int i = 0; i < n; i++)
1237 {
1238 context->deleteQuery(ids[i]);
1239 }
1240 }
1241}
1242
1243void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1244{
1245 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1246
1247 if(n < 0)
1248 {
1249 return error(GL_INVALID_VALUE);
1250 }
1251
Chris Forbes108f3e12018-08-30 19:41:59 -07001252 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001253
1254 if(context)
1255 {
1256 for(int i = 0; i < n; i++)
1257 {
1258 context->deleteRenderbuffer(renderbuffers[i]);
1259 }
1260 }
1261}
1262
1263void DeleteShader(GLuint shader)
1264{
1265 TRACE("(GLuint shader = %d)", shader);
1266
1267 if(shader == 0)
1268 {
1269 return;
1270 }
1271
Chris Forbes108f3e12018-08-30 19:41:59 -07001272 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001273
1274 if(context)
1275 {
1276 if(!context->getShader(shader))
1277 {
1278 if(context->getProgram(shader))
1279 {
1280 return error(GL_INVALID_OPERATION);
1281 }
1282 else
1283 {
1284 return error(GL_INVALID_VALUE);
1285 }
1286 }
1287
1288 context->deleteShader(shader);
1289 }
1290}
1291
1292void DeleteTextures(GLsizei n, const GLuint* textures)
1293{
1294 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1295
1296 if(n < 0)
1297 {
1298 return error(GL_INVALID_VALUE);
1299 }
1300
Chris Forbes108f3e12018-08-30 19:41:59 -07001301 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001302
1303 if(context)
1304 {
1305 for(int i = 0; i < n; i++)
1306 {
Nicolas Capens56eacf02018-09-27 13:54:27 -04001307 if(textures[i] != 0) // Attempts to delete default texture silently ignored.
Nicolas Capens0bac2852016-05-07 06:09:58 -04001308 {
1309 context->deleteTexture(textures[i]);
1310 }
1311 }
1312 }
1313}
1314
1315void DepthFunc(GLenum func)
1316{
1317 TRACE("(GLenum func = 0x%X)", func);
1318
1319 switch(func)
1320 {
1321 case GL_NEVER:
1322 case GL_ALWAYS:
1323 case GL_LESS:
1324 case GL_LEQUAL:
1325 case GL_EQUAL:
1326 case GL_GREATER:
1327 case GL_GEQUAL:
1328 case GL_NOTEQUAL:
1329 break;
1330 default:
1331 return error(GL_INVALID_ENUM);
1332 }
1333
Chris Forbes108f3e12018-08-30 19:41:59 -07001334 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001335
1336 if(context)
1337 {
1338 context->setDepthFunc(func);
1339 }
1340}
1341
1342void DepthMask(GLboolean flag)
1343{
1344 TRACE("(GLboolean flag = %d)", flag);
1345
Chris Forbes108f3e12018-08-30 19:41:59 -07001346 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001347
1348 if(context)
1349 {
1350 context->setDepthMask(flag != GL_FALSE);
1351 }
1352}
1353
1354void DepthRangef(GLclampf zNear, GLclampf zFar)
1355{
1356 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1357
Chris Forbes108f3e12018-08-30 19:41:59 -07001358 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001359
1360 if(context)
1361 {
1362 context->setDepthRange(zNear, zFar);
1363 }
1364}
1365
1366void DetachShader(GLuint program, GLuint shader)
1367{
1368 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1369
Chris Forbes108f3e12018-08-30 19:41:59 -07001370 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001371
1372 if(context)
1373 {
1374
1375 es2::Program *programObject = context->getProgram(program);
1376 es2::Shader *shaderObject = context->getShader(shader);
1377
1378 if(!programObject)
1379 {
1380 es2::Shader *shaderByProgramHandle;
1381 shaderByProgramHandle = context->getShader(program);
1382 if(!shaderByProgramHandle)
1383 {
1384 return error(GL_INVALID_VALUE);
1385 }
1386 else
1387 {
1388 return error(GL_INVALID_OPERATION);
1389 }
1390 }
1391
1392 if(!shaderObject)
1393 {
1394 es2::Program *programByShaderHandle = context->getProgram(shader);
1395 if(!programByShaderHandle)
1396 {
1397 return error(GL_INVALID_VALUE);
1398 }
1399 else
1400 {
1401 return error(GL_INVALID_OPERATION);
1402 }
1403 }
1404
1405 if(!programObject->detachShader(shaderObject))
1406 {
1407 return error(GL_INVALID_OPERATION);
1408 }
1409 }
1410}
1411
1412void Disable(GLenum cap)
1413{
1414 TRACE("(GLenum cap = 0x%X)", cap);
1415
Chris Forbes108f3e12018-08-30 19:41:59 -07001416 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001417
1418 if(context)
1419 {
1420 switch(cap)
1421 {
1422 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1423 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1424 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1425 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1426 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1427 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1428 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1429 case GL_BLEND: context->setBlendEnabled(false); break;
1430 case GL_DITHER: context->setDitherEnabled(false); break;
1431 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1432 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1433 default:
1434 return error(GL_INVALID_ENUM);
1435 }
1436 }
1437}
1438
1439void DisableVertexAttribArray(GLuint index)
1440{
1441 TRACE("(GLuint index = %d)", index);
1442
1443 if(index >= es2::MAX_VERTEX_ATTRIBS)
1444 {
1445 return error(GL_INVALID_VALUE);
1446 }
1447
Chris Forbes108f3e12018-08-30 19:41:59 -07001448 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001449
1450 if(context)
1451 {
1452 context->setVertexAttribArrayEnabled(index, false);
1453 }
1454}
1455
1456void DrawArrays(GLenum mode, GLint first, GLsizei count)
1457{
1458 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1459
1460 switch(mode)
1461 {
1462 case GL_POINTS:
1463 case GL_LINES:
1464 case GL_LINE_LOOP:
1465 case GL_LINE_STRIP:
1466 case GL_TRIANGLES:
1467 case GL_TRIANGLE_FAN:
1468 case GL_TRIANGLE_STRIP:
1469 break;
1470 default:
1471 return error(GL_INVALID_ENUM);
1472 }
1473
1474 if(count < 0 || first < 0)
1475 {
1476 return error(GL_INVALID_VALUE);
1477 }
1478
Chris Forbes108f3e12018-08-30 19:41:59 -07001479 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001480
1481 if(context)
1482 {
1483 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1484 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1485 {
1486 return error(GL_INVALID_OPERATION);
1487 }
1488
1489 context->drawArrays(mode, first, count);
1490 }
1491}
1492
1493void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1494{
1495 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1496 mode, count, type, indices);
1497
1498 switch(mode)
1499 {
1500 case GL_POINTS:
1501 case GL_LINES:
1502 case GL_LINE_LOOP:
1503 case GL_LINE_STRIP:
1504 case GL_TRIANGLES:
1505 case GL_TRIANGLE_FAN:
1506 case GL_TRIANGLE_STRIP:
1507 break;
1508 default:
1509 return error(GL_INVALID_ENUM);
1510 }
1511
1512 if(count < 0)
1513 {
1514 return error(GL_INVALID_VALUE);
1515 }
1516
Chris Forbes108f3e12018-08-30 19:41:59 -07001517 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001518
1519 if(context)
1520 {
1521 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1522 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1523 {
1524 return error(GL_INVALID_OPERATION);
1525 }
1526
1527 switch(type)
1528 {
1529 case GL_UNSIGNED_BYTE:
1530 case GL_UNSIGNED_SHORT:
1531 case GL_UNSIGNED_INT:
1532 break;
1533 default:
1534 return error(GL_INVALID_ENUM);
1535 }
1536
1537 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1538 }
1539}
1540
1541void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1542{
1543 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1544 mode, first, count, instanceCount);
1545
1546 switch(mode)
1547 {
1548 case GL_POINTS:
1549 case GL_LINES:
1550 case GL_LINE_LOOP:
1551 case GL_LINE_STRIP:
1552 case GL_TRIANGLES:
1553 case GL_TRIANGLE_FAN:
1554 case GL_TRIANGLE_STRIP:
1555 break;
1556 default:
1557 return error(GL_INVALID_ENUM);
1558 }
1559
1560 if(count < 0 || instanceCount < 0)
1561 {
1562 return error(GL_INVALID_VALUE);
1563 }
1564
Chris Forbes108f3e12018-08-30 19:41:59 -07001565 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001566
1567 if(context)
1568 {
1569 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1570 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1571 {
1572 return error(GL_INVALID_OPERATION);
1573 }
1574
1575 context->drawArrays(mode, first, count, instanceCount);
1576 }
1577}
1578
1579void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1580{
1581 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1582 mode, count, type, indices, instanceCount);
1583
1584 switch(mode)
1585 {
1586 case GL_POINTS:
1587 case GL_LINES:
1588 case GL_LINE_LOOP:
1589 case GL_LINE_STRIP:
1590 case GL_TRIANGLES:
1591 case GL_TRIANGLE_FAN:
1592 case GL_TRIANGLE_STRIP:
1593 break;
1594 default:
1595 return error(GL_INVALID_ENUM);
1596 }
1597
1598 switch(type)
1599 {
1600 case GL_UNSIGNED_BYTE:
1601 case GL_UNSIGNED_SHORT:
1602 case GL_UNSIGNED_INT:
1603 break;
1604 default:
1605 return error(GL_INVALID_ENUM);
1606 }
1607
1608 if(count < 0 || instanceCount < 0)
1609 {
1610 return error(GL_INVALID_VALUE);
1611 }
1612
Chris Forbes108f3e12018-08-30 19:41:59 -07001613 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001614
1615 if(context)
1616 {
1617 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1618 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1619 {
1620 return error(GL_INVALID_OPERATION);
1621 }
1622
1623 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1624 }
1625}
1626
1627void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
1628{
1629 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1630
Chris Forbes108f3e12018-08-30 19:41:59 -07001631 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001632
1633 if(context)
1634 {
1635 if(index >= es2::MAX_VERTEX_ATTRIBS)
1636 {
1637 return error(GL_INVALID_VALUE);
1638 }
1639
1640 context->setVertexAttribDivisor(index, divisor);
1641 }
1642}
1643
1644void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1645{
1646 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1647 mode, first, count, instanceCount);
1648
1649 switch(mode)
1650 {
1651 case GL_POINTS:
1652 case GL_LINES:
1653 case GL_LINE_LOOP:
1654 case GL_LINE_STRIP:
1655 case GL_TRIANGLES:
1656 case GL_TRIANGLE_FAN:
1657 case GL_TRIANGLE_STRIP:
1658 break;
1659 default:
1660 return error(GL_INVALID_ENUM);
1661 }
1662
1663 if(count < 0 || instanceCount < 0)
1664 {
1665 return error(GL_INVALID_VALUE);
1666 }
1667
Chris Forbes108f3e12018-08-30 19:41:59 -07001668 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001669
1670 if(context)
1671 {
1672 if(!context->hasZeroDivisor())
1673 {
1674 return error(GL_INVALID_OPERATION);
1675 }
1676
1677 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1678 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1679 {
1680 return error(GL_INVALID_OPERATION);
1681 }
1682
1683 context->drawArrays(mode, first, count, instanceCount);
1684 }
1685}
1686
1687void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1688{
1689 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1690 mode, count, type, indices, instanceCount);
1691
1692 switch(mode)
1693 {
1694 case GL_POINTS:
1695 case GL_LINES:
1696 case GL_LINE_LOOP:
1697 case GL_LINE_STRIP:
1698 case GL_TRIANGLES:
1699 case GL_TRIANGLE_FAN:
1700 case GL_TRIANGLE_STRIP:
1701 break;
1702 default:
1703 return error(GL_INVALID_ENUM);
1704 }
1705
1706 switch(type)
1707 {
1708 case GL_UNSIGNED_BYTE:
1709 case GL_UNSIGNED_SHORT:
1710 case GL_UNSIGNED_INT:
1711 break;
1712 default:
1713 return error(GL_INVALID_ENUM);
1714 }
1715
1716 if(count < 0 || instanceCount < 0)
1717 {
1718 return error(GL_INVALID_VALUE);
1719 }
1720
Chris Forbes108f3e12018-08-30 19:41:59 -07001721 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001722
1723 if(context)
1724 {
1725 if(!context->hasZeroDivisor())
1726 {
1727 return error(GL_INVALID_OPERATION);
1728 }
1729
1730 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1731 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1732 {
1733 return error(GL_INVALID_OPERATION);
1734 }
1735
1736 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1737 }
1738}
1739
1740void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
1741{
1742 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1743
Chris Forbes108f3e12018-08-30 19:41:59 -07001744 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001745
1746 if(context)
1747 {
1748 if(index >= MAX_VERTEX_ATTRIBS)
1749 {
1750 return error(GL_INVALID_VALUE);
1751 }
1752
1753 context->setVertexAttribDivisor(index, divisor);
1754 }
1755}
1756
1757void Enable(GLenum cap)
1758{
1759 TRACE("(GLenum cap = 0x%X)", cap);
1760
Chris Forbes108f3e12018-08-30 19:41:59 -07001761 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001762
1763 if(context)
1764 {
1765 switch(cap)
1766 {
1767 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1768 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1769 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1770 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1771 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1772 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1773 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1774 case GL_BLEND: context->setBlendEnabled(true); break;
1775 case GL_DITHER: context->setDitherEnabled(true); break;
1776 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1777 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1778 default:
1779 return error(GL_INVALID_ENUM);
1780 }
1781 }
1782}
1783
1784void EnableVertexAttribArray(GLuint index)
1785{
1786 TRACE("(GLuint index = %d)", index);
1787
1788 if(index >= es2::MAX_VERTEX_ATTRIBS)
1789 {
1790 return error(GL_INVALID_VALUE);
1791 }
1792
Chris Forbes108f3e12018-08-30 19:41:59 -07001793 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001794
1795 if(context)
1796 {
1797 context->setVertexAttribArrayEnabled(index, true);
1798 }
1799}
1800
1801void EndQueryEXT(GLenum target)
1802{
1803 TRACE("GLenum target = 0x%X)", target);
1804
1805 switch(target)
1806 {
1807 case GL_ANY_SAMPLES_PASSED_EXT:
1808 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1809 break;
1810 default:
1811 return error(GL_INVALID_ENUM);
1812 }
1813
Chris Forbes108f3e12018-08-30 19:41:59 -07001814 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001815
1816 if(context)
1817 {
1818 context->endQuery(target);
1819 }
1820}
1821
1822void FinishFenceNV(GLuint fence)
1823{
1824 TRACE("(GLuint fence = %d)", fence);
1825
Chris Forbes108f3e12018-08-30 19:41:59 -07001826 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001827
1828 if(context)
1829 {
1830 es2::Fence *fenceObject = context->getFence(fence);
1831
1832 if(!fenceObject)
1833 {
1834 return error(GL_INVALID_OPERATION);
1835 }
1836
1837 fenceObject->finishFence();
1838 }
1839}
1840
1841void Finish(void)
1842{
1843 TRACE("()");
1844
Chris Forbes108f3e12018-08-30 19:41:59 -07001845 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001846
1847 if(context)
1848 {
1849 context->finish();
1850 }
1851}
1852
1853void Flush(void)
1854{
1855 TRACE("()");
1856
Chris Forbes108f3e12018-08-30 19:41:59 -07001857 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001858
1859 if(context)
1860 {
1861 context->flush();
1862 }
1863}
1864
1865void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1866{
1867 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1868 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1869
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001870 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -04001871 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1872 {
1873 return error(GL_INVALID_ENUM);
1874 }
1875
Chris Forbes108f3e12018-08-30 19:41:59 -07001876 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001877
1878 if(context)
1879 {
1880 es2::Framebuffer *framebuffer = nullptr;
1881 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001882 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001883 {
1884 framebuffer = context->getReadFramebuffer();
1885 framebufferName = context->getReadFramebufferName();
1886 }
1887 else
1888 {
1889 framebuffer = context->getDrawFramebuffer();
1890 framebufferName = context->getDrawFramebufferName();
1891 }
1892
1893 if(!framebuffer || framebufferName == 0)
1894 {
1895 return error(GL_INVALID_OPERATION);
1896 }
1897
1898 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1899 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1900 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1901 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1902 if(renderbuffer != 0)
1903 {
1904 if(!context->getRenderbuffer(renderbuffer))
1905 {
1906 return error(GL_INVALID_OPERATION);
1907 }
1908 }
1909
Nicolas Capens0bac2852016-05-07 06:09:58 -04001910 switch(attachment)
1911 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001912 case GL_DEPTH_ATTACHMENT:
1913 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1914 break;
1915 case GL_STENCIL_ATTACHMENT:
1916 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1917 break;
1918 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capens83463112018-06-12 23:55:16 -04001919 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1920 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1921 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001922 default:
Nicolas Capens83463112018-06-12 23:55:16 -04001923 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
1924 {
1925 return error(GL_INVALID_ENUM);
1926 }
1927 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
1928 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001929 }
1930 }
1931}
1932
1933void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1934{
1935 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1936 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1937
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001938 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001939 {
1940 return error(GL_INVALID_ENUM);
1941 }
1942
Chris Forbes108f3e12018-08-30 19:41:59 -07001943 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001944
1945 if(context)
1946 {
1947 if(texture == 0)
1948 {
1949 textarget = GL_NONE;
1950 }
1951 else
1952 {
1953 es2::Texture *tex = context->getTexture(texture);
1954
1955 if(!tex)
1956 {
1957 return error(GL_INVALID_OPERATION);
1958 }
1959
1960 switch(textarget)
1961 {
1962 case GL_TEXTURE_2D:
1963 if(tex->getTarget() != GL_TEXTURE_2D)
1964 {
1965 return error(GL_INVALID_OPERATION);
1966 }
1967 break;
Alexis Hetu46768622018-01-16 22:09:28 -05001968 case GL_TEXTURE_RECTANGLE_ARB:
1969 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
1970 {
1971 return error(GL_INVALID_OPERATION);
1972 }
1973 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001974 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1975 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1976 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1977 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1978 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1979 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1980 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
1981 {
1982 return error(GL_INVALID_OPERATION);
1983 }
1984 break;
1985 default:
1986 return error(GL_INVALID_ENUM);
1987 }
1988
Nicolas Capens83463112018-06-12 23:55:16 -04001989 if((textarget == GL_TEXTURE_RECTANGLE_ARB) && (level != 0))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001990 {
1991 return error(GL_INVALID_VALUE);
1992 }
1993
1994 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
1995 {
1996 return error(GL_INVALID_VALUE);
1997 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04001998
1999 if(tex->isCompressed(textarget, level))
2000 {
2001 return error(GL_INVALID_OPERATION);
2002 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002003 }
2004
2005 es2::Framebuffer *framebuffer = nullptr;
2006 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002007 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002008 {
2009 framebuffer = context->getReadFramebuffer();
2010 framebufferName = context->getReadFramebufferName();
2011 }
2012 else
2013 {
2014 framebuffer = context->getDrawFramebuffer();
2015 framebufferName = context->getDrawFramebufferName();
2016 }
2017
2018 if(framebufferName == 0 || !framebuffer)
2019 {
2020 return error(GL_INVALID_OPERATION);
2021 }
2022
2023 switch(attachment)
2024 {
Nicolas Capens83463112018-06-12 23:55:16 -04002025 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2026 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
2027 case GL_DEPTH_STENCIL_ATTACHMENT:
2028 framebuffer->setDepthbuffer(textarget, texture, level);
2029 framebuffer->setStencilbuffer(textarget, texture, level);
2030 break;
2031 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002032 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2033 {
2034 return error(GL_INVALID_ENUM);
2035 }
2036 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2037 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002038 }
2039 }
2040}
2041
2042void FrontFace(GLenum mode)
2043{
2044 TRACE("(GLenum mode = 0x%X)", mode);
2045
2046 switch(mode)
2047 {
2048 case GL_CW:
2049 case GL_CCW:
2050 {
Chris Forbes108f3e12018-08-30 19:41:59 -07002051 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002052
2053 if(context)
2054 {
2055 context->setFrontFace(mode);
2056 }
2057 }
2058 break;
2059 default:
2060 return error(GL_INVALID_ENUM);
2061 }
2062}
2063
2064void GenBuffers(GLsizei n, GLuint* buffers)
2065{
2066 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2067
2068 if(n < 0)
2069 {
2070 return error(GL_INVALID_VALUE);
2071 }
2072
Chris Forbes108f3e12018-08-30 19:41:59 -07002073 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002074
2075 if(context)
2076 {
2077 for(int i = 0; i < n; i++)
2078 {
2079 buffers[i] = context->createBuffer();
2080 }
2081 }
2082}
2083
2084void GenerateMipmap(GLenum target)
2085{
2086 TRACE("(GLenum target = 0x%X)", target);
2087
Chris Forbes108f3e12018-08-30 19:41:59 -07002088 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002089
2090 if(context)
2091 {
2092 es2::Texture *texture = nullptr;
2093
Nicolas Capens0bac2852016-05-07 06:09:58 -04002094 switch(target)
2095 {
2096 case GL_TEXTURE_2D:
2097 texture = context->getTexture2D();
2098 break;
2099 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002100 {
2101 TextureCubeMap *cube = context->getTextureCubeMap();
2102 texture = cube;
2103
2104 if(!cube->isCubeComplete())
2105 {
2106 return error(GL_INVALID_OPERATION);
2107 }
2108 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002109 break;
2110 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens83463112018-06-12 23:55:16 -04002111 texture = context->getTexture2DArray();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002112 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002113 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002114 texture = context->getTexture3D();
2115 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002116 case GL_TEXTURE_RECTANGLE_ARB:
2117 texture = context->getTexture2DRect();
2118 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002119 default:
2120 return error(GL_INVALID_ENUM);
2121 }
2122
Nicolas Capens83463112018-06-12 23:55:16 -04002123 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel())))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002124 {
2125 return error(GL_INVALID_OPERATION);
2126 }
2127
Nicolas Capens0bac2852016-05-07 06:09:58 -04002128 texture->generateMipmaps();
2129 }
2130}
2131
2132void GenFencesNV(GLsizei n, GLuint* fences)
2133{
2134 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2135
2136 if(n < 0)
2137 {
2138 return error(GL_INVALID_VALUE);
2139 }
2140
Chris Forbes108f3e12018-08-30 19:41:59 -07002141 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002142
2143 if(context)
2144 {
2145 for(int i = 0; i < n; i++)
2146 {
2147 fences[i] = context->createFence();
2148 }
2149 }
2150}
2151
2152void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2153{
2154 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2155
2156 if(n < 0)
2157 {
2158 return error(GL_INVALID_VALUE);
2159 }
2160
Chris Forbes108f3e12018-08-30 19:41:59 -07002161 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002162
2163 if(context)
2164 {
2165 for(int i = 0; i < n; i++)
2166 {
2167 framebuffers[i] = context->createFramebuffer();
2168 }
2169 }
2170}
2171
2172void GenQueriesEXT(GLsizei n, GLuint* ids)
2173{
2174 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2175
2176 if(n < 0)
2177 {
2178 return error(GL_INVALID_VALUE);
2179 }
2180
Chris Forbes108f3e12018-08-30 19:41:59 -07002181 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002182
2183 if(context)
2184 {
2185 for(int i = 0; i < n; i++)
2186 {
2187 ids[i] = context->createQuery();
2188 }
2189 }
2190}
2191
2192void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2193{
2194 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2195
2196 if(n < 0)
2197 {
2198 return error(GL_INVALID_VALUE);
2199 }
2200
Chris Forbes108f3e12018-08-30 19:41:59 -07002201 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002202
2203 if(context)
2204 {
2205 for(int i = 0; i < n; i++)
2206 {
2207 renderbuffers[i] = context->createRenderbuffer();
2208 }
2209 }
2210}
2211
2212void GenTextures(GLsizei n, GLuint* textures)
2213{
2214 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2215
2216 if(n < 0)
2217 {
2218 return error(GL_INVALID_VALUE);
2219 }
2220
Chris Forbes108f3e12018-08-30 19:41:59 -07002221 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002222
2223 if(context)
2224 {
2225 for(int i = 0; i < n; i++)
2226 {
2227 textures[i] = context->createTexture();
2228 }
2229 }
2230}
2231
2232void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2233{
2234 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2235 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2236 program, index, bufsize, length, size, type, name);
2237
2238 if(bufsize < 0)
2239 {
2240 return error(GL_INVALID_VALUE);
2241 }
2242
Chris Forbes108f3e12018-08-30 19:41:59 -07002243 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002244
2245 if(context)
2246 {
2247 es2::Program *programObject = context->getProgram(program);
2248
2249 if(!programObject)
2250 {
2251 if(context->getShader(program))
2252 {
2253 return error(GL_INVALID_OPERATION);
2254 }
2255 else
2256 {
2257 return error(GL_INVALID_VALUE);
2258 }
2259 }
2260
2261 if(index >= programObject->getActiveAttributeCount())
2262 {
2263 return error(GL_INVALID_VALUE);
2264 }
2265
2266 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2267 }
2268}
2269
2270void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2271{
2272 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2273 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2274 program, index, bufsize, length, size, type, name);
2275
2276 if(bufsize < 0)
2277 {
2278 return error(GL_INVALID_VALUE);
2279 }
2280
Chris Forbes108f3e12018-08-30 19:41:59 -07002281 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002282
2283 if(context)
2284 {
2285 es2::Program *programObject = context->getProgram(program);
2286
2287 if(!programObject)
2288 {
2289 if(context->getShader(program))
2290 {
2291 return error(GL_INVALID_OPERATION);
2292 }
2293 else
2294 {
2295 return error(GL_INVALID_VALUE);
2296 }
2297 }
2298
2299 if(index >= programObject->getActiveUniformCount())
2300 {
2301 return error(GL_INVALID_VALUE);
2302 }
2303
2304 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2305 }
2306}
2307
2308void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2309{
2310 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2311 program, maxcount, count, shaders);
2312
2313 if(maxcount < 0)
2314 {
2315 return error(GL_INVALID_VALUE);
2316 }
2317
Chris Forbes108f3e12018-08-30 19:41:59 -07002318 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002319
2320 if(context)
2321 {
2322 es2::Program *programObject = context->getProgram(program);
2323
2324 if(!programObject)
2325 {
2326 if(context->getShader(program))
2327 {
2328 return error(GL_INVALID_OPERATION);
2329 }
2330 else
2331 {
2332 return error(GL_INVALID_VALUE);
2333 }
2334 }
2335
2336 return programObject->getAttachedShaders(maxcount, count, shaders);
2337 }
2338}
2339
2340int GetAttribLocation(GLuint program, const GLchar* name)
2341{
2342 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2343
Chris Forbes108f3e12018-08-30 19:41:59 -07002344 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002345
2346 if(context)
2347 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04002348 es2::Program *programObject = context->getProgram(program);
2349
2350 if(!programObject)
2351 {
2352 if(context->getShader(program))
2353 {
2354 return error(GL_INVALID_OPERATION, -1);
2355 }
2356 else
2357 {
2358 return error(GL_INVALID_VALUE, -1);
2359 }
2360 }
2361
2362 if(!programObject->isLinked())
2363 {
2364 return error(GL_INVALID_OPERATION, -1);
2365 }
2366
2367 return programObject->getAttributeLocation(name);
2368 }
2369
2370 return -1;
2371}
2372
2373void GetBooleanv(GLenum pname, GLboolean* params)
2374{
2375 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2376
Chris Forbes108f3e12018-08-30 19:41:59 -07002377 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002378
2379 if(context)
2380 {
2381 if(!(context->getBooleanv(pname, params)))
2382 {
2383 GLenum nativeType;
2384 unsigned int numParams = 0;
2385 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2386 return error(GL_INVALID_ENUM);
2387
2388 if(numParams == 0)
2389 return; // it is known that the pname is valid, but there are no parameters to return
2390
2391 if(nativeType == GL_FLOAT)
2392 {
2393 GLfloat *floatParams = nullptr;
2394 floatParams = new GLfloat[numParams];
2395
2396 context->getFloatv(pname, floatParams);
2397
2398 for(unsigned int i = 0; i < numParams; ++i)
2399 {
2400 if(floatParams[i] == 0.0f)
2401 params[i] = GL_FALSE;
2402 else
2403 params[i] = GL_TRUE;
2404 }
2405
2406 delete [] floatParams;
2407 }
2408 else if(nativeType == GL_INT)
2409 {
2410 GLint *intParams = nullptr;
2411 intParams = new GLint[numParams];
2412
2413 context->getIntegerv(pname, intParams);
2414
2415 for(unsigned int i = 0; i < numParams; ++i)
2416 {
2417 if(intParams[i] == 0)
2418 params[i] = GL_FALSE;
2419 else
2420 params[i] = GL_TRUE;
2421 }
2422
2423 delete [] intParams;
2424 }
2425 }
2426 }
2427}
2428
2429void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2430{
2431 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2432
Chris Forbes108f3e12018-08-30 19:41:59 -07002433 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002434
2435 if(context)
2436 {
2437 es2::Buffer *buffer;
2438 if(!context->getBuffer(target, &buffer))
2439 {
2440 return error(GL_INVALID_ENUM);
2441 }
2442
2443 if(!buffer)
2444 {
2445 // A null buffer means that "0" is bound to the requested buffer target
2446 return error(GL_INVALID_OPERATION);
2447 }
2448
Nicolas Capens0bac2852016-05-07 06:09:58 -04002449 switch(pname)
2450 {
2451 case GL_BUFFER_USAGE:
2452 *params = buffer->usage();
2453 break;
2454 case GL_BUFFER_SIZE:
2455 *params = (GLint)buffer->size();
2456 break;
2457 case GL_BUFFER_ACCESS_FLAGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002458 *params = buffer->access();
2459 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002460 case GL_BUFFER_MAPPED:
Nicolas Capens83463112018-06-12 23:55:16 -04002461 *params = buffer->isMapped();
2462 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002463 case GL_BUFFER_MAP_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002464 *params = (GLint)buffer->length();
2465 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002466 case GL_BUFFER_MAP_OFFSET:
Nicolas Capens83463112018-06-12 23:55:16 -04002467 *params = (GLint)buffer->offset();
2468 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002469 default:
2470 return error(GL_INVALID_ENUM);
2471 }
2472 }
2473}
2474
2475GLenum GetError(void)
2476{
2477 TRACE("()");
2478
Chris Forbes108f3e12018-08-30 19:41:59 -07002479 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002480
2481 if(context)
2482 {
2483 return context->getError();
2484 }
2485
2486 return GL_NO_ERROR;
2487}
2488
2489void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2490{
2491 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2492
Chris Forbes108f3e12018-08-30 19:41:59 -07002493 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002494
2495 if(context)
2496 {
2497 es2::Fence *fenceObject = context->getFence(fence);
2498
2499 if(!fenceObject)
2500 {
2501 return error(GL_INVALID_OPERATION);
2502 }
2503
2504 fenceObject->getFenceiv(pname, params);
2505 }
2506}
2507
2508void GetFloatv(GLenum pname, GLfloat* params)
2509{
2510 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2511
Chris Forbes108f3e12018-08-30 19:41:59 -07002512 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002513
2514 if(context)
2515 {
2516 if(!(context->getFloatv(pname, params)))
2517 {
2518 GLenum nativeType;
2519 unsigned int numParams = 0;
2520 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2521 return error(GL_INVALID_ENUM);
2522
2523 if(numParams == 0)
2524 return; // it is known that the pname is valid, but that there are no parameters to return.
2525
2526 if(nativeType == GL_BOOL)
2527 {
2528 GLboolean *boolParams = nullptr;
2529 boolParams = new GLboolean[numParams];
2530
2531 context->getBooleanv(pname, boolParams);
2532
2533 for(unsigned int i = 0; i < numParams; ++i)
2534 {
2535 if(boolParams[i] == GL_FALSE)
2536 params[i] = 0.0f;
2537 else
2538 params[i] = 1.0f;
2539 }
2540
2541 delete [] boolParams;
2542 }
2543 else if(nativeType == GL_INT)
2544 {
2545 GLint *intParams = nullptr;
2546 intParams = new GLint[numParams];
2547
2548 context->getIntegerv(pname, intParams);
2549
2550 for(unsigned int i = 0; i < numParams; ++i)
2551 {
2552 params[i] = (GLfloat)intParams[i];
2553 }
2554
2555 delete [] intParams;
2556 }
2557 }
2558 }
2559}
2560
2561void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2562{
2563 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2564 target, attachment, pname, params);
2565
Chris Forbes108f3e12018-08-30 19:41:59 -07002566 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002567
2568 if(context)
2569 {
2570 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2571 {
2572 return error(GL_INVALID_ENUM);
2573 }
2574
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002575 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002576
Nicolas Capens0bac2852016-05-07 06:09:58 -04002577 if(target == GL_READ_FRAMEBUFFER)
2578 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002579 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002580 }
2581 else
2582 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002583 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002584 }
2585
Nicolas Capens0bac2852016-05-07 06:09:58 -04002586 switch(attachment)
2587 {
2588 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002589 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002590 case GL_STENCIL:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002591 if(framebufferName != 0)
2592 {
2593 return error(GL_INVALID_OPERATION);
2594 }
2595 break;
2596 case GL_DEPTH_ATTACHMENT:
2597 case GL_STENCIL_ATTACHMENT:
2598 if(framebufferName == 0)
2599 {
2600 return error(GL_INVALID_OPERATION);
2601 }
2602 break;
2603 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002604 if(framebufferName == 0)
2605 {
2606 return error(GL_INVALID_OPERATION);
2607 }
2608 break;
2609 default:
2610 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2611 {
2612 if(framebufferName == 0)
2613 {
2614 return error(GL_INVALID_OPERATION);
2615 }
2616 }
2617 else return error(GL_INVALID_ENUM);
2618 }
2619
2620 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2621
Alexis Hetu5cd502b2018-03-22 08:29:31 -04002622 if(!framebuffer)
2623 {
2624 return error(GL_INVALID_OPERATION);
2625 }
2626
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002627 GLenum attachmentType;
2628 GLuint attachmentHandle;
2629 GLint attachmentLayer;
2630 Renderbuffer *renderbuffer = nullptr;
2631 switch(attachment)
2632 {
2633 case GL_BACK:
2634 attachmentType = framebuffer->getColorbufferType(0);
2635 attachmentHandle = framebuffer->getColorbufferName(0);
2636 attachmentLayer = framebuffer->getColorbufferLayer(0);
2637 renderbuffer = framebuffer->getColorbuffer(0);
2638 break;
2639 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002640 case GL_DEPTH_ATTACHMENT:
2641 attachmentType = framebuffer->getDepthbufferType();
2642 attachmentHandle = framebuffer->getDepthbufferName();
2643 attachmentLayer = framebuffer->getDepthbufferLayer();
2644 renderbuffer = framebuffer->getDepthbuffer();
2645 break;
2646 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002647 case GL_STENCIL_ATTACHMENT:
2648 attachmentType = framebuffer->getStencilbufferType();
2649 attachmentHandle = framebuffer->getStencilbufferName();
2650 attachmentLayer = framebuffer->getStencilbufferLayer();
2651 renderbuffer = framebuffer->getStencilbuffer();
2652 break;
2653 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002654 attachmentType = framebuffer->getDepthbufferType();
2655 attachmentHandle = framebuffer->getDepthbufferName();
2656 attachmentLayer = framebuffer->getDepthbufferLayer();
2657 renderbuffer = framebuffer->getDepthbuffer();
2658
2659 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002660 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002661 // Different attachments to DEPTH and STENCIL, query fails
2662 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002663 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002664 break;
2665 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002666 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2667 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2668 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2669 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2670 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2671 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002672 }
2673
2674 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002675 if(framebufferName == 0)
2676 {
2677 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2678 }
2679 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002680 {
2681 attachmentObjectType = attachmentType;
2682 }
2683 else if(es2::IsTextureTarget(attachmentType))
2684 {
2685 attachmentObjectType = GL_TEXTURE;
2686 }
2687 else UNREACHABLE(attachmentType);
2688
2689 if(attachmentObjectType != GL_NONE)
2690 {
2691 switch(pname)
2692 {
2693 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2694 *params = attachmentObjectType;
2695 break;
2696 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002697 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002698 {
2699 *params = attachmentHandle;
2700 }
2701 else
2702 {
2703 return error(GL_INVALID_ENUM);
2704 }
2705 break;
2706 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2707 if(attachmentObjectType == GL_TEXTURE)
2708 {
Nicolas Capens83463112018-06-12 23:55:16 -04002709 *params = renderbuffer->getLevel();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002710 }
2711 else
2712 {
2713 return error(GL_INVALID_ENUM);
2714 }
2715 break;
2716 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2717 if(attachmentObjectType == GL_TEXTURE)
2718 {
2719 if(es2::IsCubemapTextureTarget(attachmentType))
2720 {
2721 *params = attachmentType;
2722 }
2723 else
2724 {
2725 *params = 0;
2726 }
2727 }
2728 else
2729 {
2730 return error(GL_INVALID_ENUM);
2731 }
2732 break;
2733 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
Nicolas Capens83463112018-06-12 23:55:16 -04002734 *params = attachmentLayer;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002735 break;
2736 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002737 *params = renderbuffer->getRedSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002738 break;
2739 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002740 *params = renderbuffer->getGreenSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002741 break;
2742 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002743 *params = renderbuffer->getBlueSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002744 break;
2745 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002746 *params = renderbuffer->getAlphaSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002747 break;
2748 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002749 *params = renderbuffer->getDepthSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002750 break;
2751 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002752 *params = renderbuffer->getStencilSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002753 break;
2754 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002755 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2756 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002757 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002758 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002759 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002760
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002761 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002762 break;
2763 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Nicolas Capens83463112018-06-12 23:55:16 -04002764 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002765 break;
2766 default:
2767 return error(GL_INVALID_ENUM);
2768 }
2769 }
2770 else
2771 {
2772 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2773 // is NONE, then querying any other pname will generate INVALID_ENUM.
2774
2775 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2776 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2777 // INVALID_OPERATION for all other pnames
2778
2779 switch(pname)
2780 {
2781 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2782 *params = GL_NONE;
2783 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002784 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002785 *params = 0;
2786 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002787 default:
Nicolas Capens83463112018-06-12 23:55:16 -04002788 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002789 }
2790 }
2791 }
2792}
2793
2794GLenum GetGraphicsResetStatusEXT(void)
2795{
2796 TRACE("()");
2797
2798 return GL_NO_ERROR;
2799}
2800
2801void GetIntegerv(GLenum pname, GLint* params)
2802{
2803 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2804
Chris Forbes108f3e12018-08-30 19:41:59 -07002805 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002806
2807 if(!context)
2808 {
2809 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
Alistair Strachanc28d28a2018-03-24 12:24:00 -07002810 ERR("glGetIntegerv() called without current context.");
Nicolas Capens0bac2852016-05-07 06:09:58 -04002811
2812 // This is not spec compliant! When there is no current GL context, functions should
2813 // have no side effects. Google Maps queries these values before creating a context,
2814 // so we need this as a bug-compatible workaround.
2815 switch(pname)
2816 {
2817 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
2818 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
2819 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
2820 case GL_STENCIL_BITS: *params = 8; return;
2821 case GL_ALIASED_LINE_WIDTH_RANGE:
2822 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
2823 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
2824 return;
2825 }
2826 }
2827
2828 if(context)
2829 {
2830 if(!(context->getIntegerv(pname, params)))
2831 {
2832 GLenum nativeType;
2833 unsigned int numParams = 0;
2834 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2835 return error(GL_INVALID_ENUM);
2836
2837 if(numParams == 0)
2838 return; // it is known that pname is valid, but there are no parameters to return
2839
2840 if(nativeType == GL_BOOL)
2841 {
2842 GLboolean *boolParams = nullptr;
2843 boolParams = new GLboolean[numParams];
2844
2845 context->getBooleanv(pname, boolParams);
2846
2847 for(unsigned int i = 0; i < numParams; ++i)
2848 {
2849 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
2850 }
2851
2852 delete [] boolParams;
2853 }
2854 else if(nativeType == GL_FLOAT)
2855 {
2856 GLfloat *floatParams = nullptr;
2857 floatParams = new GLfloat[numParams];
2858
2859 context->getFloatv(pname, floatParams);
2860
2861 for(unsigned int i = 0; i < numParams; ++i)
2862 {
2863 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
2864 {
Alexis Hetu60e20282017-12-13 07:42:22 -05002865 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002866 }
2867 else
2868 {
2869 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
2870 }
2871 }
2872
2873 delete [] floatParams;
2874 }
2875 }
2876 }
2877}
2878
2879void GetProgramiv(GLuint program, GLenum pname, GLint* params)
2880{
2881 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
2882
Chris Forbes108f3e12018-08-30 19:41:59 -07002883 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002884
2885 if(context)
2886 {
2887 es2::Program *programObject = context->getProgram(program);
2888
2889 if(!programObject)
2890 {
2891 if(context->getShader(program))
2892 {
2893 return error(GL_INVALID_OPERATION);
2894 }
2895 else
2896 {
2897 return error(GL_INVALID_VALUE);
2898 }
2899 }
2900
Nicolas Capens0bac2852016-05-07 06:09:58 -04002901 switch(pname)
2902 {
2903 case GL_DELETE_STATUS:
2904 *params = programObject->isFlaggedForDeletion();
2905 return;
2906 case GL_LINK_STATUS:
2907 *params = programObject->isLinked();
2908 return;
2909 case GL_VALIDATE_STATUS:
2910 *params = programObject->isValidated();
2911 return;
2912 case GL_INFO_LOG_LENGTH:
2913 *params = (GLint)programObject->getInfoLogLength();
2914 return;
2915 case GL_ATTACHED_SHADERS:
2916 *params = programObject->getAttachedShadersCount();
2917 return;
2918 case GL_ACTIVE_ATTRIBUTES:
2919 *params = (GLint)programObject->getActiveAttributeCount();
2920 return;
2921 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
2922 *params = programObject->getActiveAttributeMaxLength();
2923 return;
2924 case GL_ACTIVE_UNIFORMS:
2925 *params = (GLint)programObject->getActiveUniformCount();
2926 return;
2927 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
2928 *params = programObject->getActiveUniformMaxLength();
2929 return;
2930 case GL_ACTIVE_UNIFORM_BLOCKS:
Nicolas Capens83463112018-06-12 23:55:16 -04002931 *params = (GLint)programObject->getActiveUniformBlockCount();
2932 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002933 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002934 *params = programObject->getActiveUniformBlockMaxLength();
2935 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002936 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04002937 *params = programObject->getTransformFeedbackBufferMode();
2938 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002939 case GL_TRANSFORM_FEEDBACK_VARYINGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002940 *params = programObject->getTransformFeedbackVaryingCount();
2941 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002942 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002943 *params = programObject->getTransformFeedbackVaryingMaxLength();
2944 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002945 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Nicolas Capens83463112018-06-12 23:55:16 -04002946 *params = programObject->getBinaryRetrievableHint();
2947 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002948 case GL_PROGRAM_BINARY_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002949 *params = programObject->getBinaryLength();
2950 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002951 default:
2952 return error(GL_INVALID_ENUM);
2953 }
2954 }
2955}
2956
2957void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
2958{
2959 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
2960 program, bufsize, length, infolog);
2961
2962 if(bufsize < 0)
2963 {
2964 return error(GL_INVALID_VALUE);
2965 }
2966
Chris Forbes108f3e12018-08-30 19:41:59 -07002967 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002968
2969 if(context)
2970 {
2971 es2::Program *programObject = context->getProgram(program);
2972
2973 if(!programObject)
2974 {
2975 if(context->getShader(program))
2976 {
2977 return error(GL_INVALID_OPERATION);
2978 }
2979 else
2980 {
2981 return error(GL_INVALID_VALUE);
2982 }
2983 }
2984
2985 programObject->getInfoLog(bufsize, length, infolog);
2986 }
2987}
2988
2989void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
2990{
2991 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
2992
2993 switch(pname)
2994 {
2995 case GL_CURRENT_QUERY_EXT:
2996 break;
2997 default:
2998 return error(GL_INVALID_ENUM);
2999 }
3000
Chris Forbes108f3e12018-08-30 19:41:59 -07003001 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003002
3003 if(context)
3004 {
3005 params[0] = context->getActiveQuery(target);
3006 }
3007}
3008
3009void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3010{
3011 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3012
3013 switch(pname)
3014 {
3015 case GL_QUERY_RESULT_EXT:
3016 case GL_QUERY_RESULT_AVAILABLE_EXT:
3017 break;
3018 default:
3019 return error(GL_INVALID_ENUM);
3020 }
3021
Chris Forbes108f3e12018-08-30 19:41:59 -07003022 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003023
3024 if(context)
3025 {
3026 es2::Query *queryObject = context->getQuery(name);
3027
3028 if(!queryObject)
3029 {
3030 return error(GL_INVALID_OPERATION);
3031 }
3032
3033 if(context->getActiveQuery(queryObject->getType()) == name)
3034 {
3035 return error(GL_INVALID_OPERATION);
3036 }
3037
3038 switch(pname)
3039 {
3040 case GL_QUERY_RESULT_EXT:
3041 params[0] = queryObject->getResult();
3042 break;
3043 case GL_QUERY_RESULT_AVAILABLE_EXT:
3044 params[0] = queryObject->isResultAvailable();
3045 break;
3046 default:
3047 ASSERT(false);
3048 }
3049 }
3050}
3051
3052void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3053{
3054 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3055
Chris Forbes108f3e12018-08-30 19:41:59 -07003056 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003057
3058 if(context)
3059 {
3060 if(target != GL_RENDERBUFFER)
3061 {
3062 return error(GL_INVALID_ENUM);
3063 }
3064
3065 if(context->getRenderbufferName() == 0)
3066 {
3067 return error(GL_INVALID_OPERATION);
3068 }
3069
3070 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3071
3072 switch(pname)
3073 {
3074 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3075 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003076 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3077 {
3078 GLint internalformat = renderbuffer->getFormat();
3079 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3080 }
3081 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003082 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3083 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3084 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3085 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3086 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3087 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003088 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003089 default:
3090 return error(GL_INVALID_ENUM);
3091 }
3092 }
3093}
3094
3095void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3096{
3097 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3098
Chris Forbes108f3e12018-08-30 19:41:59 -07003099 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003100
3101 if(context)
3102 {
3103 es2::Shader *shaderObject = context->getShader(shader);
3104
3105 if(!shaderObject)
3106 {
3107 if(context->getProgram(shader))
3108 {
3109 return error(GL_INVALID_OPERATION);
3110 }
3111 else
3112 {
3113 return error(GL_INVALID_VALUE);
3114 }
3115 }
3116
3117 switch(pname)
3118 {
3119 case GL_SHADER_TYPE:
3120 *params = shaderObject->getType();
3121 return;
3122 case GL_DELETE_STATUS:
3123 *params = shaderObject->isFlaggedForDeletion();
3124 return;
3125 case GL_COMPILE_STATUS:
3126 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3127 return;
3128 case GL_INFO_LOG_LENGTH:
3129 *params = (GLint)shaderObject->getInfoLogLength();
3130 return;
3131 case GL_SHADER_SOURCE_LENGTH:
3132 *params = (GLint)shaderObject->getSourceLength();
3133 return;
3134 default:
3135 return error(GL_INVALID_ENUM);
3136 }
3137 }
3138}
3139
3140void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3141{
3142 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3143 shader, bufsize, length, infolog);
3144
3145 if(bufsize < 0)
3146 {
3147 return error(GL_INVALID_VALUE);
3148 }
3149
Chris Forbes108f3e12018-08-30 19:41:59 -07003150 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003151
3152 if(context)
3153 {
3154 es2::Shader *shaderObject = context->getShader(shader);
3155
3156 if(!shaderObject)
3157 {
3158 if(context->getProgram(shader))
3159 {
3160 return error(GL_INVALID_OPERATION);
3161 }
3162 else
3163 {
3164 return error(GL_INVALID_VALUE);
3165 }
3166 }
3167
3168 shaderObject->getInfoLog(bufsize, length, infolog);
3169 }
3170}
3171
3172void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3173{
3174 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3175 shadertype, precisiontype, range, precision);
3176
3177 switch(shadertype)
3178 {
3179 case GL_VERTEX_SHADER:
3180 case GL_FRAGMENT_SHADER:
3181 break;
3182 default:
3183 return error(GL_INVALID_ENUM);
3184 }
3185
3186 switch(precisiontype)
3187 {
3188 case GL_LOW_FLOAT:
3189 case GL_MEDIUM_FLOAT:
3190 case GL_HIGH_FLOAT:
3191 // IEEE 754 single-precision
3192 range[0] = 127;
3193 range[1] = 127;
3194 *precision = 23;
3195 break;
3196 case GL_LOW_INT:
3197 case GL_MEDIUM_INT:
3198 case GL_HIGH_INT:
3199 // Full integer precision is supported
3200 range[0] = 31;
3201 range[1] = 30;
3202 *precision = 0;
3203 break;
3204 default:
3205 return error(GL_INVALID_ENUM);
3206 }
3207}
3208
3209void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3210{
3211 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3212 shader, bufsize, length, source);
3213
3214 if(bufsize < 0)
3215 {
3216 return error(GL_INVALID_VALUE);
3217 }
3218
Chris Forbes108f3e12018-08-30 19:41:59 -07003219 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003220
3221 if(context)
3222 {
3223 es2::Shader *shaderObject = context->getShader(shader);
3224
3225 if(!shaderObject)
3226 {
3227 if(context->getProgram(shader))
3228 {
3229 return error(GL_INVALID_OPERATION);
3230 }
3231 else
3232 {
3233 return error(GL_INVALID_VALUE);
3234 }
3235 }
3236
3237 shaderObject->getSource(bufsize, length, source);
3238 }
3239}
3240
3241const GLubyte* GetString(GLenum name)
3242{
3243 TRACE("(GLenum name = 0x%X)", name);
3244
3245 switch(name)
3246 {
3247 case GL_VENDOR:
3248 return (GLubyte*)"Google Inc.";
3249 case GL_RENDERER:
3250 return (GLubyte*)"Google SwiftShader";
3251 case GL_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003252 return (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003253 case GL_SHADING_LANGUAGE_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003254 return (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003255 case GL_EXTENSIONS:
Nicolas Capens894858a2018-03-22 00:55:23 -04003256 {
Chris Forbes108f3e12018-08-30 19:41:59 -07003257 auto context = es2::getContext();
Nicolas Capens894858a2018-03-22 00:55:23 -04003258 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3259 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003260 default:
3261 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3262 }
3263}
3264
3265void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3266{
3267 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3268
Chris Forbes108f3e12018-08-30 19:41:59 -07003269 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003270
3271 if(context)
3272 {
3273 es2::Texture *texture;
3274
Nicolas Capens0bac2852016-05-07 06:09:58 -04003275 switch(target)
3276 {
Nicolas Capens83463112018-06-12 23:55:16 -04003277 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3278 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3279 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3280 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3281 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3282 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003283 default:
3284 return error(GL_INVALID_ENUM);
3285 }
3286
3287 switch(pname)
3288 {
3289 case GL_TEXTURE_MAG_FILTER:
3290 *params = (GLfloat)texture->getMagFilter();
3291 break;
3292 case GL_TEXTURE_MIN_FILTER:
3293 *params = (GLfloat)texture->getMinFilter();
3294 break;
3295 case GL_TEXTURE_WRAP_S:
3296 *params = (GLfloat)texture->getWrapS();
3297 break;
3298 case GL_TEXTURE_WRAP_T:
3299 *params = (GLfloat)texture->getWrapT();
3300 break;
3301 case GL_TEXTURE_WRAP_R_OES:
3302 *params = (GLfloat)texture->getWrapR();
3303 break;
3304 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3305 *params = texture->getMaxAnisotropy();
3306 break;
3307 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3308 *params = (GLfloat)1;
3309 break;
3310 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003311 *params = (GLfloat)texture->getBaseLevel();
3312 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003313 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003314 *params = (GLfloat)texture->getCompareFunc();
3315 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003316 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003317 *params = (GLfloat)texture->getCompareMode();
3318 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003319 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003320 *params = (GLfloat)texture->getImmutableFormat();
3321 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003322 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003323 *params = (GLfloat)texture->getImmutableLevels();
3324 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003325 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003326 *params = (GLfloat)texture->getMaxLevel();
3327 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003328 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003329 *params = texture->getMaxLOD();
3330 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003331 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003332 *params = texture->getMinLOD();
3333 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003334 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003335 *params = (GLfloat)texture->getSwizzleR();
3336 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003337 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003338 *params = (GLfloat)texture->getSwizzleG();
3339 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003340 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003341 *params = (GLfloat)texture->getSwizzleB();
3342 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003343 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003344 *params = (GLfloat)texture->getSwizzleA();
3345 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003346 default:
3347 return error(GL_INVALID_ENUM);
3348 }
3349 }
3350}
3351
3352void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3353{
3354 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3355
Chris Forbes108f3e12018-08-30 19:41:59 -07003356 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003357
3358 if(context)
3359 {
3360 es2::Texture *texture;
3361
Nicolas Capens0bac2852016-05-07 06:09:58 -04003362 switch(target)
3363 {
Nicolas Capens83463112018-06-12 23:55:16 -04003364 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3365 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3366 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3367 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3368 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3369 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003370 default:
3371 return error(GL_INVALID_ENUM);
3372 }
3373
3374 switch(pname)
3375 {
3376 case GL_TEXTURE_MAG_FILTER:
3377 *params = texture->getMagFilter();
3378 break;
3379 case GL_TEXTURE_MIN_FILTER:
3380 *params = texture->getMinFilter();
3381 break;
3382 case GL_TEXTURE_WRAP_S:
3383 *params = texture->getWrapS();
3384 break;
3385 case GL_TEXTURE_WRAP_T:
3386 *params = texture->getWrapT();
3387 break;
3388 case GL_TEXTURE_WRAP_R_OES:
3389 *params = texture->getWrapR();
3390 break;
3391 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3392 *params = (GLint)texture->getMaxAnisotropy();
3393 break;
3394 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3395 *params = 1;
3396 break;
3397 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003398 *params = texture->getBaseLevel();
3399 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003400 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003401 *params = (GLint)texture->getCompareFunc();
3402 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003403 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003404 *params = (GLint)texture->getCompareMode();
3405 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003406 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003407 *params = (GLint)texture->getImmutableFormat();
3408 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003409 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003410 *params = (GLint)texture->getImmutableLevels();
3411 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003412 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003413 *params = texture->getMaxLevel();
3414 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003415 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003416 *params = (GLint)roundf(texture->getMaxLOD());
3417 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003418 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003419 *params = (GLint)roundf(texture->getMinLOD());
3420 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003421 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003422 *params = (GLint)texture->getSwizzleR();
3423 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003424 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003425 *params = (GLint)texture->getSwizzleG();
3426 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003427 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003428 *params = (GLint)texture->getSwizzleB();
3429 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003430 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003431 *params = (GLint)texture->getSwizzleA();
3432 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003433 default:
3434 return error(GL_INVALID_ENUM);
3435 }
3436 }
3437}
3438
3439void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3440{
3441 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3442 program, location, bufSize, params);
3443
3444 if(bufSize < 0)
3445 {
3446 return error(GL_INVALID_VALUE);
3447 }
3448
Chris Forbes108f3e12018-08-30 19:41:59 -07003449 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003450
3451 if(context)
3452 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003453 es2::Program *programObject = context->getProgram(program);
3454
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003455 if(!programObject)
3456 {
3457 if(context->getShader(program))
3458 {
3459 return error(GL_INVALID_OPERATION);
3460 }
3461 else
3462 {
3463 return error(GL_INVALID_VALUE);
3464 }
3465 }
3466
3467 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003468 {
3469 return error(GL_INVALID_OPERATION);
3470 }
3471
3472 if(!programObject->getUniformfv(location, &bufSize, params))
3473 {
3474 return error(GL_INVALID_OPERATION);
3475 }
3476 }
3477}
3478
3479void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3480{
3481 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3482
Chris Forbes108f3e12018-08-30 19:41:59 -07003483 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003484
3485 if(context)
3486 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003487 es2::Program *programObject = context->getProgram(program);
3488
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003489 if(!programObject)
3490 {
3491 if(context->getShader(program))
3492 {
3493 return error(GL_INVALID_OPERATION);
3494 }
3495 else
3496 {
3497 return error(GL_INVALID_VALUE);
3498 }
3499 }
3500
3501 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003502 {
3503 return error(GL_INVALID_OPERATION);
3504 }
3505
3506 if(!programObject->getUniformfv(location, nullptr, params))
3507 {
3508 return error(GL_INVALID_OPERATION);
3509 }
3510 }
3511}
3512
3513void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3514{
3515 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3516 program, location, bufSize, params);
3517
3518 if(bufSize < 0)
3519 {
3520 return error(GL_INVALID_VALUE);
3521 }
3522
Chris Forbes108f3e12018-08-30 19:41:59 -07003523 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003524
3525 if(context)
3526 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003527 es2::Program *programObject = context->getProgram(program);
3528
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003529 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003530 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003531 if(context->getShader(program))
3532 {
3533 return error(GL_INVALID_OPERATION);
3534 }
3535 else
3536 {
3537 return error(GL_INVALID_VALUE);
3538 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003539 }
3540
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003541 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003542 {
3543 return error(GL_INVALID_OPERATION);
3544 }
3545
3546 if(!programObject->getUniformiv(location, &bufSize, params))
3547 {
3548 return error(GL_INVALID_OPERATION);
3549 }
3550 }
3551}
3552
3553void GetUniformiv(GLuint program, GLint location, GLint* params)
3554{
3555 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3556
Chris Forbes108f3e12018-08-30 19:41:59 -07003557 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003558
3559 if(context)
3560 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003561 es2::Program *programObject = context->getProgram(program);
3562
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003563 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003564 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003565 if(context->getShader(program))
3566 {
3567 return error(GL_INVALID_OPERATION);
3568 }
3569 else
3570 {
3571 return error(GL_INVALID_VALUE);
3572 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003573 }
3574
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003575 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003576 {
3577 return error(GL_INVALID_OPERATION);
3578 }
3579
3580 if(!programObject->getUniformiv(location, nullptr, params))
3581 {
3582 return error(GL_INVALID_OPERATION);
3583 }
3584 }
3585}
3586
3587int GetUniformLocation(GLuint program, const GLchar* name)
3588{
3589 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3590
Chris Forbes108f3e12018-08-30 19:41:59 -07003591 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003592
3593 if(strstr(name, "gl_") == name)
3594 {
3595 return -1;
3596 }
3597
3598 if(context)
3599 {
3600 es2::Program *programObject = context->getProgram(program);
3601
3602 if(!programObject)
3603 {
3604 if(context->getShader(program))
3605 {
3606 return error(GL_INVALID_OPERATION, -1);
3607 }
3608 else
3609 {
3610 return error(GL_INVALID_VALUE, -1);
3611 }
3612 }
3613
3614 if(!programObject->isLinked())
3615 {
3616 return error(GL_INVALID_OPERATION, -1);
3617 }
3618
3619 return programObject->getUniformLocation(name);
3620 }
3621
3622 return -1;
3623}
3624
3625void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3626{
3627 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
3628
Chris Forbes108f3e12018-08-30 19:41:59 -07003629 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003630
3631 if(context)
3632 {
3633 if(index >= es2::MAX_VERTEX_ATTRIBS)
3634 {
3635 return error(GL_INVALID_VALUE);
3636 }
3637
3638 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3639
Nicolas Capens0bac2852016-05-07 06:09:58 -04003640 switch(pname)
3641 {
3642 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3643 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3644 break;
3645 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3646 *params = (GLfloat)attribState.mSize;
3647 break;
3648 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3649 *params = (GLfloat)attribState.mStride;
3650 break;
3651 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3652 *params = (GLfloat)attribState.mType;
3653 break;
3654 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3655 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
3656 break;
3657 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3658 *params = (GLfloat)attribState.mBoundBuffer.name();
3659 break;
3660 case GL_CURRENT_VERTEX_ATTRIB:
3661 {
3662 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3663 for(int i = 0; i < 4; ++i)
3664 {
3665 params[i] = attrib.getCurrentValueF(i);
3666 }
3667 }
3668 break;
3669 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003670 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3671 break;
3672 default:
3673 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003674 }
3675 }
3676}
3677
3678void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
3679{
3680 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
3681
Chris Forbes108f3e12018-08-30 19:41:59 -07003682 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003683
3684 if(context)
3685 {
3686 if(index >= es2::MAX_VERTEX_ATTRIBS)
3687 {
3688 return error(GL_INVALID_VALUE);
3689 }
3690
3691 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3692
Nicolas Capens0bac2852016-05-07 06:09:58 -04003693 switch(pname)
3694 {
3695 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3696 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3697 break;
3698 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3699 *params = attribState.mSize;
3700 break;
3701 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3702 *params = attribState.mStride;
3703 break;
3704 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3705 *params = attribState.mType;
3706 break;
3707 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3708 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
3709 break;
3710 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3711 *params = attribState.mBoundBuffer.name();
3712 break;
3713 case GL_CURRENT_VERTEX_ATTRIB:
3714 {
3715 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3716 for(int i = 0; i < 4; ++i)
3717 {
3718 float currentValue = attrib.getCurrentValueF(i);
3719 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
3720 }
3721 }
3722 break;
3723 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003724 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3725 break;
3726 default:
3727 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003728 }
3729 }
3730}
3731
3732void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
3733{
3734 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
3735
Chris Forbes108f3e12018-08-30 19:41:59 -07003736 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003737
3738 if(context)
3739 {
3740 if(index >= es2::MAX_VERTEX_ATTRIBS)
3741 {
3742 return error(GL_INVALID_VALUE);
3743 }
3744
3745 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
3746 {
3747 return error(GL_INVALID_ENUM);
3748 }
3749
3750 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
3751 }
3752}
3753
3754void Hint(GLenum target, GLenum mode)
3755{
3756 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
3757
3758 switch(mode)
3759 {
3760 case GL_FASTEST:
3761 case GL_NICEST:
3762 case GL_DONT_CARE:
3763 break;
3764 default:
3765 return error(GL_INVALID_ENUM);
3766 }
3767
Chris Forbes108f3e12018-08-30 19:41:59 -07003768 auto context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003769
3770 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003771 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003772 switch(target)
3773 {
3774 case GL_GENERATE_MIPMAP_HINT:
3775 context->setGenerateMipmapHint(mode);
3776 break;
3777 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
3778 context->setFragmentShaderDerivativeHint(mode);
3779 break;
3780 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
3781 context->setTextureFilteringHint(mode);
3782 break;
3783 default:
3784 return error(GL_INVALID_ENUM);
3785 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003786 }
3787}
3788
3789GLboolean IsBuffer(GLuint buffer)
3790{
3791 TRACE("(GLuint buffer = %d)", buffer);
3792
Chris Forbes108f3e12018-08-30 19:41:59 -07003793 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003794
3795 if(context && buffer)
3796 {
3797 es2::Buffer *bufferObject = context->getBuffer(buffer);
3798
3799 if(bufferObject)
3800 {
3801 return GL_TRUE;
3802 }
3803 }
3804
3805 return GL_FALSE;
3806}
3807
3808GLboolean IsEnabled(GLenum cap)
3809{
3810 TRACE("(GLenum cap = 0x%X)", cap);
3811
Chris Forbes108f3e12018-08-30 19:41:59 -07003812 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003813
3814 if(context)
3815 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003816 switch(cap)
3817 {
3818 case GL_CULL_FACE: return context->isCullFaceEnabled();
3819 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
3820 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
3821 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
3822 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
3823 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
3824 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
3825 case GL_BLEND: return context->isBlendEnabled();
3826 case GL_DITHER: return context->isDitherEnabled();
Nicolas Capens83463112018-06-12 23:55:16 -04003827 case GL_PRIMITIVE_RESTART_FIXED_INDEX: return context->isPrimitiveRestartFixedIndexEnabled();
3828 case GL_RASTERIZER_DISCARD: return context->isRasterizerDiscardEnabled();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003829 default:
3830 return error(GL_INVALID_ENUM, false);
3831 }
3832 }
3833
3834 return false;
3835}
3836
3837GLboolean IsFenceNV(GLuint fence)
3838{
3839 TRACE("(GLuint fence = %d)", fence);
3840
Chris Forbes108f3e12018-08-30 19:41:59 -07003841 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003842
3843 if(context)
3844 {
3845 es2::Fence *fenceObject = context->getFence(fence);
3846
3847 if(!fenceObject)
3848 {
3849 return GL_FALSE;
3850 }
3851
3852 return fenceObject->isFence();
3853 }
3854
3855 return GL_FALSE;
3856}
3857
3858GLboolean IsFramebuffer(GLuint framebuffer)
3859{
3860 TRACE("(GLuint framebuffer = %d)", framebuffer);
3861
Chris Forbes108f3e12018-08-30 19:41:59 -07003862 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003863
3864 if(context && framebuffer)
3865 {
3866 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
3867
3868 if(framebufferObject)
3869 {
3870 return GL_TRUE;
3871 }
3872 }
3873
3874 return GL_FALSE;
3875}
3876
3877GLboolean IsProgram(GLuint program)
3878{
3879 TRACE("(GLuint program = %d)", program);
3880
Chris Forbes108f3e12018-08-30 19:41:59 -07003881 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003882
3883 if(context && program)
3884 {
3885 es2::Program *programObject = context->getProgram(program);
3886
3887 if(programObject)
3888 {
3889 return GL_TRUE;
3890 }
3891 }
3892
3893 return GL_FALSE;
3894}
3895
3896GLboolean IsQueryEXT(GLuint name)
3897{
3898 TRACE("(GLuint name = %d)", name);
3899
3900 if(name == 0)
3901 {
3902 return GL_FALSE;
3903 }
3904
Chris Forbes108f3e12018-08-30 19:41:59 -07003905 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003906
3907 if(context)
3908 {
3909 es2::Query *queryObject = context->getQuery(name);
3910
3911 if(queryObject)
3912 {
3913 return GL_TRUE;
3914 }
3915 }
3916
3917 return GL_FALSE;
3918}
3919
3920GLboolean IsRenderbuffer(GLuint renderbuffer)
3921{
3922 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
3923
Chris Forbes108f3e12018-08-30 19:41:59 -07003924 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003925
3926 if(context && renderbuffer)
3927 {
3928 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
3929
3930 if(renderbufferObject)
3931 {
3932 return GL_TRUE;
3933 }
3934 }
3935
3936 return GL_FALSE;
3937}
3938
3939GLboolean IsShader(GLuint shader)
3940{
3941 TRACE("(GLuint shader = %d)", shader);
3942
Chris Forbes108f3e12018-08-30 19:41:59 -07003943 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003944
3945 if(context && shader)
3946 {
3947 es2::Shader *shaderObject = context->getShader(shader);
3948
3949 if(shaderObject)
3950 {
3951 return GL_TRUE;
3952 }
3953 }
3954
3955 return GL_FALSE;
3956}
3957
3958GLboolean IsTexture(GLuint texture)
3959{
3960 TRACE("(GLuint texture = %d)", texture);
3961
Chris Forbes108f3e12018-08-30 19:41:59 -07003962 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003963
3964 if(context && texture)
3965 {
3966 es2::Texture *textureObject = context->getTexture(texture);
3967
3968 if(textureObject)
3969 {
3970 return GL_TRUE;
3971 }
3972 }
3973
3974 return GL_FALSE;
3975}
3976
3977void LineWidth(GLfloat width)
3978{
3979 TRACE("(GLfloat width = %f)", width);
3980
3981 if(width <= 0.0f)
3982 {
3983 return error(GL_INVALID_VALUE);
3984 }
3985
Chris Forbes108f3e12018-08-30 19:41:59 -07003986 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003987
3988 if(context)
3989 {
3990 context->setLineWidth(width);
3991 }
3992}
3993
3994void LinkProgram(GLuint program)
3995{
3996 TRACE("(GLuint program = %d)", program);
3997
Chris Forbes108f3e12018-08-30 19:41:59 -07003998 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003999
4000 if(context)
4001 {
4002 es2::Program *programObject = context->getProgram(program);
4003
4004 if(!programObject)
4005 {
4006 if(context->getShader(program))
4007 {
4008 return error(GL_INVALID_OPERATION);
4009 }
4010 else
4011 {
4012 return error(GL_INVALID_VALUE);
4013 }
4014 }
4015
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004016 if(programObject == context->getCurrentProgram())
4017 {
4018 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4019 if(transformFeedback && transformFeedback->isActive())
4020 {
4021 return error(GL_INVALID_OPERATION);
4022 }
4023 }
4024
Nicolas Capens0bac2852016-05-07 06:09:58 -04004025 programObject->link();
4026 }
4027}
4028
4029void PixelStorei(GLenum pname, GLint param)
4030{
4031 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4032
Chris Forbes108f3e12018-08-30 19:41:59 -07004033 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004034
4035 if(context)
4036 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004037 switch(pname)
4038 {
4039 case GL_UNPACK_ALIGNMENT:
4040 if(param != 1 && param != 2 && param != 4 && param != 8)
4041 {
4042 return error(GL_INVALID_VALUE);
4043 }
4044 context->setUnpackAlignment(param);
4045 break;
4046 case GL_PACK_ALIGNMENT:
4047 if(param != 1 && param != 2 && param != 4 && param != 8)
4048 {
4049 return error(GL_INVALID_VALUE);
4050 }
4051 context->setPackAlignment(param);
4052 break;
4053 case GL_PACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004054 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004055 {
Nicolas Capens83463112018-06-12 23:55:16 -04004056 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004057 }
Nicolas Capens83463112018-06-12 23:55:16 -04004058 context->setPackRowLength(param);
4059 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004060 case GL_PACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004061 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004062 {
Nicolas Capens83463112018-06-12 23:55:16 -04004063 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004064 }
Nicolas Capens83463112018-06-12 23:55:16 -04004065 context->setPackSkipPixels(param);
4066 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004067 case GL_PACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004068 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004069 {
Nicolas Capens83463112018-06-12 23:55:16 -04004070 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004071 }
Nicolas Capens83463112018-06-12 23:55:16 -04004072 context->setPackSkipRows(param);
4073 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004074 case GL_UNPACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004075 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004076 {
Nicolas Capens83463112018-06-12 23:55:16 -04004077 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004078 }
Nicolas Capens83463112018-06-12 23:55:16 -04004079 context->setUnpackRowLength(param);
4080 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004081 case GL_UNPACK_IMAGE_HEIGHT:
Nicolas Capens83463112018-06-12 23:55:16 -04004082 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004083 {
Nicolas Capens83463112018-06-12 23:55:16 -04004084 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004085 }
Nicolas Capens83463112018-06-12 23:55:16 -04004086 context->setUnpackImageHeight(param);
4087 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004088 case GL_UNPACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004089 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004090 {
Nicolas Capens83463112018-06-12 23:55:16 -04004091 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004092 }
Nicolas Capens83463112018-06-12 23:55:16 -04004093 context->setUnpackSkipPixels(param);
4094 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004095 case GL_UNPACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004096 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004097 {
Nicolas Capens83463112018-06-12 23:55:16 -04004098 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004099 }
Nicolas Capens83463112018-06-12 23:55:16 -04004100 context->setUnpackSkipRows(param);
4101 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004102 case GL_UNPACK_SKIP_IMAGES:
Nicolas Capens83463112018-06-12 23:55:16 -04004103 if(param < 0)
4104 {
4105 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004106 }
Nicolas Capens83463112018-06-12 23:55:16 -04004107 context->setUnpackSkipImages(param);
4108 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004109 default:
4110 return error(GL_INVALID_ENUM);
4111 }
4112 }
4113}
4114
4115void PolygonOffset(GLfloat factor, GLfloat units)
4116{
4117 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4118
Chris Forbes108f3e12018-08-30 19:41:59 -07004119 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004120
4121 if(context)
4122 {
4123 context->setPolygonOffsetParams(factor, units);
4124 }
4125}
4126
4127void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4128 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4129{
4130 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4131 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4132 x, y, width, height, format, type, bufSize, data);
4133
4134 if(width < 0 || height < 0 || bufSize < 0)
4135 {
4136 return error(GL_INVALID_VALUE);
4137 }
4138
Chris Forbes108f3e12018-08-30 19:41:59 -07004139 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004140
4141 if(context)
4142 {
4143 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4144 }
4145}
4146
4147void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4148{
4149 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4150 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4151 x, y, width, height, format, type, pixels);
4152
4153 if(width < 0 || height < 0)
4154 {
4155 return error(GL_INVALID_VALUE);
4156 }
4157
Chris Forbes108f3e12018-08-30 19:41:59 -07004158 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004159
4160 if(context)
4161 {
4162 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4163 }
4164}
4165
4166void ReleaseShaderCompiler(void)
4167{
4168 TRACE("()");
4169
4170 es2::Shader::releaseCompiler();
4171}
4172
Nicolas Capens400667e2017-03-29 14:40:14 -04004173void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004174{
4175 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4176 target, samples, internalformat, width, height);
4177
4178 switch(target)
4179 {
4180 case GL_RENDERBUFFER:
4181 break;
4182 default:
4183 return error(GL_INVALID_ENUM);
4184 }
4185
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004186 if(width < 0 || height < 0 || samples < 0 ||
4187 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4188 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004189 {
4190 return error(GL_INVALID_VALUE);
4191 }
4192
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004193 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004194 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004195 {
4196 return error(GL_INVALID_OPERATION);
4197 }
4198
Chris Forbes108f3e12018-08-30 19:41:59 -07004199 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004200
4201 if(context)
4202 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004203 GLuint handle = context->getRenderbufferName();
4204 if(handle == 0)
4205 {
4206 return error(GL_INVALID_OPERATION);
4207 }
4208
Nicolas Capens83463112018-06-12 23:55:16 -04004209 if(IsColorRenderable(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004210 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004211 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004212 }
Nicolas Capens83463112018-06-12 23:55:16 -04004213 else if(IsDepthRenderable(internalformat) && IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004214 {
4215 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4216 }
Nicolas Capens83463112018-06-12 23:55:16 -04004217 else if(IsDepthRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004218 {
4219 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4220 }
Nicolas Capens83463112018-06-12 23:55:16 -04004221 else if(IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004222 {
4223 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4224 }
4225 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004226 }
4227}
4228
Nicolas Capens400667e2017-03-29 14:40:14 -04004229void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4230{
4231 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4232}
4233
Nicolas Capens0bac2852016-05-07 06:09:58 -04004234void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4235{
Nicolas Capens400667e2017-03-29 14:40:14 -04004236 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004237}
4238
4239void SampleCoverage(GLclampf value, GLboolean invert)
4240{
4241 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4242
Chris Forbes108f3e12018-08-30 19:41:59 -07004243 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004244
4245 if(context)
4246 {
Nicolas Capens51814272018-10-15 13:01:22 -04004247 context->setSampleCoverageParams(es2::clamp01(value), invert != GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004248 }
4249}
4250
4251void SetFenceNV(GLuint fence, GLenum condition)
4252{
4253 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4254
4255 if(condition != GL_ALL_COMPLETED_NV)
4256 {
4257 return error(GL_INVALID_ENUM);
4258 }
4259
Chris Forbes108f3e12018-08-30 19:41:59 -07004260 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004261
4262 if(context)
4263 {
4264 es2::Fence *fenceObject = context->getFence(fence);
4265
4266 if(!fenceObject)
4267 {
4268 return error(GL_INVALID_OPERATION);
4269 }
4270
4271 fenceObject->setFence(condition);
4272 }
4273}
4274
4275void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4276{
4277 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4278
4279 if(width < 0 || height < 0)
4280 {
4281 return error(GL_INVALID_VALUE);
4282 }
4283
Chris Forbes108f3e12018-08-30 19:41:59 -07004284 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004285
4286 if(context)
4287 {
4288 context->setScissorParams(x, y, width, height);
4289 }
4290}
4291
4292void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4293{
4294 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4295 "const GLvoid* binary = %p, GLsizei length = %d)",
4296 n, shaders, binaryformat, binary, length);
4297
4298 // No binary shader formats are supported.
4299 return error(GL_INVALID_ENUM);
4300}
4301
4302void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4303{
4304 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4305 shader, count, string, length);
4306
4307 if(count < 0)
4308 {
4309 return error(GL_INVALID_VALUE);
4310 }
4311
Chris Forbes108f3e12018-08-30 19:41:59 -07004312 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004313
4314 if(context)
4315 {
4316 es2::Shader *shaderObject = context->getShader(shader);
4317
4318 if(!shaderObject)
4319 {
4320 if(context->getProgram(shader))
4321 {
4322 return error(GL_INVALID_OPERATION);
4323 }
4324 else
4325 {
4326 return error(GL_INVALID_VALUE);
4327 }
4328 }
4329
4330 shaderObject->setSource(count, string, length);
4331 }
4332}
4333
4334void StencilFunc(GLenum func, GLint ref, GLuint mask)
4335{
4336 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4337}
4338
4339void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4340{
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
4384void StencilMask(GLuint mask)
4385{
4386 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4387}
4388
4389void StencilMaskSeparate(GLenum face, GLuint mask)
4390{
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
4419void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4420{
4421 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4422}
4423
4424void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4425{
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
4500GLboolean TestFenceNV(GLuint fence)
4501{
4502 TRACE("(GLuint fence = %d)", fence);
4503
Chris Forbes108f3e12018-08-30 19:41:59 -07004504 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004505
4506 if(context)
4507 {
4508 es2::Fence *fenceObject = context->getFence(fence);
4509
4510 if(!fenceObject)
4511 {
4512 return error(GL_INVALID_OPERATION, GL_TRUE);
4513 }
4514
4515 return fenceObject->testFence();
4516 }
4517
4518 return GL_TRUE;
4519}
4520
4521void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004522 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004523{
4524 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004525 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
4526 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004527
4528 if(!validImageSize(level, width, height))
4529 {
4530 return error(GL_INVALID_VALUE);
4531 }
4532
Chris Forbes108f3e12018-08-30 19:41:59 -07004533 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004534
4535 if(context)
4536 {
Nicolas Capens83463112018-06-12 23:55:16 -04004537 // GL_APPLE_texture_format_BGRA8888 allows (only) GL_BGRA_EXT / GL_RGBA, while
Nicolas Capensbc62c3b2018-02-27 16:45:43 -05004538 // GL_EXT_texture_format_BGRA8888 also allows GL_BGRA_EXT / GL_BGRA_EXT.
4539 if(format == GL_BGRA_EXT && internalformat == GL_RGBA)
4540 {
4541 internalformat = GL_BGRA_EXT;
4542 }
4543
Nicolas Capens83463112018-06-12 23:55:16 -04004544 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05004545 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004546 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004547 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004548 }
4549
4550 if(border != 0)
4551 {
4552 return error(GL_INVALID_VALUE);
4553 }
4554
4555 switch(target)
4556 {
Alexis Hetu46768622018-01-16 22:09:28 -05004557 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004558 if(level != 0)
4559 {
4560 return error(GL_INVALID_VALUE); // Defining level other than 0 is not allowed
4561 }
Nicolas Capens894858a2018-03-22 00:55:23 -04004562 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -05004563 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04004564 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4565 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4566 {
4567 return error(GL_INVALID_VALUE);
4568 }
4569 break;
4570 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4571 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4572 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4573 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4574 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4575 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4576 if(width != height)
4577 {
4578 return error(GL_INVALID_VALUE);
4579 }
4580
4581 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
4582 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
4583 {
4584 return error(GL_INVALID_VALUE);
4585 }
4586 break;
4587 default:
4588 return error(GL_INVALID_ENUM);
4589 }
4590
Nicolas Capens5555af42017-12-14 13:14:03 -05004591 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004592 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05004593 {
4594 return error(validationError);
4595 }
4596
Nicolas Capens894858a2018-03-22 00:55:23 -04004597 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
4598
Alexis Hetu46768622018-01-16 22:09:28 -05004599 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004600 {
Alexis Hetu46768622018-01-16 22:09:28 -05004601 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004602
4603 if(!texture)
4604 {
4605 return error(GL_INVALID_OPERATION);
4606 }
4607
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004608 texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004609 }
4610 else
4611 {
4612 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4613
4614 if(!texture)
4615 {
4616 return error(GL_INVALID_OPERATION);
4617 }
4618
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004619 texture->setImage(target, level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004620 }
4621 }
4622}
4623
4624void TexParameterf(GLenum target, GLenum pname, GLfloat param)
4625{
4626 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
4627
Chris Forbes108f3e12018-08-30 19:41:59 -07004628 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004629
4630 if(context)
4631 {
4632 es2::Texture *texture;
4633
Nicolas Capens0bac2852016-05-07 06:09:58 -04004634 switch(target)
4635 {
Nicolas Capens83463112018-06-12 23:55:16 -04004636 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4637 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4638 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4639 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4640 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4641 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004642 default:
4643 return error(GL_INVALID_ENUM);
4644 }
4645
4646 switch(pname)
4647 {
4648 case GL_TEXTURE_WRAP_S:
4649 if(!texture->setWrapS((GLenum)param))
4650 {
4651 return error(GL_INVALID_ENUM);
4652 }
4653 break;
4654 case GL_TEXTURE_WRAP_T:
4655 if(!texture->setWrapT((GLenum)param))
4656 {
4657 return error(GL_INVALID_ENUM);
4658 }
4659 break;
4660 case GL_TEXTURE_WRAP_R_OES:
4661 if(!texture->setWrapR((GLenum)param))
4662 {
4663 return error(GL_INVALID_ENUM);
4664 }
4665 break;
4666 case GL_TEXTURE_MIN_FILTER:
4667 if(!texture->setMinFilter((GLenum)param))
4668 {
4669 return error(GL_INVALID_ENUM);
4670 }
4671 break;
4672 case GL_TEXTURE_MAG_FILTER:
4673 if(!texture->setMagFilter((GLenum)param))
4674 {
4675 return error(GL_INVALID_ENUM);
4676 }
4677 break;
4678 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4679 if(!texture->setMaxAnisotropy(param))
4680 {
4681 return error(GL_INVALID_VALUE);
4682 }
4683 break;
4684 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004685 if(!texture->setBaseLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004686 {
4687 return error(GL_INVALID_VALUE);
4688 }
4689 break;
4690 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004691 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004692 {
4693 return error(GL_INVALID_VALUE);
4694 }
4695 break;
4696 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004697 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004698 {
4699 return error(GL_INVALID_VALUE);
4700 }
4701 break;
4702 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004703 if(!texture->setMaxLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004704 {
4705 return error(GL_INVALID_VALUE);
4706 }
4707 break;
4708 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004709 if(!texture->setMaxLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004710 {
4711 return error(GL_INVALID_VALUE);
4712 }
4713 break;
4714 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004715 if(!texture->setMinLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004716 {
4717 return error(GL_INVALID_VALUE);
4718 }
4719 break;
4720 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004721 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004722 {
4723 return error(GL_INVALID_VALUE);
4724 }
4725 break;
4726 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004727 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004728 {
4729 return error(GL_INVALID_VALUE);
4730 }
4731 break;
4732 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004733 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004734 {
4735 return error(GL_INVALID_VALUE);
4736 }
4737 break;
4738 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004739 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004740 {
4741 return error(GL_INVALID_VALUE);
4742 }
4743 break;
4744 default:
4745 return error(GL_INVALID_ENUM);
4746 }
4747 }
4748}
4749
4750void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
4751{
4752 glTexParameterf(target, pname, *params);
4753}
4754
4755void TexParameteri(GLenum target, GLenum pname, GLint param)
4756{
4757 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
4758
Chris Forbes108f3e12018-08-30 19:41:59 -07004759 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004760
4761 if(context)
4762 {
4763 es2::Texture *texture;
4764
Nicolas Capens0bac2852016-05-07 06:09:58 -04004765 switch(target)
4766 {
Nicolas Capens83463112018-06-12 23:55:16 -04004767 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4768 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4769 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4770 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4771 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4772 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004773 default:
4774 return error(GL_INVALID_ENUM);
4775 }
4776
4777 switch(pname)
4778 {
4779 case GL_TEXTURE_WRAP_S:
4780 if(!texture->setWrapS((GLenum)param))
4781 {
4782 return error(GL_INVALID_ENUM);
4783 }
4784 break;
4785 case GL_TEXTURE_WRAP_T:
4786 if(!texture->setWrapT((GLenum)param))
4787 {
4788 return error(GL_INVALID_ENUM);
4789 }
4790 break;
4791 case GL_TEXTURE_WRAP_R_OES:
4792 if(!texture->setWrapR((GLenum)param))
4793 {
4794 return error(GL_INVALID_ENUM);
4795 }
4796 break;
4797 case GL_TEXTURE_MIN_FILTER:
4798 if(!texture->setMinFilter((GLenum)param))
4799 {
4800 return error(GL_INVALID_ENUM);
4801 }
4802 break;
4803 case GL_TEXTURE_MAG_FILTER:
4804 if(!texture->setMagFilter((GLenum)param))
4805 {
4806 return error(GL_INVALID_ENUM);
4807 }
4808 break;
4809 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4810 if(!texture->setMaxAnisotropy((GLfloat)param))
4811 {
4812 return error(GL_INVALID_VALUE);
4813 }
4814 break;
4815 case GL_TEXTURE_BASE_LEVEL:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004816 if((texture->getTarget() == GL_TEXTURE_RECTANGLE_ARB) && (param != 0))
4817 {
4818 return error(GL_INVALID_OPERATION); // Base level has to be 0
4819 }
Nicolas Capens83463112018-06-12 23:55:16 -04004820 if(!texture->setBaseLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004821 {
4822 return error(GL_INVALID_VALUE);
4823 }
4824 break;
4825 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004826 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004827 {
4828 return error(GL_INVALID_VALUE);
4829 }
4830 break;
4831 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004832 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004833 {
4834 return error(GL_INVALID_VALUE);
4835 }
4836 break;
4837 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004838 if(!texture->setMaxLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004839 {
4840 return error(GL_INVALID_VALUE);
4841 }
4842 break;
4843 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004844 if(!texture->setMaxLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004845 {
4846 return error(GL_INVALID_VALUE);
4847 }
4848 break;
4849 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004850 if(!texture->setMinLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004851 {
4852 return error(GL_INVALID_VALUE);
4853 }
4854 break;
4855 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004856 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004857 {
4858 return error(GL_INVALID_VALUE);
4859 }
4860 break;
4861 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004862 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004863 {
4864 return error(GL_INVALID_VALUE);
4865 }
4866 break;
4867 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004868 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004869 {
4870 return error(GL_INVALID_VALUE);
4871 }
4872 break;
4873 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004874 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004875 {
4876 return error(GL_INVALID_VALUE);
4877 }
4878 break;
4879 default:
4880 return error(GL_INVALID_ENUM);
4881 }
4882 }
4883}
4884
4885void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
4886{
4887 glTexParameteri(target, pname, *params);
4888}
4889
4890void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004891 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004892{
4893 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
4894 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004895 "const GLvoid* data = %p)",
4896 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004897
4898 if(!es2::IsTextureTarget(target))
4899 {
4900 return error(GL_INVALID_ENUM);
4901 }
4902
4903 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4904 {
4905 return error(GL_INVALID_VALUE);
4906 }
4907
4908 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
4909 {
4910 return error(GL_INVALID_VALUE);
4911 }
4912
4913 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
4914 {
4915 return error(GL_INVALID_VALUE);
4916 }
4917
Chris Forbes108f3e12018-08-30 19:41:59 -07004918 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004919
4920 if(context)
4921 {
Alexis Hetu46768622018-01-16 22:09:28 -05004922 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004923 {
Alexis Hetu46768622018-01-16 22:09:28 -05004924 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004925
Nicolas Capens83463112018-06-12 23:55:16 -04004926 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004927 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004928 {
4929 return error(validationError);
4930 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004931
Nicolas Capens5555af42017-12-14 13:14:03 -05004932 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004933 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004934 {
4935 return error(validationError);
4936 }
4937
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004938 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004939 }
4940 else if(es2::IsCubemapTextureTarget(target))
4941 {
4942 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4943
Nicolas Capens83463112018-06-12 23:55:16 -04004944 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004945 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004946 {
4947 return error(validationError);
4948 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004949
Nicolas Capens5555af42017-12-14 13:14:03 -05004950 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004951 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004952 {
4953 return error(validationError);
4954 }
4955
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004956 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004957 }
4958 else UNREACHABLE(target);
4959 }
4960}
4961
4962void Uniform1f(GLint location, GLfloat x)
4963{
4964 glUniform1fv(location, 1, &x);
4965}
4966
4967void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
4968{
4969 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
4970
4971 if(count < 0)
4972 {
4973 return error(GL_INVALID_VALUE);
4974 }
4975
Chris Forbes108f3e12018-08-30 19:41:59 -07004976 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004977
4978 if(context)
4979 {
4980 es2::Program *program = context->getCurrentProgram();
4981
4982 if(!program)
4983 {
4984 return error(GL_INVALID_OPERATION);
4985 }
4986
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004987 if(location == -1)
4988 {
4989 return;
4990 }
4991
Nicolas Capens0bac2852016-05-07 06:09:58 -04004992 if(!program->setUniform1fv(location, count, v))
4993 {
4994 return error(GL_INVALID_OPERATION);
4995 }
4996 }
4997}
4998
4999void Uniform1i(GLint location, GLint x)
5000{
5001 glUniform1iv(location, 1, &x);
5002}
5003
5004void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5005{
5006 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5007
5008 if(count < 0)
5009 {
5010 return error(GL_INVALID_VALUE);
5011 }
5012
Chris Forbes108f3e12018-08-30 19:41:59 -07005013 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005014
5015 if(context)
5016 {
5017 es2::Program *program = context->getCurrentProgram();
5018
5019 if(!program)
5020 {
5021 return error(GL_INVALID_OPERATION);
5022 }
5023
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005024 if(location == -1)
5025 {
5026 return;
5027 }
5028
Nicolas Capens0bac2852016-05-07 06:09:58 -04005029 if(!program->setUniform1iv(location, count, v))
5030 {
5031 return error(GL_INVALID_OPERATION);
5032 }
5033 }
5034}
5035
5036void Uniform2f(GLint location, GLfloat x, GLfloat y)
5037{
5038 GLfloat xy[2] = {x, y};
5039
5040 glUniform2fv(location, 1, (GLfloat*)&xy);
5041}
5042
5043void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5044{
5045 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5046
5047 if(count < 0)
5048 {
5049 return error(GL_INVALID_VALUE);
5050 }
5051
Chris Forbes108f3e12018-08-30 19:41:59 -07005052 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005053
5054 if(context)
5055 {
5056 es2::Program *program = context->getCurrentProgram();
5057
5058 if(!program)
5059 {
5060 return error(GL_INVALID_OPERATION);
5061 }
5062
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005063 if(location == -1)
5064 {
5065 return;
5066 }
5067
Nicolas Capens0bac2852016-05-07 06:09:58 -04005068 if(!program->setUniform2fv(location, count, v))
5069 {
5070 return error(GL_INVALID_OPERATION);
5071 }
5072 }
5073}
5074
5075void Uniform2i(GLint location, GLint x, GLint y)
5076{
5077 GLint xy[4] = {x, y};
5078
5079 glUniform2iv(location, 1, (GLint*)&xy);
5080}
5081
5082void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5083{
5084 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5085
5086 if(count < 0)
5087 {
5088 return error(GL_INVALID_VALUE);
5089 }
5090
Chris Forbes108f3e12018-08-30 19:41:59 -07005091 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005092
5093 if(context)
5094 {
5095 es2::Program *program = context->getCurrentProgram();
5096
5097 if(!program)
5098 {
5099 return error(GL_INVALID_OPERATION);
5100 }
5101
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005102 if(location == -1)
5103 {
5104 return;
5105 }
5106
Nicolas Capens0bac2852016-05-07 06:09:58 -04005107 if(!program->setUniform2iv(location, count, v))
5108 {
5109 return error(GL_INVALID_OPERATION);
5110 }
5111 }
5112}
5113
5114void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5115{
5116 GLfloat xyz[3] = {x, y, z};
5117
5118 glUniform3fv(location, 1, (GLfloat*)&xyz);
5119}
5120
5121void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5122{
5123 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5124
5125 if(count < 0)
5126 {
5127 return error(GL_INVALID_VALUE);
5128 }
5129
Chris Forbes108f3e12018-08-30 19:41:59 -07005130 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005131
5132 if(context)
5133 {
5134 es2::Program *program = context->getCurrentProgram();
5135
5136 if(!program)
5137 {
5138 return error(GL_INVALID_OPERATION);
5139 }
5140
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005141 if(location == -1)
5142 {
5143 return;
5144 }
5145
Nicolas Capens0bac2852016-05-07 06:09:58 -04005146 if(!program->setUniform3fv(location, count, v))
5147 {
5148 return error(GL_INVALID_OPERATION);
5149 }
5150 }
5151}
5152
5153void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5154{
5155 GLint xyz[3] = {x, y, z};
5156
5157 glUniform3iv(location, 1, (GLint*)&xyz);
5158}
5159
5160void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5161{
5162 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5163
5164 if(count < 0)
5165 {
5166 return error(GL_INVALID_VALUE);
5167 }
5168
Chris Forbes108f3e12018-08-30 19:41:59 -07005169 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005170
5171 if(context)
5172 {
5173 es2::Program *program = context->getCurrentProgram();
5174
5175 if(!program)
5176 {
5177 return error(GL_INVALID_OPERATION);
5178 }
5179
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005180 if(location == -1)
5181 {
5182 return;
5183 }
5184
Nicolas Capens0bac2852016-05-07 06:09:58 -04005185 if(!program->setUniform3iv(location, count, v))
5186 {
5187 return error(GL_INVALID_OPERATION);
5188 }
5189 }
5190}
5191
5192void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5193{
5194 GLfloat xyzw[4] = {x, y, z, w};
5195
5196 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5197}
5198
5199void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5200{
5201 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5202
5203 if(count < 0)
5204 {
5205 return error(GL_INVALID_VALUE);
5206 }
5207
Chris Forbes108f3e12018-08-30 19:41:59 -07005208 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005209
5210 if(context)
5211 {
5212 es2::Program *program = context->getCurrentProgram();
5213
5214 if(!program)
5215 {
5216 return error(GL_INVALID_OPERATION);
5217 }
5218
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005219 if(location == -1)
5220 {
5221 return;
5222 }
5223
Nicolas Capens0bac2852016-05-07 06:09:58 -04005224 if(!program->setUniform4fv(location, count, v))
5225 {
5226 return error(GL_INVALID_OPERATION);
5227 }
5228 }
5229}
5230
5231void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5232{
5233 GLint xyzw[4] = {x, y, z, w};
5234
5235 glUniform4iv(location, 1, (GLint*)&xyzw);
5236}
5237
5238void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5239{
5240 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5241
5242 if(count < 0)
5243 {
5244 return error(GL_INVALID_VALUE);
5245 }
5246
Chris Forbes108f3e12018-08-30 19:41:59 -07005247 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005248
5249 if(context)
5250 {
5251 es2::Program *program = context->getCurrentProgram();
5252
5253 if(!program)
5254 {
5255 return error(GL_INVALID_OPERATION);
5256 }
5257
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005258 if(location == -1)
5259 {
5260 return;
5261 }
5262
Nicolas Capens0bac2852016-05-07 06:09:58 -04005263 if(!program->setUniform4iv(location, count, v))
5264 {
5265 return error(GL_INVALID_OPERATION);
5266 }
5267 }
5268}
5269
5270void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5271{
5272 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5273 location, count, transpose, value);
5274
5275 if(count < 0)
5276 {
5277 return error(GL_INVALID_VALUE);
5278 }
5279
Chris Forbes108f3e12018-08-30 19:41:59 -07005280 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005281
5282 if(context)
5283 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005284 es2::Program *program = context->getCurrentProgram();
5285
5286 if(!program)
5287 {
5288 return error(GL_INVALID_OPERATION);
5289 }
5290
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005291 if(location == -1)
5292 {
5293 return;
5294 }
5295
Nicolas Capens0bac2852016-05-07 06:09:58 -04005296 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5297 {
5298 return error(GL_INVALID_OPERATION);
5299 }
5300 }
5301}
5302
5303void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5304{
5305 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5306 location, count, transpose, value);
5307
5308 if(count < 0)
5309 {
5310 return error(GL_INVALID_VALUE);
5311 }
5312
Chris Forbes108f3e12018-08-30 19:41:59 -07005313 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005314
5315 if(context)
5316 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005317 es2::Program *program = context->getCurrentProgram();
5318
5319 if(!program)
5320 {
5321 return error(GL_INVALID_OPERATION);
5322 }
5323
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005324 if(location == -1)
5325 {
5326 return;
5327 }
5328
Nicolas Capens0bac2852016-05-07 06:09:58 -04005329 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5330 {
5331 return error(GL_INVALID_OPERATION);
5332 }
5333 }
5334}
5335
5336void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5337{
5338 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5339 location, count, transpose, value);
5340
5341 if(count < 0)
5342 {
5343 return error(GL_INVALID_VALUE);
5344 }
5345
Chris Forbes108f3e12018-08-30 19:41:59 -07005346 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005347
5348 if(context)
5349 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005350 es2::Program *program = context->getCurrentProgram();
5351
5352 if(!program)
5353 {
5354 return error(GL_INVALID_OPERATION);
5355 }
5356
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005357 if(location == -1)
5358 {
5359 return;
5360 }
5361
Nicolas Capens0bac2852016-05-07 06:09:58 -04005362 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5363 {
5364 return error(GL_INVALID_OPERATION);
5365 }
5366 }
5367}
5368
5369void UseProgram(GLuint program)
5370{
5371 TRACE("(GLuint program = %d)", program);
5372
Chris Forbes108f3e12018-08-30 19:41:59 -07005373 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005374
5375 if(context)
5376 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005377 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5378 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5379 {
5380 return error(GL_INVALID_OPERATION);
5381 }
5382
Nicolas Capens0bac2852016-05-07 06:09:58 -04005383 es2::Program *programObject = context->getProgram(program);
5384
5385 if(!programObject && program != 0)
5386 {
5387 if(context->getShader(program))
5388 {
5389 return error(GL_INVALID_OPERATION);
5390 }
5391 else
5392 {
5393 return error(GL_INVALID_VALUE);
5394 }
5395 }
5396
5397 if(program != 0 && !programObject->isLinked())
5398 {
5399 return error(GL_INVALID_OPERATION);
5400 }
5401
5402 context->useProgram(program);
5403 }
5404}
5405
5406void ValidateProgram(GLuint program)
5407{
5408 TRACE("(GLuint program = %d)", program);
5409
Chris Forbes108f3e12018-08-30 19:41:59 -07005410 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005411
5412 if(context)
5413 {
5414 es2::Program *programObject = context->getProgram(program);
5415
5416 if(!programObject)
5417 {
5418 if(context->getShader(program))
5419 {
5420 return error(GL_INVALID_OPERATION);
5421 }
5422 else
5423 {
5424 return error(GL_INVALID_VALUE);
5425 }
5426 }
5427
Ben Vanik1fd3b282017-07-10 14:08:12 -07005428 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005429 }
5430}
5431
5432void VertexAttrib1f(GLuint index, GLfloat x)
5433{
5434 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5435
5436 if(index >= es2::MAX_VERTEX_ATTRIBS)
5437 {
5438 return error(GL_INVALID_VALUE);
5439 }
5440
Chris Forbes108f3e12018-08-30 19:41:59 -07005441 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005442
5443 if(context)
5444 {
5445 GLfloat vals[4] = { x, 0, 0, 1 };
5446 context->setVertexAttrib(index, vals);
5447 }
5448}
5449
5450void VertexAttrib1fv(GLuint index, const GLfloat* values)
5451{
5452 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5453
5454 if(index >= es2::MAX_VERTEX_ATTRIBS)
5455 {
5456 return error(GL_INVALID_VALUE);
5457 }
5458
Chris Forbes108f3e12018-08-30 19:41:59 -07005459 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005460
5461 if(context)
5462 {
5463 GLfloat vals[4] = { values[0], 0, 0, 1 };
5464 context->setVertexAttrib(index, vals);
5465 }
5466}
5467
5468void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5469{
5470 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5471
5472 if(index >= es2::MAX_VERTEX_ATTRIBS)
5473 {
5474 return error(GL_INVALID_VALUE);
5475 }
5476
Chris Forbes108f3e12018-08-30 19:41:59 -07005477 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005478
5479 if(context)
5480 {
5481 GLfloat vals[4] = { x, y, 0, 1 };
5482 context->setVertexAttrib(index, vals);
5483 }
5484}
5485
5486void VertexAttrib2fv(GLuint index, const GLfloat* values)
5487{
5488 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5489
5490 if(index >= es2::MAX_VERTEX_ATTRIBS)
5491 {
5492 return error(GL_INVALID_VALUE);
5493 }
5494
Chris Forbes108f3e12018-08-30 19:41:59 -07005495 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005496
5497 if(context)
5498 {
5499 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5500 context->setVertexAttrib(index, vals);
5501 }
5502}
5503
5504void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5505{
5506 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5507
5508 if(index >= es2::MAX_VERTEX_ATTRIBS)
5509 {
5510 return error(GL_INVALID_VALUE);
5511 }
5512
Chris Forbes108f3e12018-08-30 19:41:59 -07005513 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005514
5515 if(context)
5516 {
5517 GLfloat vals[4] = { x, y, z, 1 };
5518 context->setVertexAttrib(index, vals);
5519 }
5520}
5521
5522void VertexAttrib3fv(GLuint index, const GLfloat* values)
5523{
5524 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5525
5526 if(index >= es2::MAX_VERTEX_ATTRIBS)
5527 {
5528 return error(GL_INVALID_VALUE);
5529 }
5530
Chris Forbes108f3e12018-08-30 19:41:59 -07005531 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005532
5533 if(context)
5534 {
5535 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
5536 context->setVertexAttrib(index, vals);
5537 }
5538}
5539
5540void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5541{
5542 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
5543
5544 if(index >= es2::MAX_VERTEX_ATTRIBS)
5545 {
5546 return error(GL_INVALID_VALUE);
5547 }
5548
Chris Forbes108f3e12018-08-30 19:41:59 -07005549 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005550
5551 if(context)
5552 {
5553 GLfloat vals[4] = { x, y, z, w };
5554 context->setVertexAttrib(index, vals);
5555 }
5556}
5557
5558void VertexAttrib4fv(GLuint index, const GLfloat* values)
5559{
5560 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5561
5562 if(index >= es2::MAX_VERTEX_ATTRIBS)
5563 {
5564 return error(GL_INVALID_VALUE);
5565 }
5566
Chris Forbes108f3e12018-08-30 19:41:59 -07005567 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005568
5569 if(context)
5570 {
5571 context->setVertexAttrib(index, values);
5572 }
5573}
5574
5575void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
5576{
5577 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
5578 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
5579 index, size, type, normalized, stride, ptr);
5580
5581 if(index >= es2::MAX_VERTEX_ATTRIBS)
5582 {
5583 return error(GL_INVALID_VALUE);
5584 }
5585
5586 if(size < 1 || size > 4)
5587 {
5588 return error(GL_INVALID_VALUE);
5589 }
5590
Nicolas Capens0bac2852016-05-07 06:09:58 -04005591 switch(type)
5592 {
5593 case GL_BYTE:
5594 case GL_UNSIGNED_BYTE:
5595 case GL_SHORT:
5596 case GL_UNSIGNED_SHORT:
5597 case GL_FIXED:
5598 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04005599 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capensce8eb942018-04-26 16:38:05 -04005600 case GL_HALF_FLOAT:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005601 break;
5602 case GL_INT_2_10_10_10_REV:
5603 case GL_UNSIGNED_INT_2_10_10_10_REV:
Nicolas Capens83463112018-06-12 23:55:16 -04005604 if(size != 4)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005605 {
Nicolas Capens83463112018-06-12 23:55:16 -04005606 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005607 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04005608 case GL_INT:
5609 case GL_UNSIGNED_INT:
Nicolas Capens83463112018-06-12 23:55:16 -04005610 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005611 default:
5612 return error(GL_INVALID_ENUM);
5613 }
5614
5615 if(stride < 0)
5616 {
5617 return error(GL_INVALID_VALUE);
5618 }
5619
Chris Forbes108f3e12018-08-30 19:41:59 -07005620 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005621
5622 if(context)
5623 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05005624 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
5625 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
5626 {
5627 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
5628 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
5629 return error(GL_INVALID_OPERATION);
5630 }
5631
Nicolas Capens51814272018-10-15 13:01:22 -04005632 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized != GL_FALSE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005633 }
5634}
5635
5636void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
5637{
5638 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
5639
5640 if(width < 0 || height < 0)
5641 {
5642 return error(GL_INVALID_VALUE);
5643 }
5644
Chris Forbes108f3e12018-08-30 19:41:59 -07005645 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005646
5647 if(context)
5648 {
5649 context->setViewportParams(x, y, width, height);
5650 }
5651}
5652
Alexis Hetub9dda642016-10-06 11:25:32 -04005653static void BlitFramebuffer(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 -04005654{
5655 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
5656 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
5657 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
5658 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5659
5660 switch(filter)
5661 {
5662 case GL_NEAREST:
5663 break;
5664 default:
5665 return error(GL_INVALID_ENUM);
5666 }
5667
5668 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
5669 {
5670 return error(GL_INVALID_VALUE);
5671 }
5672
Chris Forbes108f3e12018-08-30 19:41:59 -07005673 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005674
5675 if(context)
5676 {
5677 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
5678 {
5679 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
5680 return error(GL_INVALID_OPERATION);
5681 }
5682
Alexis Hetub9dda642016-10-06 11:25:32 -04005683 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005684 }
5685}
5686
Alexis Hetub9dda642016-10-06 11:25:32 -04005687void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
5688{
5689 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
5690}
5691
Nicolas Capens0bac2852016-05-07 06:09:58 -04005692void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5693 GLbitfield mask, GLenum filter)
5694{
5695 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
5696 {
5697 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
5698 return error(GL_INVALID_OPERATION);
5699 }
5700
Alexis Hetub9dda642016-10-06 11:25:32 -04005701 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005702}
5703
5704void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04005705 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005706{
5707 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
5708 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005709 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5710 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005711
5712 switch(target)
5713 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005714 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005715 switch(format)
5716 {
5717 case GL_DEPTH_COMPONENT:
5718 case GL_DEPTH_STENCIL_OES:
5719 return error(GL_INVALID_OPERATION);
5720 default:
5721 break;
5722 }
5723 break;
5724 default:
5725 return error(GL_INVALID_ENUM);
5726 }
5727
Nicolas Capensc61f46b2017-12-04 16:07:22 -05005728 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005729 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005730 return error(GL_INVALID_OPERATION);
5731 }
5732
Nicolas Capens83463112018-06-12 23:55:16 -04005733 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05005734 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005735 {
5736 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005737 }
5738
5739 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5740 {
5741 return error(GL_INVALID_VALUE);
5742 }
5743
Nicolas Capensefdf1032018-05-08 16:03:16 -04005744 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005745 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
5746 {
5747 return error(GL_INVALID_VALUE);
5748 }
5749
5750 if(border != 0)
5751 {
5752 return error(GL_INVALID_VALUE);
5753 }
5754
Chris Forbes108f3e12018-08-30 19:41:59 -07005755 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005756
5757 if(context)
5758 {
5759 es2::Texture3D *texture = context->getTexture3D();
5760
5761 if(!texture)
5762 {
5763 return error(GL_INVALID_OPERATION);
5764 }
5765
Nicolas Capens2fc90512018-01-23 22:24:22 +00005766 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005767 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005768 {
5769 return error(validationError);
5770 }
5771
Nicolas Capens894858a2018-03-22 00:55:23 -04005772 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005773 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005774 }
5775}
5776
Alexis Hetu53f48092016-06-17 14:08:06 -04005777void 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 -04005778{
5779 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5780 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005781 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5782 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005783
5784 switch(target)
5785 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005786 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005787 break;
5788 default:
5789 return error(GL_INVALID_ENUM);
5790 }
5791
Nicolas Capens0bac2852016-05-07 06:09:58 -04005792 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5793 {
5794 return error(GL_INVALID_VALUE);
5795 }
5796
5797 if((width < 0) || (height < 0) || (depth < 0))
5798 {
5799 return error(GL_INVALID_VALUE);
5800 }
5801
Chris Forbes108f3e12018-08-30 19:41:59 -07005802 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005803
5804 if(context)
5805 {
5806 es2::Texture3D *texture = context->getTexture3D();
5807
Nicolas Capens83463112018-06-12 23:55:16 -04005808 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05005809 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005810 {
5811 return error(validationError);
5812 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005813
Nicolas Capens5555af42017-12-14 13:14:03 -05005814 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005815 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005816 {
5817 return error(validationError);
5818 }
5819
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005820 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005821 }
5822}
5823
5824void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
5825{
5826 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5827 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
5828 target, level, xoffset, yoffset, zoffset, x, y, width, height);
5829
5830 switch(target)
5831 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005832 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005833 break;
5834 default:
5835 return error(GL_INVALID_ENUM);
5836 }
5837
5838 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5839 {
5840 return error(GL_INVALID_VALUE);
5841 }
5842
Chris Forbes108f3e12018-08-30 19:41:59 -07005843 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005844
5845 if(context)
5846 {
5847 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
5848
Alexis Hetu5cd502b2018-03-22 08:29:31 -04005849 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005850 {
5851 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
5852 }
5853
5854 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
5855
5856 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
5857 {
5858 return error(GL_INVALID_OPERATION);
5859 }
5860
5861 es2::Texture3D *texture = context->getTexture3D();
5862
Nicolas Capens83463112018-06-12 23:55:16 -04005863 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 -05005864 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005865 {
5866 return error(validationError);
5867 }
5868
Nicolas Capens1529c2c2018-02-06 14:44:47 -05005869 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005870 }
5871}
5872
5873void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
5874{
5875 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
5876 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
5877 target, level, internalformat, width, height, depth, border, imageSize, data);
5878
5879 switch(target)
5880 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005881 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005882 break;
5883 default:
5884 return error(GL_INVALID_ENUM);
5885 }
5886
5887 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5888 {
5889 return error(GL_INVALID_VALUE);
5890 }
5891
Nicolas Capensefdf1032018-05-08 16:03:16 -04005892 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005893 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
5894 {
5895 return error(GL_INVALID_VALUE);
5896 }
5897
Nicolas Capens83463112018-06-12 23:55:16 -04005898 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005899 {
Nicolas Capens03589982018-02-01 17:28:32 -05005900 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005901 }
5902
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005903 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005904 {
5905 return error(GL_INVALID_VALUE);
5906 }
5907
Chris Forbes108f3e12018-08-30 19:41:59 -07005908 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005909
5910 if(context)
5911 {
5912 es2::Texture3D *texture = context->getTexture3D();
5913
5914 if(!texture)
5915 {
5916 return error(GL_INVALID_OPERATION);
5917 }
5918
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005919 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005920
Nicolas Capense65f5642018-02-26 17:47:06 -05005921 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005922 {
5923 return error(validationError);
5924 }
5925
Nicolas Capens0bac2852016-05-07 06:09:58 -04005926 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
5927 }
5928}
5929
5930void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
5931{
5932 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5933 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
5934 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
5935 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
5936
5937 switch(target)
5938 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005939 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005940 break;
5941 default:
5942 return error(GL_INVALID_ENUM);
5943 }
5944
5945 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5946 {
5947 return error(GL_INVALID_VALUE);
5948 }
5949
5950 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
5951 {
5952 return error(GL_INVALID_VALUE);
5953 }
5954
Nicolas Capens83463112018-06-12 23:55:16 -04005955 if(!IsCompressed(format))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005956 {
Nicolas Capens03589982018-02-01 17:28:32 -05005957 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005958 }
5959
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005960 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005961 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05005962 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005963 }
5964
Chris Forbes108f3e12018-08-30 19:41:59 -07005965 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005966
5967 if(context)
5968 {
5969 es2::Texture3D *texture = context->getTexture3D();
5970
5971 if(!texture)
5972 {
5973 return error(GL_INVALID_OPERATION);
5974 }
5975
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005976 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -05005977 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005978 {
5979 return error(validationError);
5980 }
5981
5982 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005983 }
5984}
5985
5986void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
5987{
5988 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
5989 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
5990
Nicolas Capens6c4564a2018-01-26 01:14:34 +00005991 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005992 {
5993 return error(GL_INVALID_ENUM);
5994 }
5995
Chris Forbes108f3e12018-08-30 19:41:59 -07005996 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005997
5998 if(context)
5999 {
6000 if(texture == 0)
6001 {
6002 textarget = GL_NONE;
6003 }
6004 else
6005 {
6006 es2::Texture *tex = context->getTexture(texture);
6007
6008 if(!tex)
6009 {
6010 return error(GL_INVALID_OPERATION);
6011 }
6012
Nicolas Capens0bac2852016-05-07 06:09:58 -04006013 switch(textarget)
6014 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006015 case GL_TEXTURE_3D:
6016 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006017 {
6018 return error(GL_INVALID_OPERATION);
6019 }
6020 break;
6021 default:
6022 return error(GL_INVALID_ENUM);
6023 }
6024
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006025 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006026 {
6027 return error(GL_INVALID_VALUE);
6028 }
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006029
6030 if(tex->isCompressed(textarget, level))
6031 {
6032 return error(GL_INVALID_OPERATION);
6033 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006034 }
6035
6036 es2::Framebuffer *framebuffer = nullptr;
6037 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006038 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006039 {
6040 framebuffer = context->getReadFramebuffer();
6041 framebufferName = context->getReadFramebufferName();
6042 }
6043 else
6044 {
6045 framebuffer = context->getDrawFramebuffer();
6046 framebufferName = context->getDrawFramebufferName();
6047 }
6048
6049 if(framebufferName == 0 || !framebuffer)
6050 {
6051 return error(GL_INVALID_OPERATION);
6052 }
6053
Nicolas Capens0bac2852016-05-07 06:09:58 -04006054 switch(attachment)
6055 {
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006056 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
6057 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
Nicolas Capens83463112018-06-12 23:55:16 -04006058 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006059 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6060 {
6061 return error(GL_INVALID_ENUM);
6062 }
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006063 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006064 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006065 }
6066 }
6067}
6068
6069void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6070{
6071 if(egl::getClientVersion() == 1)
6072 {
6073 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6074 }
6075
6076 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6077
6078 switch(target)
6079 {
6080 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006081 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006082 case GL_TEXTURE_EXTERNAL_OES:
6083 break;
6084 default:
6085 return error(GL_INVALID_ENUM);
6086 }
6087
Chris Forbes108f3e12018-08-30 19:41:59 -07006088 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006089
6090 if(context)
6091 {
Alexis Hetu46768622018-01-16 22:09:28 -05006092 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006093
6094 if(!texture)
6095 {
6096 return error(GL_INVALID_OPERATION);
6097 }
6098
Nicolas Capens58df2f62016-06-07 14:48:56 -04006099 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006100
Nicolas Capens58df2f62016-06-07 14:48:56 -04006101 if(!eglImage)
6102 {
6103 return error(GL_INVALID_OPERATION);
6104 }
6105
6106 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006107 }
6108}
6109
6110void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6111{
6112 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6113
6114 UNIMPLEMENTED();
6115}
6116
6117GLboolean IsRenderbufferOES(GLuint renderbuffer)
6118{
6119 return IsRenderbuffer(renderbuffer);
6120}
6121
6122void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6123{
6124 BindRenderbuffer(target, renderbuffer);
6125}
6126
6127void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6128{
6129 DeleteRenderbuffers(n, renderbuffers);
6130}
6131
6132void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6133{
6134 GenRenderbuffers(n, renderbuffers);
6135}
6136
6137void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6138{
6139 RenderbufferStorage(target, internalformat, width, height);
6140}
6141
6142void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6143{
6144 GetRenderbufferParameteriv(target, pname, params);
6145}
6146
6147GLboolean IsFramebufferOES(GLuint framebuffer)
6148{
6149 return IsFramebuffer(framebuffer);
6150}
6151
6152void BindFramebufferOES(GLenum target, GLuint framebuffer)
6153{
6154 BindFramebuffer(target, framebuffer);
6155}
6156
6157void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6158{
6159 DeleteFramebuffers(n, framebuffers);
6160}
6161
6162void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6163{
6164 GenFramebuffers(n, framebuffers);
6165}
6166
6167GLenum CheckFramebufferStatusOES(GLenum target)
6168{
6169 return CheckFramebufferStatus(target);
6170}
6171
6172void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6173{
6174 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6175}
6176
6177void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6178{
6179 FramebufferTexture2D(target, attachment, textarget, texture, level);
6180}
6181
6182void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6183{
6184 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6185}
6186
6187void GenerateMipmapOES(GLenum target)
6188{
6189 GenerateMipmap(target);
6190}
6191
6192void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6193{
6194 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6195
6196 if(n < 0 || n > MAX_DRAW_BUFFERS)
6197 {
6198 return error(GL_INVALID_VALUE);
6199 }
6200
Chris Forbes108f3e12018-08-30 19:41:59 -07006201 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006202
6203 if(context)
6204 {
6205 GLuint drawFramebufferName = context->getDrawFramebufferName();
6206
6207 if((drawFramebufferName == 0) && (n != 1))
6208 {
6209 return error(GL_INVALID_OPERATION);
6210 }
6211
6212 for(unsigned int i = 0; i < (unsigned)n; i++)
6213 {
6214 switch(bufs[i])
6215 {
6216 case GL_BACK:
6217 if(drawFramebufferName != 0)
6218 {
6219 return error(GL_INVALID_OPERATION);
6220 }
6221 break;
6222 case GL_NONE:
6223 break;
6224 case GL_COLOR_ATTACHMENT0_EXT:
6225 case GL_COLOR_ATTACHMENT1_EXT:
6226 case GL_COLOR_ATTACHMENT2_EXT:
6227 case GL_COLOR_ATTACHMENT3_EXT:
6228 case GL_COLOR_ATTACHMENT4_EXT:
6229 case GL_COLOR_ATTACHMENT5_EXT:
6230 case GL_COLOR_ATTACHMENT6_EXT:
6231 case GL_COLOR_ATTACHMENT7_EXT:
6232 case GL_COLOR_ATTACHMENT8_EXT:
6233 case GL_COLOR_ATTACHMENT9_EXT:
6234 case GL_COLOR_ATTACHMENT10_EXT:
6235 case GL_COLOR_ATTACHMENT11_EXT:
6236 case GL_COLOR_ATTACHMENT12_EXT:
6237 case GL_COLOR_ATTACHMENT13_EXT:
6238 case GL_COLOR_ATTACHMENT14_EXT:
6239 case GL_COLOR_ATTACHMENT15_EXT:
6240 {
6241 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6242
6243 if(index >= MAX_COLOR_ATTACHMENTS)
6244 {
6245 return error(GL_INVALID_OPERATION);
6246 }
6247
6248 if(index != i)
6249 {
6250 return error(GL_INVALID_OPERATION);
6251 }
6252
6253 if(drawFramebufferName == 0)
6254 {
6255 return error(GL_INVALID_OPERATION);
6256 }
6257 }
6258 break;
6259 default:
6260 return error(GL_INVALID_ENUM);
6261 }
6262 }
6263
6264 context->setFramebufferDrawBuffers(n, bufs);
6265 }
6266}
6267
6268}
6269
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006270extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006271{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006272 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006273 {
6274 const char *name;
6275 __eglMustCastToProperFunctionPointerType address;
6276 };
6277
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006278 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006279 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006280 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6281
6282 FUNCTION(glActiveTexture),
6283 FUNCTION(glAttachShader),
6284 FUNCTION(glBeginQuery),
6285 FUNCTION(glBeginQueryEXT),
6286 FUNCTION(glBeginTransformFeedback),
6287 FUNCTION(glBindAttribLocation),
6288 FUNCTION(glBindBuffer),
6289 FUNCTION(glBindBufferBase),
6290 FUNCTION(glBindBufferRange),
6291 FUNCTION(glBindFramebuffer),
6292 FUNCTION(glBindFramebufferOES),
6293 FUNCTION(glBindRenderbuffer),
6294 FUNCTION(glBindRenderbufferOES),
6295 FUNCTION(glBindSampler),
6296 FUNCTION(glBindTexture),
6297 FUNCTION(glBindTransformFeedback),
6298 FUNCTION(glBindVertexArray),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006299 FUNCTION(glBindVertexArrayOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006300 FUNCTION(glBlendColor),
6301 FUNCTION(glBlendEquation),
6302 FUNCTION(glBlendEquationSeparate),
6303 FUNCTION(glBlendFunc),
6304 FUNCTION(glBlendFuncSeparate),
6305 FUNCTION(glBlitFramebuffer),
6306 FUNCTION(glBlitFramebufferANGLE),
6307 FUNCTION(glBufferData),
6308 FUNCTION(glBufferSubData),
6309 FUNCTION(glCheckFramebufferStatus),
6310 FUNCTION(glCheckFramebufferStatusOES),
6311 FUNCTION(glClear),
6312 FUNCTION(glClearBufferfi),
6313 FUNCTION(glClearBufferfv),
6314 FUNCTION(glClearBufferiv),
6315 FUNCTION(glClearBufferuiv),
6316 FUNCTION(glClearColor),
6317 FUNCTION(glClearDepthf),
6318 FUNCTION(glClearStencil),
6319 FUNCTION(glClientWaitSync),
6320 FUNCTION(glColorMask),
6321 FUNCTION(glCompileShader),
6322 FUNCTION(glCompressedTexImage2D),
6323 FUNCTION(glCompressedTexImage3D),
6324 FUNCTION(glCompressedTexSubImage2D),
6325 FUNCTION(glCompressedTexSubImage3D),
6326 FUNCTION(glCopyBufferSubData),
6327 FUNCTION(glCopyTexImage2D),
6328 FUNCTION(glCopyTexSubImage2D),
6329 FUNCTION(glCopyTexSubImage3D),
6330 FUNCTION(glCreateProgram),
6331 FUNCTION(glCreateShader),
6332 FUNCTION(glCullFace),
6333 FUNCTION(glDeleteBuffers),
6334 FUNCTION(glDeleteFencesNV),
6335 FUNCTION(glDeleteFramebuffers),
6336 FUNCTION(glDeleteFramebuffersOES),
6337 FUNCTION(glDeleteProgram),
6338 FUNCTION(glDeleteQueries),
6339 FUNCTION(glDeleteQueriesEXT),
6340 FUNCTION(glDeleteRenderbuffers),
6341 FUNCTION(glDeleteRenderbuffersOES),
6342 FUNCTION(glDeleteSamplers),
6343 FUNCTION(glDeleteShader),
6344 FUNCTION(glDeleteSync),
6345 FUNCTION(glDeleteTextures),
6346 FUNCTION(glDeleteTransformFeedbacks),
6347 FUNCTION(glDeleteVertexArrays),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006348 FUNCTION(glDeleteVertexArraysOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006349 FUNCTION(glDepthFunc),
Nicolas Capens659d89e2018-06-22 13:57:37 -04006350 //FUNCTION(DepthFunc),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006351 FUNCTION(glDepthMask),
6352 FUNCTION(glDepthRangef),
6353 FUNCTION(glDetachShader),
6354 FUNCTION(glDisable),
6355 FUNCTION(glDisableVertexAttribArray),
6356 FUNCTION(glDrawArrays),
6357 FUNCTION(glDrawArraysInstanced),
6358 FUNCTION(glDrawBuffers),
6359 FUNCTION(glDrawBuffersEXT),
6360 FUNCTION(glDrawElements),
6361 FUNCTION(glDrawElementsInstanced),
6362 FUNCTION(glDrawRangeElements),
6363 FUNCTION(glEGLImageTargetRenderbufferStorageOES),
6364 FUNCTION(glEGLImageTargetTexture2DOES),
6365 FUNCTION(glEnable),
6366 FUNCTION(glEnableVertexAttribArray),
6367 FUNCTION(glEndQuery),
6368 FUNCTION(glEndQueryEXT),
6369 FUNCTION(glEndTransformFeedback),
6370 FUNCTION(glFenceSync),
6371 FUNCTION(glFinish),
6372 FUNCTION(glFinishFenceNV),
6373 FUNCTION(glFlush),
6374 FUNCTION(glFlushMappedBufferRange),
6375 FUNCTION(glFramebufferRenderbuffer),
6376 FUNCTION(glFramebufferRenderbufferOES),
6377 FUNCTION(glFramebufferTexture2D),
6378 FUNCTION(glFramebufferTexture2DOES),
6379 FUNCTION(glFramebufferTextureLayer),
6380 FUNCTION(glFrontFace),
6381 FUNCTION(glGenBuffers),
6382 FUNCTION(glGenFencesNV),
6383 FUNCTION(glGenFramebuffers),
6384 FUNCTION(glGenFramebuffersOES),
6385 FUNCTION(glGenQueries),
6386 FUNCTION(glGenQueriesEXT),
6387 FUNCTION(glGenRenderbuffers),
6388 FUNCTION(glGenRenderbuffersOES),
6389 FUNCTION(glGenSamplers),
6390 FUNCTION(glGenTextures),
6391 FUNCTION(glGenTransformFeedbacks),
6392 FUNCTION(glGenVertexArrays),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006393 FUNCTION(glGenVertexArraysOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006394 FUNCTION(glGenerateMipmap),
6395 FUNCTION(glGenerateMipmapOES),
6396 FUNCTION(glGetActiveAttrib),
6397 FUNCTION(glGetActiveUniform),
6398 FUNCTION(glGetActiveUniformBlockName),
6399 FUNCTION(glGetActiveUniformBlockiv),
6400 FUNCTION(glGetActiveUniformsiv),
6401 FUNCTION(glGetAttachedShaders),
6402 FUNCTION(glGetAttribLocation),
6403 FUNCTION(glGetBooleanv),
6404 FUNCTION(glGetBufferParameteri64v),
6405 FUNCTION(glGetBufferParameteriv),
6406 FUNCTION(glGetBufferPointerv),
6407 FUNCTION(glGetError),
6408 FUNCTION(glGetFenceivNV),
6409 FUNCTION(glGetFloatv),
6410 FUNCTION(glGetFragDataLocation),
6411 FUNCTION(glGetFramebufferAttachmentParameteriv),
6412 FUNCTION(glGetFramebufferAttachmentParameterivOES),
6413 FUNCTION(glGetGraphicsResetStatusEXT),
6414 FUNCTION(glGetInteger64i_v),
6415 FUNCTION(glGetInteger64v),
6416 FUNCTION(glGetIntegeri_v),
6417 FUNCTION(glGetIntegerv),
6418 FUNCTION(glGetInternalformativ),
6419 FUNCTION(glGetProgramBinary),
6420 FUNCTION(glGetProgramInfoLog),
6421 FUNCTION(glGetProgramiv),
6422 FUNCTION(glGetQueryObjectuiv),
6423 FUNCTION(glGetQueryObjectuivEXT),
6424 FUNCTION(glGetQueryiv),
6425 FUNCTION(glGetQueryivEXT),
6426 FUNCTION(glGetRenderbufferParameteriv),
6427 FUNCTION(glGetRenderbufferParameterivOES),
6428 FUNCTION(glGetSamplerParameterfv),
6429 FUNCTION(glGetSamplerParameteriv),
6430 FUNCTION(glGetShaderInfoLog),
6431 FUNCTION(glGetShaderPrecisionFormat),
6432 FUNCTION(glGetShaderSource),
6433 FUNCTION(glGetShaderiv),
6434 FUNCTION(glGetString),
6435 FUNCTION(glGetStringi),
6436 FUNCTION(glGetSynciv),
6437 FUNCTION(glGetTexParameterfv),
6438 FUNCTION(glGetTexParameteriv),
6439 FUNCTION(glGetTransformFeedbackVarying),
6440 FUNCTION(glGetUniformBlockIndex),
6441 FUNCTION(glGetUniformIndices),
6442 FUNCTION(glGetUniformLocation),
6443 FUNCTION(glGetUniformfv),
6444 FUNCTION(glGetUniformiv),
6445 FUNCTION(glGetUniformuiv),
6446 FUNCTION(glGetVertexAttribIiv),
6447 FUNCTION(glGetVertexAttribIuiv),
6448 FUNCTION(glGetVertexAttribPointerv),
6449 FUNCTION(glGetVertexAttribfv),
6450 FUNCTION(glGetVertexAttribiv),
6451 FUNCTION(glGetnUniformfvEXT),
6452 FUNCTION(glGetnUniformivEXT),
6453 FUNCTION(glHint),
6454 FUNCTION(glInvalidateFramebuffer),
6455 FUNCTION(glInvalidateSubFramebuffer),
6456 FUNCTION(glIsBuffer),
6457 FUNCTION(glIsEnabled),
6458 FUNCTION(glIsFenceNV),
6459 FUNCTION(glIsFramebuffer),
6460 FUNCTION(glIsFramebufferOES),
6461 FUNCTION(glIsProgram),
6462 FUNCTION(glIsQuery),
6463 FUNCTION(glIsQueryEXT),
6464 FUNCTION(glIsRenderbuffer),
6465 FUNCTION(glIsRenderbufferOES),
6466 FUNCTION(glIsSampler),
6467 FUNCTION(glIsShader),
6468 FUNCTION(glIsSync),
6469 FUNCTION(glIsTexture),
6470 FUNCTION(glIsTransformFeedback),
6471 FUNCTION(glIsVertexArray),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006472 FUNCTION(glIsVertexArrayOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006473 FUNCTION(glLineWidth),
6474 FUNCTION(glLinkProgram),
6475 FUNCTION(glMapBufferRange),
6476 FUNCTION(glPauseTransformFeedback),
6477 FUNCTION(glPixelStorei),
6478 FUNCTION(glPolygonOffset),
6479 FUNCTION(glProgramBinary),
6480 FUNCTION(glProgramParameteri),
6481 FUNCTION(glReadBuffer),
6482 FUNCTION(glReadPixels),
6483 FUNCTION(glReadnPixelsEXT),
6484 FUNCTION(glReleaseShaderCompiler),
6485 FUNCTION(glRenderbufferStorage),
6486 FUNCTION(glRenderbufferStorageMultisample),
6487 FUNCTION(glRenderbufferStorageMultisampleANGLE),
6488 FUNCTION(glRenderbufferStorageOES),
6489 FUNCTION(glResumeTransformFeedback),
6490 FUNCTION(glSampleCoverage),
6491 FUNCTION(glSamplerParameterf),
6492 FUNCTION(glSamplerParameterfv),
6493 FUNCTION(glSamplerParameteri),
6494 FUNCTION(glSamplerParameteriv),
6495 FUNCTION(glScissor),
6496 FUNCTION(glSetFenceNV),
6497 FUNCTION(glShaderBinary),
6498 FUNCTION(glShaderSource),
6499 FUNCTION(glStencilFunc),
6500 FUNCTION(glStencilFuncSeparate),
6501 FUNCTION(glStencilMask),
6502 FUNCTION(glStencilMaskSeparate),
6503 FUNCTION(glStencilOp),
6504 FUNCTION(glStencilOpSeparate),
6505 FUNCTION(glTestFenceNV),
6506 FUNCTION(glTexImage2D),
6507 FUNCTION(glTexImage3D),
6508 FUNCTION(glTexImage3DOES),
6509 FUNCTION(glTexParameterf),
6510 FUNCTION(glTexParameterfv),
6511 FUNCTION(glTexParameteri),
6512 FUNCTION(glTexParameteriv),
6513 FUNCTION(glTexStorage2D),
6514 FUNCTION(glTexStorage3D),
6515 FUNCTION(glTexSubImage2D),
6516 FUNCTION(glTexSubImage3D),
6517 FUNCTION(glTransformFeedbackVaryings),
6518 FUNCTION(glUniform1f),
6519 FUNCTION(glUniform1fv),
6520 FUNCTION(glUniform1i),
6521 FUNCTION(glUniform1iv),
6522 FUNCTION(glUniform1ui),
6523 FUNCTION(glUniform1uiv),
6524 FUNCTION(glUniform2f),
6525 FUNCTION(glUniform2fv),
6526 FUNCTION(glUniform2i),
6527 FUNCTION(glUniform2iv),
6528 FUNCTION(glUniform2ui),
6529 FUNCTION(glUniform2uiv),
6530 FUNCTION(glUniform3f),
6531 FUNCTION(glUniform3fv),
6532 FUNCTION(glUniform3i),
6533 FUNCTION(glUniform3iv),
6534 FUNCTION(glUniform3ui),
6535 FUNCTION(glUniform3uiv),
6536 FUNCTION(glUniform4f),
6537 FUNCTION(glUniform4fv),
6538 FUNCTION(glUniform4i),
6539 FUNCTION(glUniform4iv),
6540 FUNCTION(glUniform4ui),
6541 FUNCTION(glUniform4uiv),
6542 FUNCTION(glUniformBlockBinding),
6543 FUNCTION(glUniformMatrix2fv),
6544 FUNCTION(glUniformMatrix2x3fv),
6545 FUNCTION(glUniformMatrix2x4fv),
6546 FUNCTION(glUniformMatrix3fv),
6547 FUNCTION(glUniformMatrix3x2fv),
6548 FUNCTION(glUniformMatrix3x4fv),
6549 FUNCTION(glUniformMatrix4fv),
6550 FUNCTION(glUniformMatrix4x2fv),
6551 FUNCTION(glUniformMatrix4x3fv),
6552 FUNCTION(glUnmapBuffer),
6553 FUNCTION(glUseProgram),
6554 FUNCTION(glValidateProgram),
6555 FUNCTION(glVertexAttrib1f),
6556 FUNCTION(glVertexAttrib1fv),
6557 FUNCTION(glVertexAttrib2f),
6558 FUNCTION(glVertexAttrib2fv),
6559 FUNCTION(glVertexAttrib3f),
6560 FUNCTION(glVertexAttrib3fv),
6561 FUNCTION(glVertexAttrib4f),
6562 FUNCTION(glVertexAttrib4fv),
6563 FUNCTION(glVertexAttribDivisor),
Adrienne Walker050ef942018-06-20 15:43:05 -07006564 FUNCTION(glVertexAttribDivisorANGLE),
6565 FUNCTION(glVertexAttribDivisorEXT),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006566 FUNCTION(glVertexAttribI4i),
6567 FUNCTION(glVertexAttribI4iv),
6568 FUNCTION(glVertexAttribI4ui),
6569 FUNCTION(glVertexAttribI4uiv),
6570 FUNCTION(glVertexAttribIPointer),
6571 FUNCTION(glVertexAttribPointer),
6572 FUNCTION(glViewport),
6573 FUNCTION(glWaitSync),
6574
6575 #undef FUNCTION
6576 };
6577
6578 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
6579 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
6580
Nicolas Capens48908cb2018-01-08 13:07:14 -05006581 // The array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6582 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6583 #ifndef NDEBUG
6584 for(size_t i = 0; i < numFunctions - 1; i++)
6585 {
6586 ASSERT(strcmp(glFunctions[i].name, glFunctions[i + 1].name) < 0);
6587 }
6588 #endif
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006589
6590 if(procname && strncmp("gl", procname, 2) == 0)
6591 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05006592 struct CompareFunctor
6593 {
6594 bool operator()(const Function &a, const Function &b) const
6595 {
6596 return strcmp(a.name, b.name) < 0;
6597 }
6598 };
6599
6600 Function needle;
6601 needle.name = procname;
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006602 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
Nicolas Capens48908cb2018-01-08 13:07:14 -05006603
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006604 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006605 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006606 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006607 }
6608 }
6609
6610 return nullptr;
6611}